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>
up_read(&fs_info->cleanup_work_sem);
if (err) {
close_ctree(tree_root);
up_read(&fs_info->cleanup_work_sem);
if (err) {
close_ctree(tree_root);
bdi_destroy(&fs_info->bdi);
cleanup_srcu_struct(&fs_info->subvol_srcu);
bdi_destroy(&fs_info->bdi);
cleanup_srcu_struct(&fs_info->subvol_srcu);
- free_fs_info(fs_info);
-
int ret;
ret = close_ctree(root);
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? */
sb->s_fs_info = NULL;
(void)ret; /* FIXME: need to fix VFS to return error? */
struct inode *inode;
struct dentry *root_dentry;
struct btrfs_root *tree_root;
struct inode *inode;
struct dentry *root_dentry;
struct btrfs_root *tree_root;
+ struct btrfs_fs_info *fs_info;
struct btrfs_key key;
int err;
struct btrfs_key key;
int err;
printk("btrfs: open_ctree failed\n");
return PTR_ERR(tree_root);
}
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;
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;
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
goto fail_close;
fail_close:
close_ctree(tree_root);
fail_close:
close_ctree(tree_root);