btrfs-progs: update read_tree_block to match the kernel definition

The in-kernel version of read_tree_block adds some extra sanity checks
to make sure we don't return blocks that don't match what we expect.
This includes the owning root, the level, and the expected first key.
We don't actually do these checks in btrfs-progs, however kernel code
we're going to sync will expect this calling convention, so update it to
match the in-kernel code and then update all the callers.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Josef Bacik 2023-04-19 17:23:59 -04:00 committed by David Sterba
parent 79e9fcd4f9
commit b3477244f9
17 changed files with 68 additions and 40 deletions

View File

@ -166,7 +166,7 @@ static int corrupt_keys_in_block(struct btrfs_fs_info *fs_info, u64 bytenr)
{
struct extent_buffer *eb;
eb = read_tree_block(fs_info, bytenr, 0);
eb = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(eb))
return -EIO;;
@ -296,7 +296,9 @@ static void btrfs_corrupt_extent_tree(struct btrfs_trans_handle *trans,
struct extent_buffer *next;
next = read_tree_block(fs_info, btrfs_node_blockptr(eb, i),
btrfs_node_ptr_generation(eb, i));
btrfs_header_owner(eb),
btrfs_node_ptr_generation(eb, i),
btrfs_header_level(eb) - 1, NULL);
if (!extent_buffer_uptodate(next))
continue;
btrfs_corrupt_extent_tree(trans, root, next);
@ -860,7 +862,7 @@ static int corrupt_metadata_block(struct btrfs_fs_info *fs_info, u64 block,
return -EINVAL;
}
eb = read_tree_block(fs_info, block, 0);
eb = read_tree_block(fs_info, block, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(eb)) {
error("couldn't read in tree block %s", field);
return -EINVAL;

View File

@ -199,7 +199,7 @@ int btrfs_find_root_search(struct btrfs_fs_info *fs_info,
for (offset = chunk_offset;
offset < chunk_offset + chunk_size;
offset += nodesize) {
eb = read_tree_block(fs_info, offset, 0);
eb = read_tree_block(fs_info, offset, 0, 0, 0, NULL);
if (!eb || IS_ERR(eb))
continue;
ret = add_eb_to_result(eb, result, nodesize, filter,

View File

@ -1898,7 +1898,9 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
free_extent_buffer(next);
reada_walk_down(root, cur, path->slots[*level]);
next = read_tree_block(gfs_info, bytenr, ptr_gen);
next = read_tree_block(gfs_info, bytenr,
btrfs_header_owner(cur), ptr_gen,
*level - 1, NULL);
if (!extent_buffer_uptodate(next)) {
struct btrfs_key node_key;
@ -6269,7 +6271,7 @@ static int run_next_block(struct btrfs_root *root,
}
/* fixme, get the real parent transid */
buf = read_tree_block(gfs_info, bytenr, gen);
buf = read_tree_block(gfs_info, bytenr, 0, gen, 0, NULL);
if (!extent_buffer_uptodate(buf)) {
record_bad_block_io(extent_cache, bytenr, size);
goto out;
@ -8615,7 +8617,8 @@ static int deal_root_from_list(struct list_head *list,
rec = list_entry(list->next,
struct root_item_record, list);
last = 0;
buf = read_tree_block(gfs_info, rec->bytenr, 0);
buf = read_tree_block(gfs_info, rec->bytenr, rec->objectid, 0,
rec->level, NULL);
if (!extent_buffer_uptodate(buf)) {
free_extent_buffer(buf);
ret = -EIO;

View File

@ -132,7 +132,7 @@ static int check_prealloc_shared_data_ref(u64 parent, u64 disk_bytenr)
int i;
int ret = 0;
eb = read_tree_block(gfs_info, parent, 0);
eb = read_tree_block(gfs_info, parent, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(eb)) {
ret = -EIO;
goto out;
@ -1127,7 +1127,7 @@ int get_extent_item_generation(u64 bytenr, u64 *gen_ret)
BTRFS_EXTENT_FLAG_TREE_BLOCK) {
struct extent_buffer *eb;
eb = read_tree_block(gfs_info, bytenr, 0);
eb = read_tree_block(gfs_info, bytenr, 0, 0, 0, NULL);
if (extent_buffer_uptodate(eb)) {
*gen_ret = btrfs_header_generation(eb);
ret = 0;

View File

@ -3748,7 +3748,7 @@ static int query_tree_block_level(u64 bytenr)
btrfs_release_path(&path);
/* Get level from tree block as an alternative source */
eb = read_tree_block(gfs_info, bytenr, transid);
eb = read_tree_block(gfs_info, bytenr, 0, transid, 0, NULL);
if (!extent_buffer_uptodate(eb)) {
free_extent_buffer(eb);
return -EIO;
@ -3800,7 +3800,7 @@ static int check_tree_block_backref(u64 root_id, u64 bytenr, int level)
}
/* Read out the tree block to get item/node key */
eb = read_tree_block(gfs_info, bytenr, 0);
eb = read_tree_block(gfs_info, bytenr, root_id, 0, 0, NULL);
if (!extent_buffer_uptodate(eb)) {
err |= REFERENCER_MISSING;
free_extent_buffer(eb);
@ -3899,7 +3899,7 @@ static int check_shared_block_backref(u64 parent, u64 bytenr, int level)
int found_parent = 0;
int i;
eb = read_tree_block(gfs_info, parent, 0);
eb = read_tree_block(gfs_info, parent, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(eb))
goto out;
@ -4072,7 +4072,7 @@ static int check_shared_data_backref(u64 parent, u64 bytenr)
int found_parent = 0;
int i;
eb = read_tree_block(gfs_info, parent, 0);
eb = read_tree_block(gfs_info, parent, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(eb))
goto out;
@ -5046,7 +5046,9 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
free_extent_buffer(next);
reada_walk_down(root, cur, path->slots[*level]);
next = read_tree_block(gfs_info, bytenr, ptr_gen);
next = read_tree_block(gfs_info, bytenr,
btrfs_header_owner(cur),
ptr_gen, *level - 1, NULL);
if (!extent_buffer_uptodate(next)) {
struct btrfs_key node_key;

View File

@ -720,7 +720,8 @@ static int travel_tree(struct btrfs_fs_info *info, struct btrfs_root *root,
// printf("travel_tree: bytenr: %llu\tnum_bytes: %llu\tref_parent: %llu\n",
// bytenr, num_bytes, ref_parent);
eb = read_tree_block(info, bytenr, 0);
eb = read_tree_block(info, bytenr, btrfs_root_id(root), 0,
0, NULL);
if (!extent_buffer_uptodate(eb))
return -EIO;

View File

@ -108,7 +108,9 @@ static int traverse_tree_blocks(struct extent_io_tree *tree,
* in, but for now this doesn't actually use the root so
* just pass in extent_root.
*/
tmp = read_tree_block(fs_info, bytenr, 0);
tmp = read_tree_block(fs_info, bytenr, key.objectid, 0,
btrfs_disk_root_level(eb, ri),
NULL);
if (!extent_buffer_uptodate(tmp)) {
fprintf(stderr, "Error reading root block\n");
return -EIO;
@ -133,7 +135,9 @@ static int traverse_tree_blocks(struct extent_io_tree *tree,
continue;
}
tmp = read_tree_block(fs_info, bytenr, 0);
tmp = read_tree_block(fs_info, bytenr,
btrfs_header_owner(eb), 0,
level - 1, NULL);
if (!extent_buffer_uptodate(tmp)) {
fprintf(stderr, "Error reading tree block\n");
return -EIO;

View File

@ -58,9 +58,10 @@ static void print_extents(struct extent_buffer *eb)
nr = btrfs_header_nritems(eb);
for (i = 0; i < nr; i++) {
next = read_tree_block(fs_info,
btrfs_node_blockptr(eb, i),
btrfs_node_ptr_generation(eb, i));
next = read_tree_block(fs_info, btrfs_node_blockptr(eb, i),
btrfs_header_owner(eb),
btrfs_node_ptr_generation(eb, i),
btrfs_header_level(eb) - 1, NULL);
if (!extent_buffer_uptodate(next))
continue;
if (btrfs_is_leaf(next) && btrfs_header_level(eb) != 1) {
@ -288,7 +289,7 @@ static int dump_print_tree_blocks(struct btrfs_fs_info *fs_info,
goto next;
}
eb = read_tree_block(fs_info, bytenr, 0);
eb = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(eb)) {
error("failed to read tree block %llu", bytenr);
ret = -EIO;
@ -625,7 +626,8 @@ again:
offset = btrfs_item_ptr_offset(leaf, slot);
read_extent_buffer(leaf, &ri, offset, sizeof(ri));
buf = read_tree_block(info, btrfs_root_bytenr(&ri), 0);
buf = read_tree_block(info, btrfs_root_bytenr(&ri),
key.objectid, 0, 0, NULL);
if (!extent_buffer_uptodate(buf))
goto next;
if (tree_id && found_key.objectid != tree_id) {

View File

@ -153,7 +153,9 @@ static int walk_nodes(struct btrfs_root *root, struct btrfs_path *path,
path->slots[level] = i;
if ((level - 1) > 0 || find_inline) {
tmp = read_tree_block(root->fs_info, cur_blocknr,
btrfs_node_ptr_generation(b, i));
btrfs_header_owner(b),
btrfs_node_ptr_generation(b, i),
level - 1, NULL);
if (!extent_buffer_uptodate(tmp)) {
error("failed to read blocknr %llu",
btrfs_node_blockptr(b, i));

View File

@ -1260,7 +1260,8 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location,
root_location = btrfs_super_root(fs_info->super_copy);
generation = btrfs_super_generation(fs_info->super_copy);
root->node = read_tree_block(fs_info, root_location,
generation);
btrfs_root_id(root), generation,
0, NULL);
if (!extent_buffer_uptodate(root->node)) {
error("opening tree root failed");
close_ctree(root);
@ -1527,7 +1528,8 @@ static int cmd_restore(const struct cmd_struct *cmd, int argc, char **argv)
if (fs_location != 0) {
free_extent_buffer(root->node);
root->node = read_tree_block(root->fs_info, fs_location, 0);
root->node = read_tree_block(root->fs_info, fs_location, 0, 0,
0, NULL);
if (!extent_buffer_uptodate(root->node)) {
error("failed to read fs location");
ret = 1;

View File

@ -707,7 +707,8 @@ static int flush_pending(struct metadump_struct *md, int done)
u64 this_read = min((u64)md->root->fs_info->nodesize,
size);
eb = read_tree_block(md->root->fs_info, start, 0);
eb = read_tree_block(md->root->fs_info, start, 0, 0, 0,
NULL);
if (!extent_buffer_uptodate(eb)) {
free(async->buffer);
free(async);
@ -811,7 +812,7 @@ static int copy_tree_blocks(struct btrfs_root *root, struct extent_buffer *eb,
continue;
ri = btrfs_item_ptr(eb, i, struct btrfs_root_item);
bytenr = btrfs_disk_root_bytenr(eb, ri);
tmp = read_tree_block(fs_info, bytenr, 0);
tmp = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(tmp)) {
error("unable to read log root block");
return -EIO;
@ -822,7 +823,7 @@ static int copy_tree_blocks(struct btrfs_root *root, struct extent_buffer *eb,
return ret;
} else {
bytenr = btrfs_node_blockptr(eb, i);
tmp = read_tree_block(fs_info, bytenr, 0);
tmp = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(tmp)) {
error("unable to read log root block");
return -EIO;
@ -2697,7 +2698,7 @@ static int iter_tree_blocks(struct btrfs_fs_info *fs_info,
continue;
ri = btrfs_item_ptr(eb, i, struct btrfs_root_item);
bytenr = btrfs_disk_root_bytenr(eb, ri);
tmp = read_tree_block(fs_info, bytenr, 0);
tmp = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(tmp)) {
error("unable to read log root block");
return -EIO;
@ -2708,7 +2709,7 @@ static int iter_tree_blocks(struct btrfs_fs_info *fs_info,
return ret;
} else {
bytenr = btrfs_node_blockptr(eb, i);
tmp = read_tree_block(fs_info, bytenr, 0);
tmp = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL);
if (!extent_buffer_uptodate(tmp)) {
error("unable to read log root block");
return -EIO;

View File

@ -461,7 +461,8 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info,
ASSERT(!ref->parent);
ASSERT(!ref->key_for_search.type);
BUG_ON(!ref->wanted_disk_byte);
eb = read_tree_block(fs_info, ref->wanted_disk_byte, 0);
eb = read_tree_block(fs_info, ref->wanted_disk_byte,
ref->root_id, 0, ref->level - 1, NULL);
if (!extent_buffer_uptodate(eb)) {
free_extent_buffer(eb);
return -EIO;
@ -823,7 +824,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
ref->level == 0) {
struct extent_buffer *eb;
eb = read_tree_block(fs_info, ref->parent, 0);
eb = read_tree_block(fs_info, ref->parent, 0,
0, ref->level, NULL);
if (!extent_buffer_uptodate(eb)) {
free_extent_buffer(eb);
ret = -EIO;

View File

@ -874,7 +874,9 @@ struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info,
return NULL;
ret = read_tree_block(fs_info, btrfs_node_blockptr(parent, slot),
btrfs_node_ptr_generation(parent, slot));
btrfs_header_owner(parent),
btrfs_node_ptr_generation(parent, slot),
level - 1, NULL);
if (!extent_buffer_uptodate(ret))
return ERR_PTR(-EIO);

View File

@ -337,8 +337,9 @@ int read_whole_eb(struct btrfs_fs_info *info, struct extent_buffer *eb, int mirr
return 0;
}
struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
u64 parent_transid)
struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
u64 owner_root, u64 parent_transid,
int level, struct btrfs_key *first_key)
{
int ret;
struct extent_buffer *eb;
@ -510,7 +511,8 @@ static int read_root_node(struct btrfs_fs_info *fs_info,
struct btrfs_root *root, u64 bytenr, u64 gen,
int level)
{
root->node = read_tree_block(fs_info, bytenr, gen);
root->node = read_tree_block(fs_info, bytenr, btrfs_root_id(root),
gen, level, NULL);
if (!extent_buffer_uptodate(root->node))
goto err;
if (btrfs_header_level(root->node) != level) {

View File

@ -138,8 +138,9 @@ static inline u64 btrfs_sb_offset(int mirror)
struct btrfs_device;
int read_whole_eb(struct btrfs_fs_info *info, struct extent_buffer *eb, int mirror);
struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
u64 parent_transid);
struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
u64 owner_root, u64 parent_transid,
int level, struct btrfs_key *first_key);
void readahead_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
u64 parent_transid);

View File

@ -1557,7 +1557,9 @@ static void dfs_print_children(struct extent_buffer *root_eb, unsigned int mode)
for (i = 0; i < nr; i++) {
next = read_tree_block(fs_info, btrfs_node_blockptr(root_eb, i),
btrfs_node_ptr_generation(root_eb, i));
btrfs_header_owner(root_eb),
btrfs_node_ptr_generation(root_eb, i),
root_eb_level, NULL);
if (!extent_buffer_uptodate(next)) {
fprintf(stderr, "failed to read %llu in tree %llu\n",
btrfs_node_blockptr(root_eb, i),

View File

@ -111,7 +111,7 @@ static int change_extent_tree_uuid(struct btrfs_fs_info *fs_info, uuid_t new_fsi
goto next;
bytenr = key.objectid;
eb = read_tree_block(fs_info, bytenr, 0);
eb = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL);
if (IS_ERR(eb)) {
error("failed to read tree block: %llu", bytenr);
ret = PTR_ERR(eb);