[PATCH 1/5] btrfs-progs: backref: properly queue indirect refs
From: Qu Wenruo <hidden>
Date: 2021-12-24 05:50:52
Subsystem:
the rest · Maintainer:
Linus Torvalds
[BUG] When calling iterate_extent_inodes() on data extents with indirect ref (with inline or keyed EXTENT_DATA_REF_KEY), it will fail to execute the call back function at all. [CAUSE] In fucntion find_parent_nodes(), we only add the target tree block if a backref has @parent populated. For indirect backref like EXTENT_DATA_REF_KEY, we rely on __resolve_indirect_ref() to get the parent leaves. However __resolve_indirect_ref() only grabs backrefs from &prefstate->pending_indirect_refs. Meaning callers should queue any indrect backref to pending_indirect_refs. But unfortunately in __add_prelim_ref() and __add_missing_keys(), none of them properly queue the indirect backrefs to pending_indirect_refs, but directly to pending. Making all indirect backrefs never got resolved, thus no callback function executed [FIX] Fix __add_prelim_ref() and __add_missing_keys() to properly queue indirect backrefs to the correct list. Currently there is no such direct user in btrfs-progs, but later csum tree re-initialization code will rely this to do proper csum re-calculate (to avoid preallocated/nodatasum extents). Signed-off-by: Qu Wenruo <redacted> --- kernel-shared/backref.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/kernel-shared/backref.c b/kernel-shared/backref.c
index 42832c481cae..f1a638ededa8 100644
--- a/kernel-shared/backref.c
+++ b/kernel-shared/backref.c@@ -192,7 +192,10 @@ static int __add_prelim_ref(struct pref_state *prefstate, u64 root_id, ref->root_id = root_id; if (key) { ref->key_for_search = *key; - head = &prefstate->pending; + if (parent) + head = &prefstate->pending; + else + head = &prefstate->pending_indirect_refs; } else if (parent) { memset(&ref->key_for_search, 0, sizeof(ref->key_for_search)); head = &prefstate->pending;
@@ -467,7 +470,10 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info, else btrfs_node_key_to_cpu(eb, &ref->key_for_search, 0); free_extent_buffer(eb); - list_move(&ref->list, &prefstate->pending); + if (ref->parent) + list_move(&ref->list, &prefstate->pending); + else + list_move(&ref->list, &prefstate->pending_indirect_refs); } return 0; }
--
2.34.1