switch fat to ->s_d_op, close exportfs races there
Al Viro [Sat, 18 Dec 2010 15:44:00 +0000 (10:44 -0500)]
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>

fs/fat/fat.h
fs/fat/inode.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c

index d75a77f..f504089 100644 (file)
@@ -319,7 +319,8 @@ extern struct inode *fat_build_inode(struct super_block *sb,
                        struct msdos_dir_entry *de, loff_t i_pos);
 extern int fat_sync_inode(struct inode *inode);
 extern int fat_fill_super(struct super_block *sb, void *data, int silent,
-                       const struct inode_operations *fs_dir_inode_ops, int isvfat);
+                       const struct inode_operations *fs_dir_inode_ops,
+                       int isvfat, void (*setup)(struct super_block *));
 
 extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
                            struct inode *i2);
index 206351a..86753fe 100644 (file)
@@ -703,7 +703,6 @@ static struct dentry *fat_fh_to_dentry(struct super_block *sb,
                struct fid *fid, int fh_len, int fh_type)
 {
        struct inode *inode = NULL;
-       struct dentry *result;
        u32 *fh = fid->raw;
 
        if (fh_len < 5 || fh_type != 3)
@@ -748,10 +747,7 @@ static struct dentry *fat_fh_to_dentry(struct super_block *sb,
         * the fat_iget lookup again.  If that fails, then we are totally out
         * of luck.  But all that is for another day
         */
-       result = d_obtain_alias(inode);
-       if (!IS_ERR(result))
-               d_set_d_op(result, sb->s_root->d_op);
-       return result;
+       return d_obtain_alias(inode);
 }
 
 static int
@@ -799,8 +795,6 @@ static struct dentry *fat_get_parent(struct dentry *child)
        brelse(bh);
 
        parent = d_obtain_alias(inode);
-       if (!IS_ERR(parent))
-               d_set_d_op(parent, sb->s_root->d_op);
 out:
        unlock_super(sb);
 
@@ -1244,7 +1238,8 @@ static int fat_read_root(struct inode *inode)
  * Read the super block of an MS-DOS FS.
  */
 int fat_fill_super(struct super_block *sb, void *data, int silent,
-                  const struct inode_operations *fs_dir_inode_ops, int isvfat)
+                  const struct inode_operations *fs_dir_inode_ops, int isvfat,
+                  void (*setup)(struct super_block *))
 {
        struct inode *root_inode = NULL, *fat_inode = NULL;
        struct buffer_head *bh;
@@ -1280,6 +1275,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        if (error)
                goto out_fail;
 
+       setup(sb); /* flavour-specific stuff that needs options */
+
        error = -EIO;
        sb_min_blocksize(sb, 512);
        bh = sb_bread(sb, 0);
index 35ffe43..7114990 100644 (file)
@@ -227,11 +227,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
        }
 out:
        unlock_super(sb);
-       d_set_d_op(dentry, &msdos_dentry_operations);
-       dentry = d_splice_alias(inode, dentry);
-       if (dentry)
-               d_set_d_op(dentry, &msdos_dentry_operations);
-       return dentry;
+       return d_splice_alias(inode, dentry);
 
 error:
        unlock_super(sb);
@@ -661,21 +657,16 @@ static const struct inode_operations msdos_dir_inode_operations = {
        .getattr        = fat_getattr,
 };
 
-static int msdos_fill_super(struct super_block *sb, void *data, int silent)
+static void setup(struct super_block *sb)
 {
-       int res;
-
-       lock_super(sb);
-       res = fat_fill_super(sb, data, silent, &msdos_dir_inode_operations, 0);
-       if (res) {
-               unlock_super(sb);
-               return res;
-       }
-
+       sb->s_d_op = &msdos_dentry_operations;
        sb->s_flags |= MS_NOATIME;
-       d_set_d_op(sb->s_root, &msdos_dentry_operations);
-       unlock_super(sb);
-       return 0;
+}
+
+static int msdos_fill_super(struct super_block *sb, void *data, int silent)
+{
+       return fat_fill_super(sb, data, silent, &msdos_dir_inode_operations,
+                            0, setup);
 }
 
 static struct dentry *msdos_mount(struct file_system_type *fs_type,
index e3ffc5e..f88f752 100644 (file)
@@ -772,13 +772,10 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
 
 out:
        unlock_super(sb);
-       d_set_d_op(dentry, sb->s_root->d_op);
        dentry->d_time = dentry->d_parent->d_inode->i_version;
        dentry = d_splice_alias(inode, dentry);
-       if (dentry) {
-               d_set_d_op(dentry, sb->s_root->d_op);
+       if (dentry)
                dentry->d_time = dentry->d_parent->d_inode->i_version;
-       }
        return dentry;
 
 error:
@@ -1066,24 +1063,18 @@ static const struct inode_operations vfat_dir_inode_operations = {
        .getattr        = fat_getattr,
 };
 
-static int vfat_fill_super(struct super_block *sb, void *data, int silent)
+static void setup(struct super_block *sb)
 {
-       int res;
-
-       lock_super(sb);
-       res = fat_fill_super(sb, data, silent, &vfat_dir_inode_operations, 1);
-       if (res) {
-               unlock_super(sb);
-               return res;
-       }
-
        if (MSDOS_SB(sb)->options.name_check != 's')
-               d_set_d_op(sb->s_root, &vfat_ci_dentry_ops);
+               sb->s_d_op = &vfat_ci_dentry_ops;
        else
-               d_set_d_op(sb->s_root, &vfat_dentry_ops);
+               sb->s_d_op = &vfat_dentry_ops;
+}
 
-       unlock_super(sb);
-       return 0;
+static int vfat_fill_super(struct super_block *sb, void *data, int silent)
+{
+       return fat_fill_super(sb, data, silent, &vfat_dir_inode_operations,
+                            1, setup);
 }
 
 static struct dentry *vfat_mount(struct file_system_type *fs_type,