summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorLinus Torvalds2018-10-30 16:27:13 +0100
committerLinus Torvalds2018-10-30 16:27:13 +0100
commit85b5d4bcab8b46664f8e1993bd5919cb0f24a3ca (patch)
tree904b271d66dfbe005f4006fbd5e0bcc97a2fb428 /fs/btrfs/ctree.c
parentMerge tag 'rpmsg-v4.20' of git://github.com/andersson/remoteproc (diff)
parentBtrfs: fix use-after-free when dumping free space (diff)
downloadkernel-qcow2-linux-85b5d4bcab8b46664f8e1993bd5919cb0f24a3ca.tar.gz
kernel-qcow2-linux-85b5d4bcab8b46664f8e1993bd5919cb0f24a3ca.tar.xz
kernel-qcow2-linux-85b5d4bcab8b46664f8e1993bd5919cb0f24a3ca.zip
Merge tag 'for-4.20-part2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull more btrfs updates from David Sterba: "This contains a few minor updates and fixes that were under testing or arrived shortly after the merge window freeze, mostly stable material" * tag 'for-4.20-part2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: Btrfs: fix use-after-free when dumping free space Btrfs: fix use-after-free during inode eviction btrfs: move the dio_sem higher up the callchain btrfs: don't run delayed_iputs in commit btrfs: fix insert_reserved error handling btrfs: only free reserved extent if we didn't insert it btrfs: don't use ctl->free_space for max_extent_size btrfs: set max_extent_size properly btrfs: reset max_extent_size properly MAINTAINERS: update my email address for btrfs btrfs: delayed-ref: extract find_first_ref_head from find_ref_head Btrfs: fix deadlock when writing out free space caches Btrfs: fix assertion on fsync of regular file when using no-holes feature Btrfs: fix null pointer dereference on compressed write path error
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 2ee43b6a4f09..539901fb5165 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1014,9 +1014,26 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
if ((root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && parent)
parent_start = parent->start;
+ /*
+ * If we are COWing a node/leaf from the extent, chunk or device trees,
+ * make sure that we do not finish block group creation of pending block
+ * groups. We do this to avoid a deadlock.
+ * COWing can result in allocation of a new chunk, and flushing pending
+ * block groups (btrfs_create_pending_block_groups()) can be triggered
+ * when finishing allocation of a new chunk. Creation of a pending block
+ * group modifies the extent, chunk and device trees, therefore we could
+ * deadlock with ourselves since we are holding a lock on an extent
+ * buffer that btrfs_create_pending_block_groups() may try to COW later.
+ */
+ if (root == fs_info->extent_root ||
+ root == fs_info->chunk_root ||
+ root == fs_info->dev_root)
+ trans->can_flush_pending_bgs = false;
+
cow = btrfs_alloc_tree_block(trans, root, parent_start,
root->root_key.objectid, &disk_key, level,
search_start, empty_size);
+ trans->can_flush_pending_bgs = true;
if (IS_ERR(cow))
return PTR_ERR(cow);