btrfs-progs: do not merge tree block refs have different root_id

For an extent item which contains many tree block backrefs, like

In 020-extent-ref-cases/keyed_block_ref.img

item 10 key (29470720 METADATA_ITEM 0) itemoff 3450 itemsize 222
                refs 23 gen 10 flags TREE_BLOCK
                tree block skinny level 0
                tree block backref root 278
                tree block backref root 277
                tree block backref root 276
                tree block backref root 275
                tree block backref root 274
                tree block backref root 273
                tree block backref root 272
                tree block backref root 271
                tree block backref root 270
                tree block backref root 269
                tree block backref root 268
                tree block backref root 267
                tree block backref root 266
                tree block backref root 265
                tree block backref root 264
                tree block backref root 263
                tree block backref root 262
                tree block backref root 261
                tree block backref root 260
                tree block backref root 259
                tree block backref root 258
                tree block backref root 257

In find_parent_nodes(), these refs's parents are 0, then __merge_refs
will merge refs to one ref. It causes only one root to be returned.

So, if both parents are 0, do not merge refs.

Lowmem check calls find_parent_nodes frequently to decide whether
check an extent buffer or not. The bug affects bytes accounting.

Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
master
Su Yue 2018-04-25 13:19:24 +08:00 committed by David Sterba
parent d9b32dd2e9
commit 42a5710aca
1 changed files with 6 additions and 0 deletions

View File

@ -505,6 +505,12 @@ static void __merge_refs(struct pref_state *prefstate, int mode)
if (!ref_for_same_block(ref1, ref2))
continue;
} else {
/*
* Parent == 0 means that the ref is tree block
* backref or its parent is unresolved.
*/
if (!ref1->parent || !ref2->parent)
continue;
if (ref1->parent != ref2->parent)
continue;
}