aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2010-12-18 10:44:00 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-01-12 20:02:43 -0500
commit3d23985d6cfa7908e46fd0c62a2ee84faffe4d8b (patch)
tree5561a4f3eb3ef265de2b6d224194ff58b713fe0a
parent6cc9c1d2c1414ef67f465462aa96a5d1fed12f5d (diff)
switch fat to ->s_d_op, close exportfs races there
don't bother with lock_super() in fat_fill_super() callers, while we are at it - there won't be any concurrency anyway. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/fat/fat.h3
-rw-r--r--fs/fat/inode.c13
-rw-r--r--fs/fat/namei_msdos.c27
-rw-r--r--fs/fat/namei_vfat.c27
4 files changed, 25 insertions, 45 deletions
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index d75a77f85c28..f50408901f7e 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -319,7 +319,8 @@ extern struct inode *fat_build_inode(struct super_block *sb,
319 struct msdos_dir_entry *de, loff_t i_pos); 319 struct msdos_dir_entry *de, loff_t i_pos);
320extern int fat_sync_inode(struct inode *inode); 320extern int fat_sync_inode(struct inode *inode);
321extern int fat_fill_super(struct super_block *sb, void *data, int silent, 321extern int fat_fill_super(struct super_block *sb, void *data, int silent,
322 const struct inode_operations *fs_dir_inode_ops, int isvfat); 322 const struct inode_operations *fs_dir_inode_ops,
323 int isvfat, void (*setup)(struct super_block *));
323 324
324extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, 325extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
325 struct inode *i2); 326 struct inode *i2);
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 206351af7c58..86753fe10bd1 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -703,7 +703,6 @@ static struct dentry *fat_fh_to_dentry(struct super_block *sb,
703 struct fid *fid, int fh_len, int fh_type) 703 struct fid *fid, int fh_len, int fh_type)
704{ 704{
705 struct inode *inode = NULL; 705 struct inode *inode = NULL;
706 struct dentry *result;
707 u32 *fh = fid->raw; 706 u32 *fh = fid->raw;
708 707
709 if (fh_len < 5 || fh_type != 3) 708 if (fh_len < 5 || fh_type != 3)
@@ -748,10 +747,7 @@ static struct dentry *fat_fh_to_dentry(struct super_block *sb,
748 * the fat_iget lookup again. If that fails, then we are totally out 747 * the fat_iget lookup again. If that fails, then we are totally out
749 * of luck. But all that is for another day 748 * of luck. But all that is for another day
750 */ 749 */
751 result = d_obtain_alias(inode); 750 return d_obtain_alias(inode);
752 if (!IS_ERR(result))
753 d_set_d_op(result, sb->s_root->d_op);
754 return result;
755} 751}
756 752
757static int 753static int
@@ -799,8 +795,6 @@ static struct dentry *fat_get_parent(struct dentry *child)
799 brelse(bh); 795 brelse(bh);
800 796
801 parent = d_obtain_alias(inode); 797 parent = d_obtain_alias(inode);
802 if (!IS_ERR(parent))
803 d_set_d_op(parent, sb->s_root->d_op);
804out: 798out:
805 unlock_super(sb); 799 unlock_super(sb);
806 800
@@ -1244,7 +1238,8 @@ static int fat_read_root(struct inode *inode)
1244 * Read the super block of an MS-DOS FS. 1238 * Read the super block of an MS-DOS FS.
1245 */ 1239 */
1246int fat_fill_super(struct super_block *sb, void *data, int silent, 1240int fat_fill_super(struct super_block *sb, void *data, int silent,
1247 const struct inode_operations *fs_dir_inode_ops, int isvfat) 1241 const struct inode_operations *fs_dir_inode_ops, int isvfat,
1242 void (*setup)(struct super_block *))
1248{ 1243{
1249 struct inode *root_inode = NULL, *fat_inode = NULL; 1244 struct inode *root_inode = NULL, *fat_inode = NULL;
1250 struct buffer_head *bh; 1245 struct buffer_head *bh;
@@ -1280,6 +1275,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
1280 if (error) 1275 if (error)
1281 goto out_fail; 1276 goto out_fail;
1282 1277
1278 setup(sb); /* flavour-specific stuff that needs options */
1279
1283 error = -EIO; 1280 error = -EIO;
1284 sb_min_blocksize(sb, 512); 1281 sb_min_blocksize(sb, 512);
1285 bh = sb_bread(sb, 0); 1282 bh = sb_bread(sb, 0);
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 35ffe43afa4b..711499040eb6 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -227,11 +227,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
227 } 227 }
228out: 228out:
229 unlock_super(sb); 229 unlock_super(sb);
230 d_set_d_op(dentry, &msdos_dentry_operations); 230 return d_splice_alias(inode, dentry);
231 dentry = d_splice_alias(inode, dentry);
232 if (dentry)
233 d_set_d_op(dentry, &msdos_dentry_operations);
234 return dentry;
235 231
236error: 232error:
237 unlock_super(sb); 233 unlock_super(sb);
@@ -661,21 +657,16 @@ static const struct inode_operations msdos_dir_inode_operations = {
661 .getattr = fat_getattr, 657 .getattr = fat_getattr,
662}; 658};
663 659
664static int msdos_fill_super(struct super_block *sb, void *data, int silent) 660static void setup(struct super_block *sb)
665{ 661{
666 int res; 662 sb->s_d_op = &msdos_dentry_operations;
667
668 lock_super(sb);
669 res = fat_fill_super(sb, data, silent, &msdos_dir_inode_operations, 0);
670 if (res) {
671 unlock_super(sb);
672 return res;
673 }
674
675 sb->s_flags |= MS_NOATIME; 663 sb->s_flags |= MS_NOATIME;
676 d_set_d_op(sb->s_root, &msdos_dentry_operations); 664}
677 unlock_super(sb); 665
678 return 0; 666static int msdos_fill_super(struct super_block *sb, void *data, int silent)
667{
668 return fat_fill_super(sb, data, silent, &msdos_dir_inode_operations,
669 0, setup);
679} 670}
680 671
681static struct dentry *msdos_mount(struct file_system_type *fs_type, 672static struct dentry *msdos_mount(struct file_system_type *fs_type,
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index e3ffc5e12332..f88f752babd9 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -772,13 +772,10 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
772 772
773out: 773out:
774 unlock_super(sb); 774 unlock_super(sb);
775 d_set_d_op(dentry, sb->s_root->d_op);
776 dentry->d_time = dentry->d_parent->d_inode->i_version; 775 dentry->d_time = dentry->d_parent->d_inode->i_version;
777 dentry = d_splice_alias(inode, dentry); 776 dentry = d_splice_alias(inode, dentry);
778 if (dentry) { 777 if (dentry)
779 d_set_d_op(dentry, sb->s_root->d_op);
780 dentry->d_time = dentry->d_parent->d_inode->i_version; 778 dentry->d_time = dentry->d_parent->d_inode->i_version;
781 }
782 return dentry; 779 return dentry;
783 780
784error: 781error:
@@ -1066,24 +1063,18 @@ static const struct inode_operations vfat_dir_inode_operations = {
1066 .getattr = fat_getattr, 1063 .getattr = fat_getattr,
1067}; 1064};
1068 1065
1069static int vfat_fill_super(struct super_block *sb, void *data, int silent) 1066static void setup(struct super_block *sb)
1070{ 1067{
1071 int res;
1072
1073 lock_super(sb);
1074 res = fat_fill_super(sb, data, silent, &vfat_dir_inode_operations, 1);
1075 if (res) {
1076 unlock_super(sb);
1077 return res;
1078 }
1079
1080 if (MSDOS_SB(sb)->options.name_check != 's') 1068 if (MSDOS_SB(sb)->options.name_check != 's')
1081 d_set_d_op(sb->s_root, &vfat_ci_dentry_ops); 1069 sb->s_d_op = &vfat_ci_dentry_ops;
1082 else 1070 else
1083 d_set_d_op(sb->s_root, &vfat_dentry_ops); 1071 sb->s_d_op = &vfat_dentry_ops;
1072}
1084 1073
1085 unlock_super(sb); 1074static int vfat_fill_super(struct super_block *sb, void *data, int silent)
1086 return 0; 1075{
1076 return fat_fill_super(sb, data, silent, &vfat_dir_inode_operations,
1077 1, setup);
1087} 1078}
1088 1079
1089static struct dentry *vfat_mount(struct file_system_type *fs_type, 1080static struct dentry *vfat_mount(struct file_system_type *fs_type,