goto out_free;
}
- if (!btrfs_grab_fs_root(root)) {
- srcu_read_unlock(&fs_info->subvol_srcu, index);
- ret = -ENOENT;
- goto out_free;
- }
-
if (btrfs_is_testing(fs_info)) {
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = -ENOENT;
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;
}
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;
}
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;
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;
err = PTR_ERR(root);
goto fail;
}
- if (!btrfs_grab_fs_root(root)) {
- err = -ENOENT;
- goto fail;
- }
key.objectid = objectid;
key.type = BTRFS_INODE_ITEM_KEY;
ret = PTR_ERR(inode_root);
goto cleanup;
}
- if (!btrfs_grab_fs_root(inode_root)) {
- ret = -ENOENT;
- goto cleanup;
- }
key.objectid = defrag->ino;
key.type = BTRFS_INODE_ITEM_KEY;
err = PTR_ERR(new_root);
goto out;
}
- if (!btrfs_grab_fs_root(new_root)) {
- err = -ENOENT;
- goto out;
- }
*sub_root = new_root;
location->objectid = btrfs_root_dirid(&new_root->root_item);
btrfs_abort_transaction(trans, ret);
goto fail;
}
- if (!btrfs_grab_fs_root(new_root)) {
- ret = -ENOENT;
- btrfs_abort_transaction(trans, ret);
- goto fail;
- }
btrfs_record_root_in_trans(trans, new_root);
btrfs_free_path(path);
return PTR_ERR(root);
}
- if (!btrfs_grab_fs_root(root)) {
- btrfs_free_path(path);
- return -ENOENT;
- }
}
key.objectid = sk->min_objectid;
root = NULL;
goto out;
}
- if (!btrfs_grab_fs_root(root)) {
- ret = -ENOENT;
- root = NULL;
- goto out;
- }
key.objectid = dirid;
key.type = BTRFS_INODE_REF_KEY;
ret = PTR_ERR(root);
goto out;
}
- if (!btrfs_grab_fs_root(root)) {
- ret = -ENOENT;
- goto out;
- }
key.objectid = dirid;
key.type = BTRFS_INODE_REF_KEY;
ret = PTR_ERR(root);
goto out_free;
}
- if (!btrfs_grab_fs_root(root)) {
- ret = -ENOENT;
- goto out;
- }
root_item = &root->root_item;
subvol_info->treeid = key.objectid;
ret = PTR_ERR(new_root);
goto out;
}
- if (!btrfs_grab_fs_root(new_root)) {
- ret = -ENOENT;
- goto out;
- }
if (!is_fstree(new_root->root_key.objectid)) {
ret = -ENOENT;
goto out_free;
u64 root_objectid)
{
struct btrfs_key key;
- struct btrfs_root *root;
key.objectid = root_objectid;
key.type = BTRFS_ROOT_ITEM_KEY;
else
key.offset = (u64)-1;
- root = btrfs_get_fs_root(fs_info, &key, false);
- if (IS_ERR(root))
- return root;
- if (!btrfs_grab_fs_root(root))
- return ERR_PTR(-ENOENT);
- return root;
+ return btrfs_get_fs_root(fs_info, &key, false);
}
static noinline_for_stack
root = btrfs_get_fs_root(fs_info, &root_key, false);
err = PTR_ERR_OR_ZERO(root);
- if (!err && !btrfs_grab_fs_root(root))
- err = -ENOENT;
if (err && err != -ENOENT) {
break;
} else if (err == -ENOENT) {
ret = PTR_ERR(local_root);
goto err;
}
- if (!btrfs_grab_fs_root(local_root)) {
- ret = -ENOENT;
- goto err;
- }
/*
* this makes the path point to (inum INODE_ITEM ioff)
ret = PTR_ERR(clone_root);
goto out;
}
- if (!btrfs_grab_fs_root(clone_root)) {
- srcu_read_unlock(&fs_info->subvol_srcu, index);
- ret = -ENOENT;
- goto out;
- }
spin_lock(&clone_root->root_item_lock);
if (!btrfs_root_readonly(clone_root) ||
btrfs_root_dead(clone_root)) {
ret = PTR_ERR(sctx->parent_root);
goto out;
}
- if (!btrfs_grab_fs_root(sctx->parent_root)) {
- srcu_read_unlock(&fs_info->subvol_srcu, index);
- ret = -ENOENT;
- sctx->parent_root = ERR_PTR(ret);
- goto out;
- }
spin_lock(&sctx->parent_root->root_item_lock);
sctx->parent_root->send_in_progress++;
fs_root = NULL;
goto err;
}
- if (!btrfs_grab_fs_root(fs_root)) {
- ret = -ENOENT;
- fs_root = NULL;
- goto err;
- }
/*
* Walk up the filesystem tree by inode refs until we hit the
btrfs_abort_transaction(trans, ret);
goto fail;
}
- if (!btrfs_grab_fs_root(pending->snap)) {
- ret = -ENOENT;
- pending->snap = NULL;
- btrfs_abort_transaction(trans, ret);
- goto fail;
- }
ret = btrfs_reloc_post_snapshot(trans, pending);
if (ret) {
tmp_key.offset = (u64)-1;
wc.replay_dest = btrfs_get_fs_root(fs_info, &tmp_key, true);
- if (!IS_ERR(wc.replay_dest)) {
- if (!btrfs_grab_fs_root(wc.replay_dest))
- wc.replay_dest = ERR_PTR(-ENOENT);
- }
if (IS_ERR(wc.replay_dest)) {
ret = PTR_ERR(wc.replay_dest);
ret = 1;
goto out;
}
- if (!btrfs_grab_fs_root(subvol_root)) {
- ret = 1;
- goto out;
- }
switch (type) {
case BTRFS_UUID_KEY_SUBVOL: