diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-12-18 10:44:00 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-12 20:02:43 -0500 |
commit | 3d23985d6cfa7908e46fd0c62a2ee84faffe4d8b (patch) | |
tree | 5561a4f3eb3ef265de2b6d224194ff58b713fe0a | |
parent | 6cc9c1d2c1414ef67f465462aa96a5d1fed12f5d (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.h | 3 | ||||
-rw-r--r-- | fs/fat/inode.c | 13 | ||||
-rw-r--r-- | fs/fat/namei_msdos.c | 27 | ||||
-rw-r--r-- | fs/fat/namei_vfat.c | 27 |
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); |
320 | extern int fat_sync_inode(struct inode *inode); | 320 | extern int fat_sync_inode(struct inode *inode); |
321 | extern int fat_fill_super(struct super_block *sb, void *data, int silent, | 321 | extern 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 | ||
324 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, | 325 | extern 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 | ||
757 | static int | 753 | static 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); | ||
804 | out: | 798 | out: |
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 | */ |
1246 | int fat_fill_super(struct super_block *sb, void *data, int silent, | 1240 | int 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 | } |
228 | out: | 228 | out: |
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 | ||
236 | error: | 232 | error: |
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 | ||
664 | static int msdos_fill_super(struct super_block *sb, void *data, int silent) | 660 | static 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; | 666 | static 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 | ||
681 | static struct dentry *msdos_mount(struct file_system_type *fs_type, | 672 | static 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 | ||
773 | out: | 773 | out: |
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 | ||
784 | error: | 781 | error: |
@@ -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 | ||
1069 | static int vfat_fill_super(struct super_block *sb, void *data, int silent) | 1066 | static 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); | 1074 | static 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 | ||
1089 | static struct dentry *vfat_mount(struct file_system_type *fs_type, | 1080 | static struct dentry *vfat_mount(struct file_system_type *fs_type, |