]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
fat: add mutex lock to fat_build_inode
authorNamjae Jeon <namjae.jeon@samsung.com>
Sat, 3 Nov 2012 00:43:00 +0000 (11:43 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Tue, 6 Nov 2012 04:58:44 +0000 (15:58 +1100)
fat_nfs_get_inode() does not hold i_mutex of parent directory.  So add
lock to fat_build_inode().

We are making use of fat_build_inode to build the inode using 'i_pos'.
Since, this function is local to FAT and when mounted over NFS. We can
make use of FAT parallely from local NFS Server and mounted from NFS
client. So, in order to avoid race to multiple regeneration for the
same 'i_pos' - we have introduced this locking.

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>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
fs/fat/fat.h
fs/fat/inode.c

index 177e94e5127719fbfd1621a6bee57b7fe671c57f..811267c31f5b1c3dc4c126c5d86be0f0fe4a03d4 100644 (file)
@@ -75,6 +75,7 @@ struct msdos_sb_info {
        unsigned long fsinfo_sector;  /* sector number of FAT32 fsinfo */
        struct mutex fat_lock;
        struct mutex s_lock;
+       struct mutex nfs_build_inode_lock;
        unsigned int prev_free;      /* previously allocated cluster number */
        unsigned int free_clusters;  /* -1 if undefined */
        unsigned int free_clus_valid; /* is free_clusters valid? */
index 63e08839984c946e71e82288ec76f67c9e67ee04..a1650ef096cec82fc62e7dd95e7076c2082158cd 100644 (file)
@@ -443,12 +443,25 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
        return 0;
 }
 
+static inline void fat_lock_build_inode(struct msdos_sb_info *sbi)
+{
+       if (sbi->options.nfs == FAT_NFS_NOSTALE_RO)
+               mutex_lock(&sbi->nfs_build_inode_lock);
+}
+
+static inline void fat_unlock_build_inode(struct msdos_sb_info *sbi)
+{
+       if (sbi->options.nfs == FAT_NFS_NOSTALE_RO)
+               mutex_unlock(&sbi->nfs_build_inode_lock);
+}
+
 struct inode *fat_build_inode(struct super_block *sb,
                        struct msdos_dir_entry *de, loff_t i_pos)
 {
        struct inode *inode;
        int err;
 
+       fat_lock_build_inode(MSDOS_SB(sb));
        inode = fat_iget(sb, i_pos);
        if (inode)
                goto out;
@@ -468,6 +481,7 @@ struct inode *fat_build_inode(struct super_block *sb,
        fat_attach(inode, i_pos);
        insert_inode_hash(inode);
 out:
+       fat_unlock_build_inode(MSDOS_SB(sb));
        return inode;
 }
 
@@ -1173,6 +1187,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
        sb->s_magic = MSDOS_SUPER_MAGIC;
        sb->s_op = &fat_sops;
        sb->s_export_op = &fat_export_ops;
+       mutex_init(&sbi->nfs_build_inode_lock);
        ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
                             DEFAULT_RATELIMIT_BURST);