btrfs-progs: properly populate missing trees

With my global roots prep patches I regressed us on handling the case
where we didn't find a root at all.  In this case we need to return an
error (prior we returned -ENOENT) or we need to populate a dummy tree if
we have OPEN_CTREE_PARTIAL set.  This fixes a segfault of fuzz test 006.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Josef Bacik 2022-02-22 17:22:39 -05:00 committed by David Sterba
parent 29beeb1a30
commit 401690ff68

View file

@ -1059,6 +1059,7 @@ static int load_global_roots_objectid(struct btrfs_fs_info *fs_info,
struct btrfs_root *tree_root = fs_info->tree_root;
struct btrfs_root *root;
int ret;
int found = 0;
struct btrfs_key key = {
.objectid = objectid,
.type = BTRFS_ROOT_ITEM_KEY,
@ -1124,9 +1125,51 @@ static int load_global_roots_objectid(struct btrfs_fs_info *fs_info,
break;
}
found++;
path->slots[0]++;
}
btrfs_release_path(path);
/*
* We didn't find all of our roots, create empty ones if we have PARTIAL
* set.
*/
if (!ret && found < fs_info->nr_global_roots) {
int i;
if (!(flags & OPEN_CTREE_PARTIAL)) {
error("could not setup %s tree", str);
return -EIO;
}
warning("could not setup %s tree, skipping it", str);
for (i = found; i < fs_info->nr_global_roots; i++) {
root = calloc(1, sizeof(*root));
if (!root) {
ret = -ENOMEM;
break;
}
btrfs_setup_root(root, fs_info, objectid);
root->root_key.objectid = objectid;
root->root_key.type = BTRFS_ROOT_ITEM_KEY;
root->root_key.offset = i;
root->track_dirty = 1;
root->node = btrfs_find_create_tree_block(fs_info, 0);
if (!root->node) {
free(root);
ret = -ENOMEM;
break;
}
clear_extent_buffer_uptodate(root->node);
ret = btrfs_global_root_insert(fs_info, root);
if (ret) {
free_extent_buffer(root->node);
free(root);
break;
}
}
}
return ret;
}