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 #define FILEID_FAT_WITHOUT_PARENT (offsetof(struct fat_fid, parent_i_pos_hi)/4)
27 #define FILEID_FAT_WITH_PARENT (sizeof(struct fat_fid)/4)
30 * Look up a directory inode given its starting cluster.
32 static struct inode *fat_dget(struct super_block *sb, int i_logstart)
34 struct msdos_sb_info *sbi = MSDOS_SB(sb);
35 struct hlist_head *head;
36 struct hlist_node *_p;
37 struct msdos_inode_info *i;
38 struct inode *inode = NULL;
40 head = sbi->dir_hashtable + fat_dir_hash(i_logstart);
41 spin_lock(&sbi->dir_hash_lock);
42 hlist_for_each_entry(i, _p, head, i_dir_hash) {
43 BUG_ON(i->vfs_inode.i_sb != sb);
44 if (i->i_logstart != i_logstart)
46 inode = igrab(&i->vfs_inode);
50 spin_unlock(&sbi->dir_hash_lock);
54 static struct inode *fat_ilookup(struct super_block *sb, u64 ino, loff_t i_pos)
56 if (MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO)
57 return fat_iget(sb, i_pos);
60 if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
62 return ilookup(sb, ino);
66 static struct inode *fat_nfs_get_inode(struct super_block *sb,
67 u64 ino, u32 generation, loff_t i_pos)
70 struct inode *inode = fat_ilookup(sb, ino, i_pos);
72 if (inode && generation && (inode->i_generation != generation)) {
76 if (inode == NULL && MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO) {
77 struct buffer_head *bh = NULL;
78 struct msdos_dir_entry *de ;
81 fat_get_blknr_offset(MSDOS_SB(sb), i_pos, &blocknr, &offset);
82 bh = sb_bread(sb, blocknr);
85 "unable to read block(%llu) for building NFS inode",
89 de = (struct msdos_dir_entry *)bh->b_data;
90 /* If a file is deleted on server and client is not updated
91 * yet, we must not build the inode upon a lookup call.
93 if (IS_FREE(de[offset].name))
96 inode = fat_build_inode(sb, &de[offset], i_pos);
105 fat_encode_fh_nostale(struct inode *inode, __u32 *fh, int *lenp,
106 struct inode *parent)
109 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
110 struct fat_fid *fid = (struct fat_fid *) fh;
112 int type = FILEID_INO32_GEN;
114 if (parent && (len < FILEID_FAT_WITH_PARENT)) {
115 *lenp = FILEID_FAT_WITH_PARENT;
117 } else if (len < FILEID_FAT_WITHOUT_PARENT) {
118 *lenp = FILEID_FAT_WITHOUT_PARENT;
122 i_pos = fat_i_pos_read(sbi, inode);
123 *lenp = FILEID_FAT_WITHOUT_PARENT;
124 fid->i_gen = inode->i_generation;
125 fid->i_pos_low = i_pos & 0xFFFFFFFF;
126 fid->i_pos_hi = (i_pos >> 32) & 0xFF;
128 i_pos = fat_i_pos_read(sbi, parent);
129 fid->parent_i_pos_hi = (i_pos >> 32) & 0xFF;
130 fid->parent_i_pos_low = i_pos & 0xFFFFFFFF;
131 fid->parent_i_gen = parent->i_generation;
132 type = FILEID_INO32_GEN_PARENT;
133 *lenp = FILEID_FAT_WITH_PARENT;
140 * Map a NFS file handle to a corresponding dentry.
141 * The dentry may or may not be connected to the filesystem root.
143 struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fh,
144 int fh_len, int fh_type)
146 struct inode *inode = NULL;
151 case FILEID_INO32_GEN:
152 case FILEID_INO32_GEN_PARENT:
153 inode = fat_nfs_get_inode(sb, fh->i32.ino, fh->i32.gen, 0);
157 return d_obtain_alias(inode);
159 struct dentry *fat_fh_to_dentry_nostale(struct super_block *sb, struct fid *fh,
160 int fh_len, int fh_type)
162 struct inode *inode = NULL;
163 struct fat_fid *fid = (struct fat_fid *)fh;
167 case FILEID_INO32_GEN:
168 if (fh_len < FILEID_FAT_WITHOUT_PARENT)
170 case FILEID_INO32_GEN_PARENT:
171 if ((fh_len < FILEID_FAT_WITH_PARENT) &&
172 (fh_type == FILEID_INO32_GEN_PARENT))
174 i_pos = fid->i_pos_hi;
175 i_pos = (i_pos << 32) | (fid->i_pos_low);
176 inode = fat_nfs_get_inode(sb, 0, fid->i_gen, i_pos);
181 return d_obtain_alias(inode);
185 * Find the parent for a file specified by NFS handle.
186 * This requires that the handle contain the i_ino of the parent.
188 struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
189 int fh_len, int fh_type)
191 struct inode *inode = NULL;
197 case FILEID_INO32_GEN:
198 case FILEID_INO32_GEN_PARENT:
199 inode = fat_nfs_get_inode(sb, fid->i32.ino, fid->i32.gen, 0);
203 return d_obtain_alias(inode);
206 struct dentry *fat_fh_to_parent_nostale(struct super_block *sb, struct fid *fh,
207 int fh_len, int fh_type)
209 struct inode *inode = NULL;
210 struct fat_fid *fid = (struct fat_fid *)fh;
213 if (fh_len < FILEID_FAT_WITH_PARENT)
217 case FILEID_INO32_GEN_PARENT:
218 i_pos = fid->parent_i_pos_hi;
219 i_pos = (i_pos << 32) | (fid->parent_i_pos_low);
220 inode = fat_nfs_get_inode(sb, 0, fid->parent_i_gen, i_pos);
224 return d_obtain_alias(inode);
228 * Read the directory entries of 'search_clus' and find the entry
229 * which contains 'match_ipos' for the starting cluster.If the entry
230 * is found, rebuild its inode.
232 static struct inode *fat_traverse_cluster(struct super_block *sb,
233 int search_clus, int match_ipos)
235 struct msdos_sb_info *sbi = MSDOS_SB(sb);
236 struct buffer_head *bh;
238 int parent_ipos, search_ipos;
240 struct msdos_dir_entry *de;
241 struct inode *inode = NULL;
242 int iterations = sbi->cluster_size >> sb->s_blocksize_bits;
243 blknr = fat_clus_to_blknr(sbi, search_clus);
246 bh = sb_bread(sb, blknr);
248 fat_msg(sb, KERN_ERR,
249 "NFS:unable to read block(%llu) while traversing cluster(%d)",
250 (llu)blknr, search_clus);
251 inode = ERR_PTR(-EIO);
254 de = (struct msdos_dir_entry *)bh->b_data;
255 for (i = 0; i < sbi->dir_per_block; i++) {
256 if (de[i].name[0] == FAT_ENT_FREE) {
257 /*Reached end of directory*/
259 inode = ERR_PTR(-ENODATA);
262 if (de[i].name[0] == DELETED_FLAG)
264 if (de[i].attr == ATTR_EXT)
266 if (!(de[i].attr & ATTR_DIR))
269 search_ipos = fat_get_start(sbi, &de[i]);
270 if (search_ipos == match_ipos) {
271 /*Success.Now build the inode*/
272 parent_ipos = (loff_t)i +
273 (blknr << sbi->dir_per_block_bits);
274 inode = fat_build_inode(sb, &de[i],
283 } while (--iterations > 0);
289 * Read the FAT to find the next cluster in the chain
290 * corresponding to 'search_clus'.
292 static int fat_read_next_clus(struct super_block *sb, int search_clus)
294 struct msdos_sb_info *sbi = MSDOS_SB(sb);
295 /*bits 31 to 7 give relative sector number*/
296 sector_t blknr = search_clus >> 7;
297 /*bits 6 to 0 give offset*/
298 unsigned int offset = search_clus & 0x7F;
300 unsigned int next_cluster;
301 struct buffer_head *bh = sb_bread(sb, blknr + sbi->fat_start);
303 fat_msg(sb, KERN_ERR,
304 "NFS:unable to read block(%llu) for finding the next cluster in FAT chain",
308 address = (__le32 *) bh->b_data;
309 next_cluster = (le32_to_cpu(address[offset])) & 0x0FFFFFFF;
315 * Rebuild the parent for a directory that is not connected
316 * to the filesystem root
319 struct inode *fat_rebuild_parent(struct super_block *sb, int parent_logstart)
321 int search_clus, clus_to_match;
322 struct msdos_dir_entry *de;
323 struct inode *parent;
324 struct msdos_sb_info *sbi = MSDOS_SB(sb);
325 sector_t blknr = fat_clus_to_blknr(sbi, parent_logstart);
326 struct buffer_head *parent_bh = sb_bread(sb, blknr);
329 fat_msg(sb, KERN_ERR,
330 "NFS:unable to read cluster of parent directory");
333 de = (struct msdos_dir_entry *) parent_bh->b_data;
334 clus_to_match = fat_get_start(sbi, &de[0]);
335 search_clus = fat_get_start(sbi, &de[1]);
337 search_clus = sbi->root_cluster;
340 parent = fat_traverse_cluster(sb,
341 search_clus, clus_to_match);
342 if (IS_ERR(parent) || parent)
344 search_clus = fat_read_next_clus(sb, search_clus);
347 } while (search_clus != FAT_ENT_EOF);
354 * Find the parent for a directory that is not currently connected to
355 * the filesystem root.
357 * On entry, the caller holds child_dir->d_inode->i_mutex.
359 struct dentry *fat_get_parent(struct dentry *child_dir)
361 struct super_block *sb = child_dir->d_sb;
362 struct buffer_head *dotdot_bh = NULL;
363 struct msdos_dir_entry *de;
364 struct inode *parent_inode = NULL;
365 struct msdos_sb_info *sbi = MSDOS_SB(sb);
368 if (!fat_get_dotdot_entry(child_dir->d_inode, &dotdot_bh, &de)) {
369 parent_logstart = fat_get_start(sbi, de);
370 parent_inode = fat_dget(sb, parent_logstart);
371 if (!parent_inode && sbi->options.nfs == FAT_NFS_NOSTALE_RO)
372 parent_inode = fat_rebuild_parent(sb, parent_logstart);
376 return d_obtain_alias(parent_inode);
379 const struct export_operations fat_export_ops = {
380 .fh_to_dentry = fat_fh_to_dentry,
381 .fh_to_parent = fat_fh_to_parent,
382 .get_parent = fat_get_parent,
384 const struct export_operations fat_export_ops_nostale = {
385 .encode_fh = fat_encode_fh_nostale,
386 .fh_to_dentry = fat_fh_to_dentry_nostale,
387 .fh_to_parent = fat_fh_to_parent_nostale,
388 .get_parent = fat_get_parent,