summaryrefslogtreecommitdiff
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2020-11-17 22:23:05 +0100
committerLinus Walleij <linus.walleij@linaro.org>2020-11-17 22:23:05 +0100
commitad9a72f9c6fd3998f0080701f1cc1f43a4317b7c (patch)
treedd53a560a1523f5dcd9823b29ae92bdcc0b7da4d /fs/btrfs/backref.c
parentb9bf97105f4b9adc32604d24072147b242564fb3 (diff)
parent09162bc32c880a791c6c0668ce0745cf7958f576 (diff)
Merge tag 'v5.10-rc4' into devel
Linux 5.10-rc4
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index b3268f4ea5f3..771a036867dc 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -544,7 +544,18 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info,
int level = ref->level;
struct btrfs_key search_key = ref->key_for_search;
- root = btrfs_get_fs_root(fs_info, ref->root_id, false);
+ /*
+ * If we're search_commit_root we could possibly be holding locks on
+ * other tree nodes. This happens when qgroups does backref walks when
+ * adding new delayed refs. To deal with this we need to look in cache
+ * for the root, and if we don't find it then we need to search the
+ * tree_root's commit root, thus the btrfs_get_fs_root_commit_root usage
+ * here.
+ */
+ if (path->search_commit_root)
+ root = btrfs_get_fs_root_commit_root(fs_info, path, ref->root_id);
+ else
+ root = btrfs_get_fs_root(fs_info, ref->root_id, false);
if (IS_ERR(root)) {
ret = PTR_ERR(root);
goto out_free;