Commit 6f9a3da5 authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

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: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent fd79d43b
...@@ -7201,10 +7201,16 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7201,10 +7201,16 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
ret = PTR_ERR(clone_root); ret = PTR_ERR(clone_root);
goto out; 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); spin_lock(&clone_root->root_item_lock);
if (!btrfs_root_readonly(clone_root) || if (!btrfs_root_readonly(clone_root) ||
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_fs_root(clone_root);
srcu_read_unlock(&fs_info->subvol_srcu, index); srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = -EPERM; ret = -EPERM;
goto out; goto out;
...@@ -7212,6 +7218,7 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7212,6 +7218,7 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
if (clone_root->dedupe_in_progress) { if (clone_root->dedupe_in_progress) {
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_fs_root(clone_root);
srcu_read_unlock(&fs_info->subvol_srcu, index); srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = -EAGAIN; ret = -EAGAIN;
goto out; goto out;
...@@ -7240,6 +7247,12 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7240,6 +7247,12 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
ret = PTR_ERR(sctx->parent_root); ret = PTR_ERR(sctx->parent_root);
goto out; 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); spin_lock(&sctx->parent_root->root_item_lock);
sctx->parent_root->send_in_progress++; sctx->parent_root->send_in_progress++;
...@@ -7267,7 +7280,8 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -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 * is behind the current send position. This is checked while searching
* for possible clone sources. * 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 */ /* We do a bsearch later */
sort(sctx->clone_roots, sctx->clone_roots_cnt, sort(sctx->clone_roots, sctx->clone_roots_cnt,
...@@ -7352,18 +7366,24 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) ...@@ -7352,18 +7366,24 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
} }
if (sort_clone_roots) { 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( btrfs_root_dec_send_in_progress(
sctx->clone_roots[i].root); sctx->clone_roots[i].root);
btrfs_put_fs_root(sctx->clone_roots[i].root);
}
} else { } 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( btrfs_root_dec_send_in_progress(
sctx->clone_roots[i].root); sctx->clone_roots[i].root);
btrfs_put_fs_root(sctx->clone_roots[i].root);
}
btrfs_root_dec_send_in_progress(send_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_root_dec_send_in_progress(sctx->parent_root);
btrfs_put_fs_root(sctx->parent_root);
}
kvfree(clone_sources_tmp); kvfree(clone_sources_tmp);
......
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