Commit 8fceb4e0171f6bf64db756c65b2ce5f15aed8b4d

Authored by Namjae Jeon
Committed by Linus Torvalds
1 parent ea3983ace6

fat (exportfs): rebuild inode if ilookup() fails

If the cache lookups fail,use the i_pos value to find the directory entry
of the inode and rebuild the inode.Since this involves accessing the FAT
media, do this only if the nostale_ro nfs mount option is specified.

Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Ravishankar N <ravi.n1@samsung.com>
Signed-off-by: Amit Sahrawat <a.sahrawat@samsung.com>
Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 52 additions and 5 deletions Side-by-side Diff

... ... @@ -75,6 +75,7 @@
75 75 unsigned long root_cluster; /* first cluster of the root directory */
76 76 unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */
77 77 struct mutex fat_lock;
  78 + struct mutex nfs_build_inode_lock;
78 79 struct mutex s_lock;
79 80 unsigned int prev_free; /* previously allocated cluster number */
80 81 unsigned int free_clusters; /* -1 if undefined */
... ... @@ -443,12 +443,25 @@
443 443 return 0;
444 444 }
445 445  
  446 +static inline void fat_lock_build_inode(struct msdos_sb_info *sbi)
  447 +{
  448 + if (sbi->options.nfs == FAT_NFS_NOSTALE_RO)
  449 + mutex_lock(&sbi->nfs_build_inode_lock);
  450 +}
  451 +
  452 +static inline void fat_unlock_build_inode(struct msdos_sb_info *sbi)
  453 +{
  454 + if (sbi->options.nfs == FAT_NFS_NOSTALE_RO)
  455 + mutex_unlock(&sbi->nfs_build_inode_lock);
  456 +}
  457 +
446 458 struct inode *fat_build_inode(struct super_block *sb,
447 459 struct msdos_dir_entry *de, loff_t i_pos)
448 460 {
449 461 struct inode *inode;
450 462 int err;
451 463  
  464 + fat_lock_build_inode(MSDOS_SB(sb));
452 465 inode = fat_iget(sb, i_pos);
453 466 if (inode)
454 467 goto out;
... ... @@ -468,6 +481,7 @@
468 481 fat_attach(inode, i_pos);
469 482 insert_inode_hash(inode);
470 483 out:
  484 + fat_unlock_build_inode(MSDOS_SB(sb));
471 485 return inode;
472 486 }
473 487  
... ... @@ -1247,6 +1261,7 @@
1247 1261 sb->s_magic = MSDOS_SUPER_MAGIC;
1248 1262 sb->s_op = &fat_sops;
1249 1263 sb->s_export_op = &fat_export_ops;
  1264 + mutex_init(&sbi->nfs_build_inode_lock);
1250 1265 ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
1251 1266 DEFAULT_RATELIMIT_BURST);
1252 1267  
... ... @@ -50,18 +50,49 @@
50 50 return inode;
51 51 }
52 52  
  53 +static struct inode *fat_ilookup(struct super_block *sb, u64 ino, loff_t i_pos)
  54 +{
  55 + if (MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO)
  56 + return fat_iget(sb, i_pos);
  57 +
  58 + else {
  59 + if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
  60 + return NULL;
  61 + return ilookup(sb, ino);
  62 + }
  63 +}
  64 +
53 65 static struct inode *__fat_nfs_get_inode(struct super_block *sb,
54 66 u64 ino, u32 generation, loff_t i_pos)
55 67 {
56   - struct inode *inode;
  68 + struct inode *inode = fat_ilookup(sb, ino, i_pos);
57 69  
58   - if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
59   - return NULL;
60   -
61   - inode = ilookup(sb, ino);
62 70 if (inode && generation && (inode->i_generation != generation)) {
63 71 iput(inode);
64 72 inode = NULL;
  73 + }
  74 + if (inode == NULL && MSDOS_SB(sb)->options.nfs == FAT_NFS_NOSTALE_RO) {
  75 + struct buffer_head *bh = NULL;
  76 + struct msdos_dir_entry *de ;
  77 + sector_t blocknr;
  78 + int offset;
  79 + fat_get_blknr_offset(MSDOS_SB(sb), i_pos, &blocknr, &offset);
  80 + bh = sb_bread(sb, blocknr);
  81 + if (!bh) {
  82 + fat_msg(sb, KERN_ERR,
  83 + "unable to read block(%llu) for building NFS inode",
  84 + (llu)blocknr);
  85 + return inode;
  86 + }
  87 + de = (struct msdos_dir_entry *)bh->b_data;
  88 + /* If a file is deleted on server and client is not updated
  89 + * yet, we must not build the inode upon a lookup call.
  90 + */
  91 + if (IS_FREE(de[offset].name))
  92 + inode = NULL;
  93 + else
  94 + inode = fat_build_inode(sb, &de[offset], i_pos);
  95 + brelse(bh);
65 96 }
66 97  
67 98 return inode;