]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
btrfs: preparation to fixing mount/umount race
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 17 Nov 2011 06:00:31 +0000 (01:00 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 9 Jan 2012 00:33:22 +0000 (19:33 -0500)
We need fs_info and root to live until the moment when the victim
superblock leaves the list, so we need to postpone free_fs_info()
until after ->put_super().  The call is buried in close_ctree(),
though, so we need to lift it into the callers (including
btrfs_put_super()) first.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/btrfs/disk-io.c
fs/btrfs/super.c

index f99a099a7747fd4ff2b0584a3f689d33a52136ab..dcb5d949b54317a2470239e2251130777b153a85 100644 (file)
@@ -2424,6 +2424,7 @@ retry_root_backup:
                up_read(&fs_info->cleanup_work_sem);
                if (err) {
                        close_ctree(tree_root);
+                       free_fs_info(fs_info);
                        return ERR_PTR(err);
                }
        }
@@ -3059,8 +3060,6 @@ int close_ctree(struct btrfs_root *root)
        bdi_destroy(&fs_info->bdi);
        cleanup_srcu_struct(&fs_info->subvol_srcu);
 
-       free_fs_info(fs_info);
-
        return 0;
 }
 
index ae488aa1966a1b32d6a3c4438424eb690740d4c9..a3f435e5898758598a9b8906980a0e6952b299c0 100644 (file)
@@ -151,6 +151,7 @@ static void btrfs_put_super(struct super_block *sb)
        int ret;
 
        ret = close_ctree(root);
+       free_fs_info(root->fs_info);
        sb->s_fs_info = NULL;
 
        (void)ret; /* FIXME: need to fix VFS to return error? */
@@ -589,6 +590,7 @@ static int btrfs_fill_super(struct super_block *sb,
        struct inode *inode;
        struct dentry *root_dentry;
        struct btrfs_root *tree_root;
+       struct btrfs_fs_info *fs_info;
        struct btrfs_key key;
        int err;
 
@@ -609,12 +611,13 @@ static int btrfs_fill_super(struct super_block *sb,
                printk("btrfs: open_ctree failed\n");
                return PTR_ERR(tree_root);
        }
+       fs_info = tree_root->fs_info;
        sb->s_fs_info = tree_root;
 
        key.objectid = BTRFS_FIRST_FREE_OBJECTID;
        key.type = BTRFS_INODE_ITEM_KEY;
        key.offset = 0;
-       inode = btrfs_iget(sb, &key, tree_root->fs_info->fs_root, NULL);
+       inode = btrfs_iget(sb, &key, fs_info->fs_root, NULL);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                goto fail_close;
@@ -635,6 +638,7 @@ static int btrfs_fill_super(struct super_block *sb,
 
 fail_close:
        close_ctree(tree_root);
+       free_fs_info(fs_info);
        return err;
 }