aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-11-17 01:00:31 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-01-08 19:33:22 -0500
commit98c7089c769048f941bd5c5285287f8fc301f8b1 (patch)
tree3e31f46b43fb1b533dc720db7a9d84da3b148433 /fs
parent48fa57ac2c30a8a0b770b7ad50b4b30c1d12f005 (diff)
btrfs: preparation to fixing mount/umount race
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/disk-io.c3
-rw-r--r--fs/btrfs/super.c6
2 files changed, 6 insertions, 3 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index f99a099a774..dcb5d949b54 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2424,6 +2424,7 @@ retry_root_backup:
2424 up_read(&fs_info->cleanup_work_sem); 2424 up_read(&fs_info->cleanup_work_sem);
2425 if (err) { 2425 if (err) {
2426 close_ctree(tree_root); 2426 close_ctree(tree_root);
2427 free_fs_info(fs_info);
2427 return ERR_PTR(err); 2428 return ERR_PTR(err);
2428 } 2429 }
2429 } 2430 }
@@ -3059,8 +3060,6 @@ int close_ctree(struct btrfs_root *root)
3059 bdi_destroy(&fs_info->bdi); 3060 bdi_destroy(&fs_info->bdi);
3060 cleanup_srcu_struct(&fs_info->subvol_srcu); 3061 cleanup_srcu_struct(&fs_info->subvol_srcu);
3061 3062
3062 free_fs_info(fs_info);
3063
3064 return 0; 3063 return 0;
3065} 3064}
3066 3065
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index ae488aa1966..a3f435e5898 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -151,6 +151,7 @@ static void btrfs_put_super(struct super_block *sb)
151 int ret; 151 int ret;
152 152
153 ret = close_ctree(root); 153 ret = close_ctree(root);
154 free_fs_info(root->fs_info);
154 sb->s_fs_info = NULL; 155 sb->s_fs_info = NULL;
155 156
156 (void)ret; /* FIXME: need to fix VFS to return error? */ 157 (void)ret; /* FIXME: need to fix VFS to return error? */
@@ -589,6 +590,7 @@ static int btrfs_fill_super(struct super_block *sb,
589 struct inode *inode; 590 struct inode *inode;
590 struct dentry *root_dentry; 591 struct dentry *root_dentry;
591 struct btrfs_root *tree_root; 592 struct btrfs_root *tree_root;
593 struct btrfs_fs_info *fs_info;
592 struct btrfs_key key; 594 struct btrfs_key key;
593 int err; 595 int err;
594 596
@@ -609,12 +611,13 @@ static int btrfs_fill_super(struct super_block *sb,
609 printk("btrfs: open_ctree failed\n"); 611 printk("btrfs: open_ctree failed\n");
610 return PTR_ERR(tree_root); 612 return PTR_ERR(tree_root);
611 } 613 }
614 fs_info = tree_root->fs_info;
612 sb->s_fs_info = tree_root; 615 sb->s_fs_info = tree_root;
613 616
614 key.objectid = BTRFS_FIRST_FREE_OBJECTID; 617 key.objectid = BTRFS_FIRST_FREE_OBJECTID;
615 key.type = BTRFS_INODE_ITEM_KEY; 618 key.type = BTRFS_INODE_ITEM_KEY;
616 key.offset = 0; 619 key.offset = 0;
617 inode = btrfs_iget(sb, &key, tree_root->fs_info->fs_root, NULL); 620 inode = btrfs_iget(sb, &key, fs_info->fs_root, NULL);
618 if (IS_ERR(inode)) { 621 if (IS_ERR(inode)) {
619 err = PTR_ERR(inode); 622 err = PTR_ERR(inode);
620 goto fail_close; 623 goto fail_close;
@@ -635,6 +638,7 @@ static int btrfs_fill_super(struct super_block *sb,
635 638
636fail_close: 639fail_close:
637 close_ctree(tree_root); 640 close_ctree(tree_root);
641 free_fs_info(fs_info);
638 return err; 642 return err;
639} 643}
640 644