btrfs: protect snapshots from deleting during send
The patch "Btrfs: fix protection between send and root deletion"
(18f687d538
) 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>
This commit is contained in:

committed by
Chris Mason

parent
944a4515b2
commit
521e0546c9
@@ -5518,7 +5518,7 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
|
||||
|
||||
/*
|
||||
* The subvolume must remain read-only during send, protect against
|
||||
* making it RW.
|
||||
* making it RW. This also protects against deletion.
|
||||
*/
|
||||
spin_lock(&send_root->root_item_lock);
|
||||
send_root->send_in_progress++;
|
||||
@@ -5578,6 +5578,15 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
|
||||
}
|
||||
|
||||
sctx->send_root = send_root;
|
||||
/*
|
||||
* Unlikely but possible, if the subvolume is marked for deletion but
|
||||
* is slow to remove the directory entry, send can still be started
|
||||
*/
|
||||
if (btrfs_root_dead(sctx->send_root)) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sctx->clone_roots_cnt = arg->clone_sources_count;
|
||||
|
||||
sctx->send_max_size = BTRFS_SEND_BUF_SIZE;
|
||||
@@ -5667,7 +5676,8 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
|
||||
|
||||
spin_lock(&sctx->parent_root->root_item_lock);
|
||||
sctx->parent_root->send_in_progress++;
|
||||
if (!btrfs_root_readonly(sctx->parent_root)) {
|
||||
if (!btrfs_root_readonly(sctx->parent_root) ||
|
||||
btrfs_root_dead(sctx->parent_root)) {
|
||||
spin_unlock(&sctx->parent_root->root_item_lock);
|
||||
srcu_read_unlock(&fs_info->subvol_srcu, index);
|
||||
ret = -EPERM;
|
||||
|
Reference in New Issue
Block a user