btrfs-progs: check: abstract out the used marking helpers

We will walk all referenced tree blocks during check in order to avoid
writing over any referenced blocks during fsck.  However in the future
we're going to need to do this for things like fixing block group
accounting with extent tree v2.  This is because extent tree v2 will not
refer to all of the allocated blocks in the extent tree.  Refactor the
code some to allow us to send down an arbitrary extent_io_tree so we can
use this helper for any case where we need to figure out where all the
used space is on an extent tree v2 file system.

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:02 -05:00 committed by David Sterba
parent 550fd48136
commit 17f6374cfa

View File

@ -599,23 +599,21 @@ void reset_cached_block_groups()
}
}
static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin)
static int traverse_tree_blocks(struct extent_io_tree *tree,
struct extent_buffer *eb, int tree_root)
{
struct btrfs_fs_info *fs_info = eb->fs_info;
struct extent_buffer *tmp;
struct btrfs_root_item *ri;
struct btrfs_key key;
struct extent_io_tree *tree;
u64 bytenr;
int level = btrfs_header_level(eb);
int nritems;
int ret;
int i;
u64 end = eb->start + eb->len;
bool pin = tree == &fs_info->pinned_extents;
if (pin)
tree = &gfs_info->pinned_extents;
else
tree = gfs_info->excluded_extents;
/*
* If we have pinned/excluded this block before, don't do it again.
* This can not only avoid forever loop with broken filesystem
@ -625,7 +623,7 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
return 0;
if (pin)
btrfs_pin_extent(gfs_info, eb->start, eb->len);
btrfs_pin_extent(fs_info, eb->start, eb->len);
else
set_extent_dirty(tree, eb->start, end - 1);
@ -654,12 +652,12 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
* in, but for now this doesn't actually use the root so
* just pass in extent_root.
*/
tmp = read_tree_block(gfs_info, bytenr, 0);
tmp = read_tree_block(fs_info, bytenr, 0);
if (!extent_buffer_uptodate(tmp)) {
fprintf(stderr, "Error reading root block\n");
return -EIO;
}
ret = traverse_tree_blocks(tmp, 0, pin);
ret = traverse_tree_blocks(tree, tmp, 0);
free_extent_buffer(tmp);
if (ret)
return ret;
@ -667,24 +665,24 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
u64 end;
bytenr = btrfs_node_blockptr(eb, i);
end = bytenr + gfs_info->nodesize - 1;
end = bytenr + fs_info->nodesize - 1;
/* If we aren't the tree root don't read the block */
if (level == 1 && !tree_root) {
if (pin)
btrfs_pin_extent(gfs_info, bytenr,
gfs_info->nodesize);
btrfs_pin_extent(fs_info, bytenr,
fs_info->nodesize);
else
set_extent_dirty(tree, bytenr, end);
continue;
}
tmp = read_tree_block(gfs_info, bytenr, 0);
tmp = read_tree_block(fs_info, bytenr, 0);
if (!extent_buffer_uptodate(tmp)) {
fprintf(stderr, "Error reading tree block\n");
return -EIO;
}
ret = traverse_tree_blocks(tmp, tree_root, pin);
ret = traverse_tree_blocks(tree, tmp, tree_root);
free_extent_buffer(tmp);
if (ret)
return ret;
@ -694,30 +692,25 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
return 0;
}
static int pin_down_tree_blocks(struct extent_buffer *eb, int tree_root)
int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
struct extent_io_tree *tree)
{
return traverse_tree_blocks(eb, tree_root, 1);
int ret;
ret = traverse_tree_blocks(tree, fs_info->chunk_root->node, 0);
if (!ret)
ret = traverse_tree_blocks(tree, fs_info->tree_root->node, 1);
return ret;
}
int pin_metadata_blocks(void)
{
int ret;
ret = pin_down_tree_blocks(gfs_info->chunk_root->node, 0);
if (ret)
return ret;
return pin_down_tree_blocks(gfs_info->tree_root->node, 1);
}
static int exclude_tree_blocks(struct extent_buffer *eb, int tree_root)
{
return traverse_tree_blocks(eb, tree_root, 0);
return btrfs_mark_used_tree_blocks(gfs_info,
&gfs_info->pinned_extents);
}
int exclude_metadata_blocks(void)
{
int ret;
struct extent_io_tree *excluded_extents;
excluded_extents = malloc(sizeof(*excluded_extents));
@ -726,10 +719,7 @@ int exclude_metadata_blocks(void)
extent_io_tree_init(excluded_extents);
gfs_info->excluded_extents = excluded_extents;
ret = exclude_tree_blocks(gfs_info->chunk_root->node, 0);
if (ret)
return ret;
return exclude_tree_blocks(gfs_info->tree_root->node, 1);
return btrfs_mark_used_tree_blocks(gfs_info, excluded_extents);
}
void cleanup_excluded_extents(void)