From 00b6ce046d984e99e52af0d355e3703958154684 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Sat, 3 Nov 2012 11:43:00 +1100 Subject: [PATCH] fat: add mutex lock to fat_build_inode 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 Signed-off-by: Ravishankar N Signed-off-by: Amit Sahrawat Cc: OGAWA Hirofumi Cc: "J. Bruce Fields" Signed-off-by: Andrew Morton --- fs/fat/fat.h | 1 + fs/fat/inode.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 177e94e51277..811267c31f5b 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -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? */ diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 63e08839984c..a1650ef096ce 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -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); -- 2.39.5