aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/send.c
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.cz>2014-04-15 10:41:44 -0400
committerChris Mason <clm@fb.com>2014-06-09 20:20:31 -0400
commit521e0546c970c3d845076f243828fa7abd71edfc (patch)
treee203f19e76c97629173c097e051946e2aeb6ce4a /fs/btrfs/send.c
parent944a4515b27302ac42d5964b7400c72f4d692782 (diff)
btrfs: protect snapshots from deleting during send
The patch "Btrfs: fix protection between send and root deletion" (18f687d538449373c37c) does not actually prevent to delete the snapshot and just takes care during background cleaning, but this seems rather user unfriendly, this patch implements the idea presented in http://www.spinics.net/lists/linux-btrfs/msg30813.html - add an internal root_item flag to denote a dead root - check if the send_in_progress is set and refuse to delete, otherwise set the flag and proceed - check the flag in send similar to the btrfs_root_readonly checks, for all involved roots The root lookup in send via btrfs_read_fs_root_no_name will check if the root is really dead or not. If it is, ENOENT, aborted send. If it's alive, it's protected by send_in_progress, send can continue. CC: Miao Xie <miaox@cn.fujitsu.com> CC: Wang Shilong <wangsl.fnst@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.cz> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/send.c')
-rw-r--r--fs/btrfs/send.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 484aacac2c89..c76400dda4df 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -5518,7 +5518,7 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
5518 5518
5519 /* 5519 /*
5520 * The subvolume must remain read-only during send, protect against 5520 * The subvolume must remain read-only during send, protect against
5521 * making it RW. 5521 * making it RW. This also protects against deletion.
5522 */ 5522 */
5523 spin_lock(&send_root->root_item_lock); 5523 spin_lock(&send_root->root_item_lock);
5524 send_root->send_in_progress++; 5524 send_root->send_in_progress++;
@@ -5578,6 +5578,15 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
5578 } 5578 }
5579 5579
5580 sctx->send_root = send_root; 5580 sctx->send_root = send_root;
5581 /*
5582 * Unlikely but possible, if the subvolume is marked for deletion but
5583 * is slow to remove the directory entry, send can still be started
5584 */
5585 if (btrfs_root_dead(sctx->send_root)) {
5586 ret = -EPERM;
5587 goto out;
5588 }
5589
5581 sctx->clone_roots_cnt = arg->clone_sources_count; 5590 sctx->clone_roots_cnt = arg->clone_sources_count;
5582 5591
5583 sctx->send_max_size = BTRFS_SEND_BUF_SIZE; 5592 sctx->send_max_size = BTRFS_SEND_BUF_SIZE;
@@ -5667,7 +5676,8 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
5667 5676
5668 spin_lock(&sctx->parent_root->root_item_lock); 5677 spin_lock(&sctx->parent_root->root_item_lock);
5669 sctx->parent_root->send_in_progress++; 5678 sctx->parent_root->send_in_progress++;
5670 if (!btrfs_root_readonly(sctx->parent_root)) { 5679 if (!btrfs_root_readonly(sctx->parent_root) ||
5680 btrfs_root_dead(sctx->parent_root)) {
5671 spin_unlock(&sctx->parent_root->root_item_lock); 5681 spin_unlock(&sctx->parent_root->root_item_lock);
5672 srcu_read_unlock(&fs_info->subvol_srcu, index); 5682 srcu_read_unlock(&fs_info->subvol_srcu, index);
5673 ret = -EPERM; 5683 ret = -EPERM;