linux/fs/fat/nfs.c
<<
>>
Prefs
   1/* fs/fat/nfs.c
   2 *
   3 * This software is licensed under the terms of the GNU General Public
   4 * License version 2, as published by the Free Software Foundation, and
   5 * may be copied, distributed, and modified under those terms.
   6 *
   7 * This program is distributed in the hope that it will be useful,
   8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10 * GNU General Public License for more details.
  11 *
  12 */
  13
  14#include <linux/exportfs.h>
  15#include "fat.h"
  16
  17/**
  18 * Look up a directory inode given its starting cluster.
  19 */
  20static struct inode *fat_dget(struct super_block *sb, int i_logstart)
  21{
  22        struct msdos_sb_info *sbi = MSDOS_SB(sb);
  23        struct hlist_head *head;
  24        struct hlist_node *_p;
  25        struct msdos_inode_info *i;
  26        struct inode *inode = NULL;
  27
  28        head = sbi->dir_hashtable + fat_dir_hash(i_logstart);
  29        spin_lock(&sbi->dir_hash_lock);
  30        hlist_for_each_entry(i, _p, head, i_dir_hash) {
  31                BUG_ON(i->vfs_inode.i_sb != sb);
  32                if (i->i_logstart != i_logstart)
  33                        continue;
  34                inode = igrab(&i->vfs_inode);
  35                if (inode)
  36                        break;
  37        }
  38        spin_unlock(&sbi->dir_hash_lock);
  39        return inode;
  40}
  41
  42static struct inode *fat_nfs_get_inode(struct super_block *sb,
  43                                       u64 ino, u32 generation)
  44{
  45        struct inode *inode;
  46
  47        if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
  48                return NULL;
  49
  50        inode = ilookup(sb, ino);
  51        if (inode && generation && (inode->i_generation != generation)) {
  52                iput(inode);
  53                inode = NULL;
  54        }
  55
  56        return inode;
  57}
  58
  59/**
  60 * Map a NFS file handle to a corresponding dentry.
  61 * The dentry may or may not be connected to the filesystem root.
  62 */
  63struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid,
  64                                int fh_len, int fh_type)
  65{
  66        return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
  67                                    fat_nfs_get_inode);
  68}
  69
  70/*
  71 * Find the parent for a file specified by NFS handle.
  72 * This requires that the handle contain the i_ino of the parent.
  73 */
  74struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
  75                                int fh_len, int fh_type)
  76{
  77        return generic_fh_to_parent(sb, fid, fh_len, fh_type,
  78                                    fat_nfs_get_inode);
  79}
  80
  81/*
  82 * Find the parent for a directory that is not currently connected to
  83 * the filesystem root.
  84 *
  85 * On entry, the caller holds child_dir->d_inode->i_mutex.
  86 */
  87struct dentry *fat_get_parent(struct dentry *child_dir)
  88{
  89        struct super_block *sb = child_dir->d_sb;
  90        struct buffer_head *bh = NULL;
  91        struct msdos_dir_entry *de;
  92        struct inode *parent_inode = NULL;
  93
  94        if (!fat_get_dotdot_entry(child_dir->d_inode, &bh, &de)) {
  95                int parent_logstart = fat_get_start(MSDOS_SB(sb), de);
  96                parent_inode = fat_dget(sb, parent_logstart);
  97        }
  98        brelse(bh);
  99
 100        return d_obtain_alias(parent_inode);
 101}
 102
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.