Commit c75e8394 authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

btrfs: kill the subvol_srcu

Now that we have proper root ref counting everywhere we can kill the
subvol_srcu.

* removal of fs_info::subvol_srcu reduces size of fs_info by 1176 bytes

* the refcount_t used for the references checks for accidental 0->1
  in cases where the root lifetime would not be properly protected

* there's a leak detector for roots to catch unfreed roots at umount
  time

* SRCU served us well over the years but is was not a proper
  synchronization mechanism for some cases
Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
[ update changelog ]
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent efc34534
...@@ -542,24 +542,19 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, ...@@ -542,24 +542,19 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info,
int ret = 0; int ret = 0;
int root_level; int root_level;
int level = ref->level; int level = ref->level;
int index;
struct btrfs_key search_key = ref->key_for_search; struct btrfs_key search_key = ref->key_for_search;
root_key.objectid = ref->root_id; root_key.objectid = ref->root_id;
root_key.type = BTRFS_ROOT_ITEM_KEY; root_key.type = BTRFS_ROOT_ITEM_KEY;
root_key.offset = (u64)-1; root_key.offset = (u64)-1;
index = srcu_read_lock(&fs_info->subvol_srcu);
root = btrfs_get_fs_root(fs_info, &root_key, false); root = btrfs_get_fs_root(fs_info, &root_key, false);
if (IS_ERR(root)) { if (IS_ERR(root)) {
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = PTR_ERR(root); ret = PTR_ERR(root);
goto out_free; goto out_free;
} }
if (btrfs_is_testing(fs_info)) { if (btrfs_is_testing(fs_info)) {
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = -ENOENT; ret = -ENOENT;
goto out; goto out;
} }
...@@ -571,10 +566,8 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, ...@@ -571,10 +566,8 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info,
else else
root_level = btrfs_old_root_level(root, time_seq); root_level = btrfs_old_root_level(root, time_seq);
if (root_level + 1 == level) { if (root_level + 1 == level)
srcu_read_unlock(&fs_info->subvol_srcu, index);
goto out; goto out;
}
/* /*
* We can often find data backrefs with an offset that is too large * We can often find data backrefs with an offset that is too large
...@@ -604,9 +597,6 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, ...@@ -604,9 +597,6 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info,
else else
ret = btrfs_search_old_slot(root, &search_key, path, time_seq); ret = btrfs_search_old_slot(root, &search_key, path, time_seq);
/* root node has been locked, we can release @subvol_srcu safely here */
srcu_read_unlock(&fs_info->subvol_srcu, index);
btrfs_debug(fs_info, btrfs_debug(fs_info,
"search slot in root %llu (level %d, ref count %d) returned %d for key (%llu %u %llu)", "search slot in root %llu (level %d, ref count %d) returned %d for key (%llu %u %llu)",
ref->root_id, level, ref->count, ret, ref->root_id, level, ref->count, ret,
......
...@@ -697,7 +697,6 @@ struct btrfs_fs_info { ...@@ -697,7 +697,6 @@ struct btrfs_fs_info {
struct rw_semaphore cleanup_work_sem; struct rw_semaphore cleanup_work_sem;
struct rw_semaphore subvol_sem; struct rw_semaphore subvol_sem;
struct srcu_struct subvol_srcu;
spinlock_t trans_lock; spinlock_t trans_lock;
/* /*
......
...@@ -2757,46 +2757,33 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block ...@@ -2757,46 +2757,33 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block
sb->s_blocksize = BTRFS_BDEV_BLOCKSIZE; sb->s_blocksize = BTRFS_BDEV_BLOCKSIZE;
sb->s_blocksize_bits = blksize_bits(BTRFS_BDEV_BLOCKSIZE); sb->s_blocksize_bits = blksize_bits(BTRFS_BDEV_BLOCKSIZE);
ret = init_srcu_struct(&fs_info->subvol_srcu);
if (ret)
return ret;
ret = percpu_counter_init(&fs_info->dio_bytes, 0, GFP_KERNEL); ret = percpu_counter_init(&fs_info->dio_bytes, 0, GFP_KERNEL);
if (ret) if (ret)
goto fail; return ret;
ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL); ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL);
if (ret) if (ret)
goto fail; return ret;
fs_info->dirty_metadata_batch = PAGE_SIZE * fs_info->dirty_metadata_batch = PAGE_SIZE *
(1 + ilog2(nr_cpu_ids)); (1 + ilog2(nr_cpu_ids));
ret = percpu_counter_init(&fs_info->delalloc_bytes, 0, GFP_KERNEL); ret = percpu_counter_init(&fs_info->delalloc_bytes, 0, GFP_KERNEL);
if (ret) if (ret)
goto fail; return ret;
ret = percpu_counter_init(&fs_info->dev_replace.bio_counter, 0, ret = percpu_counter_init(&fs_info->dev_replace.bio_counter, 0,
GFP_KERNEL); GFP_KERNEL);
if (ret) if (ret)
goto fail; return ret;
fs_info->delayed_root = kmalloc(sizeof(struct btrfs_delayed_root), fs_info->delayed_root = kmalloc(sizeof(struct btrfs_delayed_root),
GFP_KERNEL); GFP_KERNEL);
if (!fs_info->delayed_root) { if (!fs_info->delayed_root)
ret = -ENOMEM; return -ENOMEM;
goto fail;
}
btrfs_init_delayed_root(fs_info->delayed_root); btrfs_init_delayed_root(fs_info->delayed_root);
ret = btrfs_alloc_stripe_hash_table(fs_info); return btrfs_alloc_stripe_hash_table(fs_info);
if (ret)
goto fail;
return 0;
fail:
cleanup_srcu_struct(&fs_info->subvol_srcu);
return ret;
} }
static int btrfs_uuid_rescan_kthread(void *data) static int btrfs_uuid_rescan_kthread(void *data)
...@@ -2870,13 +2857,13 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device ...@@ -2870,13 +2857,13 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
fs_info->chunk_root = chunk_root; fs_info->chunk_root = chunk_root;
if (!tree_root || !chunk_root) { if (!tree_root || !chunk_root) {
err = -ENOMEM; err = -ENOMEM;
goto fail_srcu; goto fail;
} }
fs_info->btree_inode = new_inode(sb); fs_info->btree_inode = new_inode(sb);
if (!fs_info->btree_inode) { if (!fs_info->btree_inode) {
err = -ENOMEM; err = -ENOMEM;
goto fail_srcu; goto fail;
} }
mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
btrfs_init_btree_inode(fs_info); btrfs_init_btree_inode(fs_info);
...@@ -3398,8 +3385,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device ...@@ -3398,8 +3385,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
btrfs_mapping_tree_free(&fs_info->mapping_tree); btrfs_mapping_tree_free(&fs_info->mapping_tree);
iput(fs_info->btree_inode); iput(fs_info->btree_inode);
fail_srcu:
cleanup_srcu_struct(&fs_info->subvol_srcu);
fail: fail:
btrfs_close_devices(fs_info->fs_devices); btrfs_close_devices(fs_info->fs_devices);
return err; return err;
...@@ -3902,9 +3887,6 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, ...@@ -3902,9 +3887,6 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
drop_ref = true; drop_ref = true;
spin_unlock(&fs_info->fs_roots_radix_lock); spin_unlock(&fs_info->fs_roots_radix_lock);
if (btrfs_root_refs(&root->root_item) == 0)
synchronize_srcu(&fs_info->subvol_srcu);
if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) { if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
btrfs_free_log(NULL, root); btrfs_free_log(NULL, root);
if (root->reloc_root) { if (root->reloc_root) {
...@@ -4116,7 +4098,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) ...@@ -4116,7 +4098,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
btrfs_mapping_tree_free(&fs_info->mapping_tree); btrfs_mapping_tree_free(&fs_info->mapping_tree);
btrfs_close_devices(fs_info->fs_devices); btrfs_close_devices(fs_info->fs_devices);
cleanup_srcu_struct(&fs_info->subvol_srcu);
} }
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
......
...@@ -65,8 +65,6 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, ...@@ -65,8 +65,6 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
struct btrfs_root *root; struct btrfs_root *root;
struct inode *inode; struct inode *inode;
struct btrfs_key key; struct btrfs_key key;
int index;
int err = 0;
if (objectid < BTRFS_FIRST_FREE_OBJECTID) if (objectid < BTRFS_FIRST_FREE_OBJECTID)
return ERR_PTR(-ESTALE); return ERR_PTR(-ESTALE);
...@@ -75,13 +73,9 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, ...@@ -75,13 +73,9 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
key.type = BTRFS_ROOT_ITEM_KEY; key.type = BTRFS_ROOT_ITEM_KEY;
key.offset = (u64)-1; key.offset = (u64)-1;
index = srcu_read_lock(&fs_info->subvol_srcu);
root = btrfs_get_fs_root(fs_info, &key, true); root = btrfs_get_fs_root(fs_info, &key, true);
if (IS_ERR(root)) { if (IS_ERR(root))
err = PTR_ERR(root); return ERR_CAST(root);
goto fail;
}
key.objectid = objectid; key.objectid = objectid;
key.type = BTRFS_INODE_ITEM_KEY; key.type = BTRFS_INODE_ITEM_KEY;
...@@ -89,12 +83,8 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, ...@@ -89,12 +83,8 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
inode = btrfs_iget(sb, &key, root); inode = btrfs_iget(sb, &key, root);
btrfs_put_root(root); btrfs_put_root(root);
if (IS_ERR(inode)) { if (IS_ERR(inode))
err = PTR_ERR(inode); return ERR_CAST(inode);
goto fail;
}
srcu_read_unlock(&fs_info->subvol_srcu, index);
if (check_generation && generation != inode->i_generation) { if (check_generation && generation != inode->i_generation) {
iput(inode); iput(inode);
...@@ -102,9 +92,6 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, ...@@ -102,9 +92,6 @@ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
} }
return d_obtain_alias(inode); return d_obtain_alias(inode);
fail:
srcu_read_unlock(&fs_info->subvol_srcu, index);
return ERR_PTR(err);
} }
static struct dentry *btrfs_fh_to_parent(struct super_block *sb, struct fid *fh, static struct dentry *btrfs_fh_to_parent(struct super_block *sb, struct fid *fh,
......
...@@ -278,7 +278,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, ...@@ -278,7 +278,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
struct btrfs_key key; struct btrfs_key key;
struct btrfs_ioctl_defrag_range_args range; struct btrfs_ioctl_defrag_range_args range;
int num_defrag; int num_defrag;
int index;
int ret; int ret;
/* get the inode */ /* get the inode */
...@@ -286,8 +285,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, ...@@ -286,8 +285,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
key.type = BTRFS_ROOT_ITEM_KEY; key.type = BTRFS_ROOT_ITEM_KEY;
key.offset = (u64)-1; key.offset = (u64)-1;
index = srcu_read_lock(&fs_info->subvol_srcu);
inode_root = btrfs_get_fs_root(fs_info, &key, true); inode_root = btrfs_get_fs_root(fs_info, &key, true);
if (IS_ERR(inode_root)) { if (IS_ERR(inode_root)) {
ret = PTR_ERR(inode_root); ret = PTR_ERR(inode_root);
...@@ -303,7 +300,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, ...@@ -303,7 +300,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
ret = PTR_ERR(inode); ret = PTR_ERR(inode);
goto cleanup; goto cleanup;
} }
srcu_read_unlock(&fs_info->subvol_srcu, index);
/* do a chunk of defrag */ /* do a chunk of defrag */
clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags);
...@@ -339,7 +335,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, ...@@ -339,7 +335,6 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
iput(inode); iput(inode);
return 0; return 0;
cleanup: cleanup:
srcu_read_unlock(&fs_info->subvol_srcu, index);
kmem_cache_free(btrfs_inode_defrag_cachep, defrag); kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
return ret; return ret;
} }
......
...@@ -5364,7 +5364,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) ...@@ -5364,7 +5364,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
struct btrfs_root *sub_root = root; struct btrfs_root *sub_root = root;
struct btrfs_key location; struct btrfs_key location;
u8 di_type = 0; u8 di_type = 0;
int index;
int ret = 0; int ret = 0;
if (dentry->d_name.len > BTRFS_NAME_LEN) if (dentry->d_name.len > BTRFS_NAME_LEN)
...@@ -5391,7 +5390,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) ...@@ -5391,7 +5390,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
return inode; return inode;
} }
index = srcu_read_lock(&fs_info->subvol_srcu);
ret = fixup_tree_root_location(fs_info, dir, dentry, ret = fixup_tree_root_location(fs_info, dir, dentry,
&location, &sub_root); &location, &sub_root);
if (ret < 0) { if (ret < 0) {
...@@ -5404,7 +5402,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) ...@@ -5404,7 +5402,6 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
} }
if (root != sub_root) if (root != sub_root)
btrfs_put_root(sub_root); btrfs_put_root(sub_root);
srcu_read_unlock(&fs_info->subvol_srcu, index);
if (!IS_ERR(inode) && root != sub_root) { if (!IS_ERR(inode) && root != sub_root) {
down_read(&fs_info->cleanup_work_sem); down_read(&fs_info->cleanup_work_sem);
......
...@@ -7028,7 +7028,6 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7028,7 +7028,6 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
int clone_sources_to_rollback = 0; int clone_sources_to_rollback = 0;
unsigned alloc_size; unsigned alloc_size;
int sort_clone_roots = 0; int sort_clone_roots = 0;
int index;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
...@@ -7155,11 +7154,8 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7155,11 +7154,8 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
key.type = BTRFS_ROOT_ITEM_KEY; key.type = BTRFS_ROOT_ITEM_KEY;
key.offset = (u64)-1; key.offset = (u64)-1;
index = srcu_read_lock(&fs_info->subvol_srcu);
clone_root = btrfs_get_fs_root(fs_info, &key, true); clone_root = btrfs_get_fs_root(fs_info, &key, true);
if (IS_ERR(clone_root)) { if (IS_ERR(clone_root)) {
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = PTR_ERR(clone_root); ret = PTR_ERR(clone_root);
goto out; goto out;
} }
...@@ -7168,7 +7164,6 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7168,7 +7164,6 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
btrfs_root_dead(clone_root)) { btrfs_root_dead(clone_root)) {
spin_unlock(&clone_root->root_item_lock); spin_unlock(&clone_root->root_item_lock);
btrfs_put_root(clone_root); btrfs_put_root(clone_root);
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = -EPERM; ret = -EPERM;
goto out; goto out;
} }
...@@ -7176,13 +7171,11 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7176,13 +7171,11 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
dedupe_in_progress_warn(clone_root); dedupe_in_progress_warn(clone_root);
spin_unlock(&clone_root->root_item_lock); spin_unlock(&clone_root->root_item_lock);
btrfs_put_root(clone_root); btrfs_put_root(clone_root);
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = -EAGAIN; ret = -EAGAIN;
goto out; goto out;
} }
clone_root->send_in_progress++; clone_root->send_in_progress++;
spin_unlock(&clone_root->root_item_lock); spin_unlock(&clone_root->root_item_lock);
srcu_read_unlock(&fs_info->subvol_srcu, index);
sctx->clone_roots[i].root = clone_root; sctx->clone_roots[i].root = clone_root;
clone_sources_to_rollback = i + 1; clone_sources_to_rollback = i + 1;
...@@ -7196,11 +7189,8 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7196,11 +7189,8 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
key.type = BTRFS_ROOT_ITEM_KEY; key.type = BTRFS_ROOT_ITEM_KEY;
key.offset = (u64)-1; key.offset = (u64)-1;
index = srcu_read_lock(&fs_info->subvol_srcu);
sctx->parent_root = btrfs_get_fs_root(fs_info, &key, true); sctx->parent_root = btrfs_get_fs_root(fs_info, &key, true);
if (IS_ERR(sctx->parent_root)) { if (IS_ERR(sctx->parent_root)) {
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = PTR_ERR(sctx->parent_root); ret = PTR_ERR(sctx->parent_root);
goto out; goto out;
} }
...@@ -7210,20 +7200,16 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7210,20 +7200,16 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
if (!btrfs_root_readonly(sctx->parent_root) || if (!btrfs_root_readonly(sctx->parent_root) ||
btrfs_root_dead(sctx->parent_root)) { btrfs_root_dead(sctx->parent_root)) {
spin_unlock(&sctx->parent_root->root_item_lock); spin_unlock(&sctx->parent_root->root_item_lock);
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = -EPERM; ret = -EPERM;
goto out; goto out;
} }
if (sctx->parent_root->dedupe_in_progress) { if (sctx->parent_root->dedupe_in_progress) {
dedupe_in_progress_warn(sctx->parent_root); dedupe_in_progress_warn(sctx->parent_root);
spin_unlock(&sctx->parent_root->root_item_lock); spin_unlock(&sctx->parent_root->root_item_lock);
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = -EAGAIN; ret = -EAGAIN;
goto out; goto out;
} }
spin_unlock(&sctx->parent_root->root_item_lock); spin_unlock(&sctx->parent_root->root_item_lock);
srcu_read_unlock(&fs_info->subvol_srcu, index);
} }
/* /*
......
...@@ -134,14 +134,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(u32 nodesize, u32 sectorsize) ...@@ -134,14 +134,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(u32 nodesize, u32 sectorsize)
fs_info->nodesize = nodesize; fs_info->nodesize = nodesize;
fs_info->sectorsize = sectorsize; fs_info->sectorsize = sectorsize;
if (init_srcu_struct(&fs_info->subvol_srcu)) {
kfree(fs_info->fs_devices);
kfree(fs_info->super_copy);
kfree(fs_info);
return NULL;
}
set_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state); set_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state);
test_mnt->mnt_sb->s_fs_info = fs_info; test_mnt->mnt_sb->s_fs_info = fs_info;
...@@ -191,7 +183,6 @@ void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info) ...@@ -191,7 +183,6 @@ void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info)
} }
btrfs_free_qgroup_config(fs_info); btrfs_free_qgroup_config(fs_info);
btrfs_free_fs_roots(fs_info); btrfs_free_fs_roots(fs_info);
cleanup_srcu_struct(&fs_info->subvol_srcu);
kfree(fs_info->super_copy); kfree(fs_info->super_copy);
btrfs_check_leaked_roots(fs_info); btrfs_check_leaked_roots(fs_info);
btrfs_extent_buffer_leak_debug_check(fs_info); btrfs_extent_buffer_leak_debug_check(fs_info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment