Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Btrfs: fix deadlock when using free space tree due to block group creation

When modifying the free space tree we can end up COWing one of its extent
buffers which in turn might result in allocating a new chunk, which in
turn can result in flushing (finish creation) of pending block groups. If
that happens we can deadlock because creating a pending block group needs
to update the free space tree, and if any of the updates tries to modify
the same extent buffer that we are COWing, we end up in a deadlock since
we try to write lock twice the same extent buffer.

So fix this by skipping pending block group creation if we are COWing an
extent buffer from the free space tree. This is a case missed by commit
5ce555578e091 ("Btrfs: fix deadlock when writing out free space caches").

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=202173
Fixes: 5ce555578e091 ("Btrfs: fix deadlock when writing out free space caches")
CC: stable@vger.kernel.org # 4.18+
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>

authored by

Filipe Manana and committed by
David Sterba
a6d8654d d8b55242

+9 -7
+9 -7
fs/btrfs/ctree.c
··· 1016 1016 parent_start = parent->start; 1017 1017 1018 1018 /* 1019 - * If we are COWing a node/leaf from the extent, chunk or device trees, 1020 - * make sure that we do not finish block group creation of pending block 1021 - * groups. We do this to avoid a deadlock. 1019 + * If we are COWing a node/leaf from the extent, chunk, device or free 1020 + * space trees, make sure that we do not finish block group creation of 1021 + * pending block groups. We do this to avoid a deadlock. 1022 1022 * COWing can result in allocation of a new chunk, and flushing pending 1023 1023 * block groups (btrfs_create_pending_block_groups()) can be triggered 1024 1024 * when finishing allocation of a new chunk. Creation of a pending block 1025 - * group modifies the extent, chunk and device trees, therefore we could 1026 - * deadlock with ourselves since we are holding a lock on an extent 1027 - * buffer that btrfs_create_pending_block_groups() may try to COW later. 1025 + * group modifies the extent, chunk, device and free space trees, 1026 + * therefore we could deadlock with ourselves since we are holding a 1027 + * lock on an extent buffer that btrfs_create_pending_block_groups() may 1028 + * try to COW later. 1028 1029 */ 1029 1030 if (root == fs_info->extent_root || 1030 1031 root == fs_info->chunk_root || 1031 - root == fs_info->dev_root) 1032 + root == fs_info->dev_root || 1033 + root == fs_info->free_space_root) 1032 1034 trans->can_flush_pending_bgs = false; 1033 1035 1034 1036 cow = btrfs_alloc_tree_block(trans, root, parent_start,