Commit e8f6216d authored by Filipe Manana's avatar Filipe Manana Committed by Luis Henriques

Btrfs: send, don't leave without decrementing clone root's send_progress

commit 2f1f465a upstream.

If the clone root was not readonly or the dead flag was set on it, we were
leaving without decrementing the root's send_progress counter (and before
we just incremented it). If a concurrent snapshot deletion was in progress
and ended up being aborted, it would be impossible to later attempt to
delete again the snapshot, since the root's send_in_progress counter could
never go back to 0.

We were also setting clone_sources_to_rollback to i + 1 too early - if we
bailed out because the clone root we got is not readonly or flagged as dead
we ended up later derreferencing a null pointer because we didn't assign
the clone root to sctx->clone_roots[i].root:

		for (i = 0; sctx && i < clone_sources_to_rollback; i++)
			btrfs_root_dec_send_in_progress(
					sctx->clone_roots[i].root);

So just don't increment the send_in_progress counter if the root is readonly
or flagged as dead.
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.cz>
Signed-off-by: default avatarChris Mason <clm@fb.com>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 9c41450b
...@@ -5644,9 +5644,7 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_) ...@@ -5644,9 +5644,7 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
ret = PTR_ERR(clone_root); ret = PTR_ERR(clone_root);
goto out; goto out;
} }
clone_sources_to_rollback = i + 1;
spin_lock(&clone_root->root_item_lock); spin_lock(&clone_root->root_item_lock);
clone_root->send_in_progress++;
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);
...@@ -5654,10 +5652,12 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_) ...@@ -5654,10 +5652,12 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
ret = -EPERM; ret = -EPERM;
goto out; goto out;
} }
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); 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;
} }
vfree(clone_sources_tmp); vfree(clone_sources_tmp);
clone_sources_tmp = NULL; clone_sources_tmp = NULL;
......
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