aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2015-03-02 15:53:53 -0500
committerChris Mason <clm@fb.com>2015-03-26 20:55:51 -0400
commit2f1f465ae6da244099af55c066e5355abd8ff620 (patch)
tree05e245ff3ad099a59616f39710737119cb0442df
parent5cc2b17e80cf5770f2e585c2d90fd8af1b901258 (diff)
Btrfs: send, don't leave without decrementing clone root's send_progress
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: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.cz> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/send.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 6ec28f13659e..571de5a08fe7 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -5852,9 +5852,7 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
5852 ret = PTR_ERR(clone_root); 5852 ret = PTR_ERR(clone_root);
5853 goto out; 5853 goto out;
5854 } 5854 }
5855 clone_sources_to_rollback = i + 1;
5856 spin_lock(&clone_root->root_item_lock); 5855 spin_lock(&clone_root->root_item_lock);
5857 clone_root->send_in_progress++;
5858 if (!btrfs_root_readonly(clone_root) || 5856 if (!btrfs_root_readonly(clone_root) ||
5859 btrfs_root_dead(clone_root)) { 5857 btrfs_root_dead(clone_root)) {
5860 spin_unlock(&clone_root->root_item_lock); 5858 spin_unlock(&clone_root->root_item_lock);
@@ -5862,10 +5860,12 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
5862 ret = -EPERM; 5860 ret = -EPERM;
5863 goto out; 5861 goto out;
5864 } 5862 }
5863 clone_root->send_in_progress++;
5865 spin_unlock(&clone_root->root_item_lock); 5864 spin_unlock(&clone_root->root_item_lock);
5866 srcu_read_unlock(&fs_info->subvol_srcu, index); 5865 srcu_read_unlock(&fs_info->subvol_srcu, index);
5867 5866
5868 sctx->clone_roots[i].root = clone_root; 5867 sctx->clone_roots[i].root = clone_root;
5868 clone_sources_to_rollback = i + 1;
5869 } 5869 }
5870 vfree(clone_sources_tmp); 5870 vfree(clone_sources_tmp);
5871 clone_sources_tmp = NULL; 5871 clone_sources_tmp = NULL;