btrfs: hold a ref on the root in btrfs_ioctl_send
We lookup all the clone roots and the parent root for send, so we need to hold refs on all of these roots while we're processing them. Signed-off-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
fd79d43b34
commit
6f9a3da5da
|
@ -7201,10 +7201,16 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
|
|||
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)) {
|
||||
spin_unlock(&clone_root->root_item_lock);
|
||||
btrfs_put_fs_root(clone_root);
|
||||
srcu_read_unlock(&fs_info->subvol_srcu, index);
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
|
@ -7212,6 +7218,7 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
|
|||
if (clone_root->dedupe_in_progress) {
|
||||
dedupe_in_progress_warn(clone_root);
|
||||
spin_unlock(&clone_root->root_item_lock);
|
||||
btrfs_put_fs_root(clone_root);
|
||||
srcu_read_unlock(&fs_info->subvol_srcu, index);
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
|
@ -7240,6 +7247,12 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
|
|||
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++;
|
||||
|
@ -7267,7 +7280,8 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
|
|||
* is behind the current send position. This is checked while searching
|
||||
* for possible clone sources.
|
||||
*/
|
||||
sctx->clone_roots[sctx->clone_roots_cnt++].root = sctx->send_root;
|
||||
sctx->clone_roots[sctx->clone_roots_cnt++].root =
|
||||
btrfs_grab_fs_root(sctx->send_root);
|
||||
|
||||
/* We do a bsearch later */
|
||||
sort(sctx->clone_roots, sctx->clone_roots_cnt,
|
||||
|
@ -7352,18 +7366,24 @@ out:
|
|||
}
|
||||
|
||||
if (sort_clone_roots) {
|
||||
for (i = 0; i < sctx->clone_roots_cnt; i++)
|
||||
for (i = 0; i < sctx->clone_roots_cnt; i++) {
|
||||
btrfs_root_dec_send_in_progress(
|
||||
sctx->clone_roots[i].root);
|
||||
btrfs_put_fs_root(sctx->clone_roots[i].root);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; sctx && i < clone_sources_to_rollback; i++)
|
||||
for (i = 0; sctx && i < clone_sources_to_rollback; i++) {
|
||||
btrfs_root_dec_send_in_progress(
|
||||
sctx->clone_roots[i].root);
|
||||
btrfs_put_fs_root(sctx->clone_roots[i].root);
|
||||
}
|
||||
|
||||
btrfs_root_dec_send_in_progress(send_root);
|
||||
}
|
||||
if (sctx && !IS_ERR_OR_NULL(sctx->parent_root))
|
||||
if (sctx && !IS_ERR_OR_NULL(sctx->parent_root)) {
|
||||
btrfs_root_dec_send_in_progress(sctx->parent_root);
|
||||
btrfs_put_fs_root(sctx->parent_root);
|
||||
}
|
||||
|
||||
kvfree(clone_sources_tmp);
|
||||
|
||||
|
|
Loading…
Reference in New Issue