aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2019-01-08 06:44:41 -0500
committerDavid Sterba <dsterba@suse.com>2019-01-09 08:52:36 -0500
commita6d8654d885d7d79a3fb82da64eaa489ca332a82 (patch)
treeb83db2ff93e52ee665492f8f32d6d97ac5a3c088
parentd8b5524242108cb7d28c9b8b9aded7c1edd0e8a8 (diff)
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>
-rw-r--r--fs/btrfs/ctree.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index d92462fe66c8..f64aad613727 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1016,19 +1016,21 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
1016 parent_start = parent->start; 1016 parent_start = parent->start;
1017 1017
1018 /* 1018 /*
1019 * If we are COWing a node/leaf from the extent, chunk or device trees, 1019 * If we are COWing a node/leaf from the extent, chunk, device or free
1020 * make sure that we do not finish block group creation of pending block 1020 * space trees, make sure that we do not finish block group creation of
1021 * groups. We do this to avoid a deadlock. 1021 * pending block groups. We do this to avoid a deadlock.
1022 * COWing can result in allocation of a new chunk, and flushing pending 1022 * COWing can result in allocation of a new chunk, and flushing pending
1023 * block groups (btrfs_create_pending_block_groups()) can be triggered 1023 * block groups (btrfs_create_pending_block_groups()) can be triggered
1024 * when finishing allocation of a new chunk. Creation of a pending block 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 1025 * group modifies the extent, chunk, device and free space trees,
1026 * deadlock with ourselves since we are holding a lock on an extent 1026 * therefore we could deadlock with ourselves since we are holding a
1027 * buffer that btrfs_create_pending_block_groups() may try to COW later. 1027 * lock on an extent buffer that btrfs_create_pending_block_groups() may
1028 * try to COW later.
1028 */ 1029 */
1029 if (root == fs_info->extent_root || 1030 if (root == fs_info->extent_root ||
1030 root == fs_info->chunk_root || 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 trans->can_flush_pending_bgs = false; 1034 trans->can_flush_pending_bgs = false;
1033 1035
1034 cow = btrfs_alloc_tree_block(trans, root, parent_start, 1036 cow = btrfs_alloc_tree_block(trans, root, parent_start,