mirror of
https://github.com/kdave/btrfs-progs
synced 2024-12-11 17:06:32 +00:00
btrfs-progs: backref: properly queue indirect refs
[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 function 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 indirect 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 <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
d6ee42633b
commit
90cdc23d01
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user