Skip to content

Commit dc058f5

Browse files
fdmananakdave
authored andcommitted
btrfs: send: check for dead send root under critical section
We're checking if the send root is dead without the protection of the root's root_item_lock spinlock, which is what protects the root's flags. The inverse, setting the dead flag on a root, is done under the protection of that lock, at btrfs_delete_subvolume(). Also checking and updating the root's send_in_progress counter is supposed to be done in the same critical section as checking for or setting the root dead flag, so that these operations are done atomically as a single step (which is correctly done by btrfs_delete_subvolume()). So fix this by checking if the send root is dead in the same critical section that updates the send_in_progress counter, which is protected by the root's root_item_lock spinlock. Signed-off-by: Filipe Manana <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 722d343 commit dc058f5

File tree

1 file changed

+8
-9
lines changed

1 file changed

+8
-9
lines changed

fs/btrfs/send.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8125,6 +8125,14 @@ long btrfs_ioctl_send(struct btrfs_inode *inode, const struct btrfs_ioctl_send_a
81258125
* making it RW. This also protects against deletion.
81268126
*/
81278127
spin_lock(&send_root->root_item_lock);
8128+
/*
8129+
* Unlikely but possible, if the subvolume is marked for deletion but
8130+
* is slow to remove the directory entry, send can still be started.
8131+
*/
8132+
if (btrfs_root_dead(send_root)) {
8133+
spin_unlock(&send_root->root_item_lock);
8134+
return -EPERM;
8135+
}
81288136
if (btrfs_root_readonly(send_root) && send_root->dedupe_in_progress) {
81298137
dedupe_in_progress_warn(send_root);
81308138
spin_unlock(&send_root->root_item_lock);
@@ -8207,15 +8215,6 @@ long btrfs_ioctl_send(struct btrfs_inode *inode, const struct btrfs_ioctl_send_a
82078215
}
82088216

82098217
sctx->send_root = send_root;
8210-
/*
8211-
* Unlikely but possible, if the subvolume is marked for deletion but
8212-
* is slow to remove the directory entry, send can still be started
8213-
*/
8214-
if (btrfs_root_dead(sctx->send_root)) {
8215-
ret = -EPERM;
8216-
goto out;
8217-
}
8218-
82198218
sctx->clone_roots_cnt = arg->clone_sources_count;
82208219

82218220
if (sctx->proto >= 2) {

0 commit comments

Comments
 (0)