Commit bd676446 authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

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: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent c2fa821c
......@@ -2930,6 +2930,45 @@ static int btrfs_validate_write_super(struct btrfs_fs_info *fs_info,
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),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment