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.
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.
14 #include <linux/exportfs.h>
26 * Look up a directory inode given its starting cluster.
28 static struct inode *fat_dget(struct super_block *sb, int i_logstart)
30 struct msdos_sb_info *sbi = MSDOS_SB(sb);
31 struct hlist_head *head;
32 struct hlist_node *_p;
33 struct msdos_inode_info *i;
34 struct inode *inode = NULL;
36 head = sbi->dir_hashtable + fat_dir_hash(i_logstart);
37 spin_lock(&sbi->dir_hash_lock);
38 hlist_for_each_entry(i, _p, head, i_dir_hash) {
39 BUG_ON(i->vfs_inode.i_sb != sb);
40 if (i->i_logstart != i_logstart)
42 inode = igrab(&i->vfs_inode);
46 spin_unlock(&sbi->dir_hash_lock);
50 static struct inode *fat_nfs_get_inode(struct super_block *sb,
51 u64 ino, u32 generation, loff_t i_pos)
55 if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
58 inode = ilookup(sb, ino);
59 if (inode && generation && (inode->i_generation != generation)) {
63 if (inode == NULL && MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO) {
64 struct buffer_head *bh = NULL;
65 struct msdos_dir_entry *de ;
68 fat_get_blknr_offset(MSDOS_SB(sb), i_pos, &blocknr, &offset);
69 bh = sb_bread(sb, blocknr);
72 "unable to read block(%llu) for building NFS inode",
76 de = (struct msdos_dir_entry *)bh->b_data;
77 /* If a file is deleted on server and client is not updated
78 * yet, we must not build the inode upon a lookup call.
80 if (IS_FREE(de[offset].name))
83 inode = fat_build_inode(sb, &de[offset], i_pos);
92 fat_encode_fh(struct inode *inode, __u32 *fh, int *lenp, struct inode *parent)
95 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
96 struct fat_fid *fid = (struct fat_fid *) fh;
98 int type = FILEID_INO32_GEN;
100 if (parent && (len < 5)) {
103 } else if (len < 3) {
108 i_pos = fat_i_pos_read(sbi, inode);
110 fid->ino = inode->i_ino;
111 fid->gen = inode->i_generation;
114 fid->parent_ino = parent->i_ino;
115 fid->parent_gen = parent->i_generation;
116 type = FILEID_INO32_GEN_PARENT;
124 * Map a NFS file handle to a corresponding dentry.
125 * The dentry may or may not be connected to the filesystem root.
127 struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fh,
128 int fh_len, int fh_type)
130 struct inode *inode = NULL;
131 struct fat_fid *fid = (struct fat_fid *)fh;
136 case FILEID_INO32_GEN:
137 case FILEID_INO32_GEN_PARENT:
138 inode = fat_nfs_get_inode(sb, fid->ino, fid->gen, fid->i_pos);
143 return d_obtain_alias(inode);
147 * Find the parent for a file specified by NFS handle.
148 * This requires that the handle contain the i_ino of the parent.
150 struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fh,
151 int fh_len, int fh_type)
153 struct inode *inode = NULL;
154 struct fat_fid *fid = (struct fat_fid *)fh;
159 case FILEID_INO32_GEN_PARENT:
160 inode = fat_nfs_get_inode(sb, fid->parent_ino, fid->parent_gen,
165 return d_obtain_alias(inode);
169 * Find the parent for a directory that is not currently connected to
170 * the filesystem root.
172 * On entry, the caller holds child_dir->d_inode->i_mutex.
174 struct dentry *fat_get_parent(struct dentry *child_dir)
176 struct super_block *sb = child_dir->d_sb;
177 struct buffer_head *bh = NULL;
178 struct msdos_dir_entry *de;
179 struct inode *parent_inode = NULL;
181 if (!fat_get_dotdot_entry(child_dir->d_inode, &bh, &de)) {
182 int parent_logstart = fat_get_start(MSDOS_SB(sb), de);
183 parent_inode = fat_dget(sb, parent_logstart);
187 return d_obtain_alias(parent_inode);