summaryrefslogtreecommitdiff
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2020-01-24 09:32:56 -0500
committerDavid Sterba <dsterba@suse.com>2020-03-23 17:01:32 +0100
commitbc44d7c4b2b179c4b74fba208b9908e2ecbc1b4d (patch)
tree183d1adc1dcae85af965e25476a5a6c8cbb0137b /fs/btrfs/disk-io.c
parent81f096edf0472864879e1e5a7f0fdf87ea90fe75 (diff)
btrfs: push btrfs_grab_fs_root into btrfs_get_fs_root
Now that all callers of btrfs_get_fs_root are subsequently calling btrfs_grab_fs_root and handling dropping the ref when they are done appropriately, go ahead and push btrfs_grab_fs_root up into btrfs_get_fs_root. Signed-off-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c45
1 files changed, 26 insertions, 19 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 5be61619c71b..a0c67200fb2a 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1496,6 +1496,8 @@ static struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
spin_lock(&fs_info->fs_roots_radix_lock);
root = radix_tree_lookup(&fs_info->fs_roots_radix,
(unsigned long)root_id);
+ if (root)
+ root = btrfs_grab_fs_root(root);
spin_unlock(&fs_info->fs_roots_radix_lock);
return root;
}
@@ -1552,29 +1554,31 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
int ret;
if (location->objectid == BTRFS_ROOT_TREE_OBJECTID)
- return fs_info->tree_root;
+ return btrfs_grab_fs_root(fs_info->tree_root);
if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID)
- return fs_info->extent_root;
+ return btrfs_grab_fs_root(fs_info->extent_root);
if (location->objectid == BTRFS_CHUNK_TREE_OBJECTID)
- return fs_info->chunk_root;
+ return btrfs_grab_fs_root(fs_info->chunk_root);
if (location->objectid == BTRFS_DEV_TREE_OBJECTID)
- return fs_info->dev_root;
+ return btrfs_grab_fs_root(fs_info->dev_root);
if (location->objectid == BTRFS_CSUM_TREE_OBJECTID)
- return fs_info->csum_root;
+ return btrfs_grab_fs_root(fs_info->csum_root);
if (location->objectid == BTRFS_QUOTA_TREE_OBJECTID)
- return fs_info->quota_root ? fs_info->quota_root :
- ERR_PTR(-ENOENT);
+ return btrfs_grab_fs_root(fs_info->quota_root) ?
+ fs_info->quota_root : ERR_PTR(-ENOENT);
if (location->objectid == BTRFS_UUID_TREE_OBJECTID)
- return fs_info->uuid_root ? fs_info->uuid_root :
- ERR_PTR(-ENOENT);
+ return btrfs_grab_fs_root(fs_info->uuid_root) ?
+ fs_info->uuid_root : ERR_PTR(-ENOENT);
if (location->objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
- return fs_info->free_space_root ? fs_info->free_space_root :
- ERR_PTR(-ENOENT);
+ return btrfs_grab_fs_root(fs_info->free_space_root) ?
+ fs_info->free_space_root : ERR_PTR(-ENOENT);
again:
root = btrfs_lookup_fs_root(fs_info, location->objectid);
if (root) {
- if (check_ref && btrfs_root_refs(&root->root_item) == 0)
+ if (check_ref && btrfs_root_refs(&root->root_item) == 0) {
+ btrfs_put_fs_root(root);
return ERR_PTR(-ENOENT);
+ }
return root;
}
@@ -1607,8 +1611,18 @@ again:
if (ret == 0)
set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state);
+ /*
+ * All roots have two refs on them at all times, one for the mounted fs,
+ * and one for being in the radix tree. This way we only free the root
+ * when we are unmounting or deleting the subvolume. We get one ref
+ * from __setup_root, one for inserting it into the radix tree, and then
+ * we have the third for returning it, and the caller will put it when
+ * it's done with the root.
+ */
+ btrfs_grab_fs_root(root);
ret = btrfs_insert_fs_root(fs_info, root);
if (ret) {
+ btrfs_put_fs_root(root);
if (ret == -EEXIST) {
btrfs_free_fs_root(root);
goto again;
@@ -3207,13 +3221,6 @@ int __cold open_ctree(struct super_block *sb,
goto fail_qgroup;
}
- if (!btrfs_grab_fs_root(fs_info->fs_root)) {
- fs_info->fs_root = NULL;
- err = -ENOENT;
- btrfs_warn(fs_info, "failed to grab a ref on the fs tree");
- goto fail_qgroup;
- }
-
if (sb_rdonly(sb))
return 0;