btrfs-progs: image: keep track of seen blocks when walking trees

Extent tree v2 no longer tracks all allocated blocks on the file system,
so we'll have to default to walking trees to generate metadata images.
There's an annoying drawback with walking trees with btrfs-image where
we'll happily copy multiple blocks over and over again if there are
snapshots.  Fix this by keeping track of blocks we've seen and simply
skipping blocks that we've already queued up for copying.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Josef Bacik 2021-11-10 15:08:00 -05:00 committed by David Sterba
parent 639b1fc2e7
commit 29e56c7e05

View File

@ -93,6 +93,8 @@ struct metadump_struct {
pthread_cond_t cond;
struct rb_root name_tree;
struct extent_io_tree seen;
struct list_head list;
struct list_head ordered;
size_t num_items;
@ -461,6 +463,7 @@ static void metadump_destroy(struct metadump_struct *md, int num_threads)
free(name->sub);
free(name);
}
extent_io_tree_cleanup(&md->seen);
}
static int metadump_init(struct metadump_struct *md, struct btrfs_root *root,
@ -476,6 +479,7 @@ static int metadump_init(struct metadump_struct *md, struct btrfs_root *root,
memset(md, 0, sizeof(*md));
INIT_LIST_HEAD(&md->list);
INIT_LIST_HEAD(&md->ordered);
extent_io_tree_init(&md->seen);
md->root = root;
md->out = out;
md->pending_start = (u64)-1;
@ -771,6 +775,14 @@ static int copy_tree_blocks(struct btrfs_root *root, struct extent_buffer *eb,
int i = 0;
int ret;
bytenr = btrfs_header_bytenr(eb);
if (test_range_bit(&metadump->seen, bytenr,
bytenr + fs_info->nodesize - 1, EXTENT_DIRTY, 1))
return 0;
set_extent_dirty(&metadump->seen, bytenr,
bytenr + fs_info->nodesize - 1);
ret = add_extent(btrfs_header_bytenr(eb), fs_info->nodesize,
metadump, 0);
if (ret) {