btrfs: abstract out loading the tree root

We're going to be adding more roots that need to be loaded from the
super block, so abstract out the code to read the tree_root from the
super block, and use this helper for the chunk root as well.  This will
make it simpler to load the new trees in the future.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Josef Bacik 2021-12-15 15:40:06 -05:00 committed by David Sterba
parent c2fa821cc9
commit bd676446c1

View File

@ -2930,6 +2930,45 @@ out:
return ret;
}
static int load_super_root(struct btrfs_root *root, u64 bytenr, u64 gen, int level)
{
int ret = 0;
root->node = read_tree_block(root->fs_info, bytenr,
root->root_key.objectid, gen, level, NULL);
if (IS_ERR(root->node)) {
ret = PTR_ERR(root->node);
root->node = NULL;
} else if (!extent_buffer_uptodate(root->node)) {
free_extent_buffer(root->node);
root->node = NULL;
ret = -EIO;
}
if (ret)
return ret;
btrfs_set_root_node(&root->root_item, root->node);
root->commit_root = btrfs_root_node(root);
btrfs_set_root_refs(&root->root_item, 1);
return ret;
}
static int load_important_roots(struct btrfs_fs_info *fs_info)
{
struct btrfs_super_block *sb = fs_info->super_copy;
u64 gen, bytenr;
int level, ret;
bytenr = btrfs_super_root(sb);
gen = btrfs_super_generation(sb);
level = btrfs_super_root_level(sb);
ret = load_super_root(fs_info->tree_root, bytenr, gen, level);
if (ret)
btrfs_warn(fs_info, "couldn't read tree root");
return ret;
}
static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
{
int backup_index = find_newest_super_backup(fs_info);
@ -2940,9 +2979,6 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
int i;
for (i = 0; i < BTRFS_NUM_BACKUP_ROOTS; i++) {
u64 generation;
int level;
if (handle_error) {
if (!IS_ERR(tree_root->node))
free_extent_buffer(tree_root->node);
@ -2967,29 +3003,13 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
if (ret < 0)
return ret;
}
generation = btrfs_super_generation(sb);
level = btrfs_super_root_level(sb);
tree_root->node = read_tree_block(fs_info, btrfs_super_root(sb),
BTRFS_ROOT_TREE_OBJECTID,
generation, level, NULL);
if (IS_ERR(tree_root->node)) {
handle_error = true;
ret = PTR_ERR(tree_root->node);
tree_root->node = NULL;
btrfs_warn(fs_info, "couldn't read tree root");
continue;
} else if (!extent_buffer_uptodate(tree_root->node)) {
ret = load_important_roots(fs_info);
if (ret) {
handle_error = true;
ret = -EIO;
btrfs_warn(fs_info, "error while reading tree root");
continue;
}
btrfs_set_root_node(&tree_root->root_item, tree_root->node);
tree_root->commit_root = btrfs_root_node(tree_root);
btrfs_set_root_refs(&tree_root->root_item, 1);
/*
* No need to hold btrfs_root::objectid_mutex since the fs
* hasn't been fully initialised and we are the only user
@ -3009,8 +3029,8 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
}
/* All successful */
fs_info->generation = generation;
fs_info->last_trans_committed = generation;
fs_info->generation = btrfs_header_generation(tree_root->node);
fs_info->last_trans_committed = fs_info->generation;
fs_info->last_reloc_trans = 0;
/* Always begin writing backup roots after the one being used */
@ -3594,21 +3614,12 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
generation = btrfs_super_chunk_root_generation(disk_super);
level = btrfs_super_chunk_root_level(disk_super);
chunk_root->node = read_tree_block(fs_info,
btrfs_super_chunk_root(disk_super),
BTRFS_CHUNK_TREE_OBJECTID,
generation, level, NULL);
if (IS_ERR(chunk_root->node) ||
!extent_buffer_uptodate(chunk_root->node)) {
ret = load_super_root(chunk_root, btrfs_super_chunk_root(disk_super),
generation, level);
if (ret) {
btrfs_err(fs_info, "failed to read chunk root");
if (!IS_ERR(chunk_root->node))
free_extent_buffer(chunk_root->node);
chunk_root->node = NULL;
goto fail_tree_roots;
}
btrfs_set_root_node(&chunk_root->root_item, chunk_root->node);
chunk_root->commit_root = btrfs_root_node(chunk_root);
read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid,
offsetof(struct btrfs_header, chunk_tree_uuid),