btrfs-progs: update read_tree_block to take a btrfs_parent_tree_check

In the kernel we've added a control struct to handle the different
checks we want to do on extent buffers when we read them.  Update our
copy of read_tree_block to take this as an argument, then update all of
the callers to use the new structure.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Josef Bacik 2023-08-23 10:33:01 -04:00 committed by David Sterba
parent a38570f9d6
commit f4e16e0238
19 changed files with 152 additions and 82 deletions

View File

@ -29,6 +29,7 @@
#include "kernel-shared/transaction.h"
#include "kernel-shared/extent_io.h"
#include "kernel-shared/file-item.h"
#include "kernel-shared/tree-checker.h"
#include "common/utils.h"
#include "common/help.h"
#include "common/extent-cache.h"
@ -172,8 +173,9 @@ static void corrupt_keys(struct btrfs_trans_handle *trans,
static int corrupt_keys_in_block(struct btrfs_fs_info *fs_info, u64 bytenr)
{
struct extent_buffer *eb;
struct btrfs_tree_parent_check check = { 0 };
eb = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL);
eb = read_tree_block(fs_info, bytenr, &check);
if (!extent_buffer_uptodate(eb))
return -EIO;;
@ -301,11 +303,14 @@ static void btrfs_corrupt_extent_tree(struct btrfs_trans_handle *trans,
for (i = 0; i < btrfs_header_nritems(eb); i++) {
struct extent_buffer *next;
struct btrfs_tree_parent_check check = {
.owner_root = btrfs_header_owner(eb),
.transid = btrfs_node_ptr_generation(eb, i),
.level = btrfs_header_level(eb) - 1,
};
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);
&check);
if (!extent_buffer_uptodate(next))
continue;
btrfs_corrupt_extent_tree(trans, root, next);
@ -860,6 +865,7 @@ static int corrupt_metadata_block(struct btrfs_fs_info *fs_info, u64 block,
char *field)
{
struct extent_buffer *eb;
struct btrfs_tree_parent_check check = { 0 };
enum btrfs_metadata_block_field corrupt_field;
int ret;
@ -869,7 +875,7 @@ static int corrupt_metadata_block(struct btrfs_fs_info *fs_info, u64 block,
return -EINVAL;
}
eb = read_tree_block(fs_info, block, 0, 0, 0, NULL);
eb = read_tree_block(fs_info, block, &check);
if (!extent_buffer_uptodate(eb)) {
error("couldn't read in tree block %s", field);
return -EINVAL;

View File

@ -25,6 +25,7 @@
#include "kernel-shared/disk-io.h"
#include "kernel-shared/volumes.h"
#include "kernel-shared/extent_io.h"
#include "kernel-shared/tree-checker.h"
#include "common/box.h"
#include "common/utils.h"
#include "common/extent-cache.h"
@ -200,7 +201,9 @@ 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, 0, 0, NULL);
struct btrfs_tree_parent_check check = { 0 };
eb = read_tree_block(fs_info, offset, &check);
if (!eb || IS_ERR(eb))
continue;
ret = add_eb_to_result(eb, result, nodesize, filter,

View File

@ -1894,11 +1894,15 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
next = btrfs_find_tree_block(gfs_info, bytenr, gfs_info->nodesize);
if (!next || !btrfs_buffer_uptodate(next, ptr_gen, 0)) {
struct btrfs_tree_parent_check check = {
.owner_root = btrfs_header_owner(cur),
.transid = ptr_gen,
.level = *level - 1,
};
free_extent_buffer(next);
reada_walk_down(root, cur, path->slots[*level]);
next = read_tree_block(gfs_info, bytenr,
btrfs_header_owner(cur), ptr_gen,
*level - 1, NULL);
next = read_tree_block(gfs_info, bytenr, &check);
if (!extent_buffer_uptodate(next)) {
struct btrfs_key node_key;
@ -6205,6 +6209,7 @@ static int run_next_block(struct btrfs_root *root,
{
struct extent_buffer *buf;
struct extent_record *rec = NULL;
struct btrfs_tree_parent_check check = { 0 };
u64 bytenr;
u32 size;
u64 parent;
@ -6261,7 +6266,8 @@ static int run_next_block(struct btrfs_root *root,
}
/* fixme, get the real parent transid */
buf = read_tree_block(gfs_info, bytenr, 0, gen, 0, NULL);
check.transid = gen;
buf = read_tree_block(gfs_info, bytenr, &check);
if (!extent_buffer_uptodate(buf)) {
record_bad_block_io(extent_cache, bytenr, size);
goto out;
@ -8603,12 +8609,15 @@ static int deal_root_from_list(struct list_head *list,
while (!list_empty(list)) {
struct root_item_record *rec;
struct extent_buffer *buf;
struct btrfs_tree_parent_check check = { 0 };
rec = list_entry(list->next,
struct root_item_record, list);
last = 0;
buf = read_tree_block(gfs_info, rec->bytenr, rec->objectid, 0,
rec->level, NULL);
check.owner_root = rec->objectid;
check.level = rec->level;
buf = read_tree_block(gfs_info, rec->bytenr, &check);
if (!extent_buffer_uptodate(buf)) {
free_extent_buffer(buf);
ret = -EIO;

View File

@ -29,6 +29,7 @@
#include "kernel-shared/backref.h"
#include "kernel-shared/compression.h"
#include "kernel-shared/file-item.h"
#include "kernel-shared/tree-checker.h"
#include "common/internal.h"
#include "common/messages.h"
#include "common/utils.h"
@ -127,11 +128,12 @@ next:
static int check_prealloc_shared_data_ref(u64 parent, u64 disk_bytenr)
{
struct extent_buffer *eb;
struct btrfs_tree_parent_check check = { 0 };
u32 nr;
int i;
int ret = 0;
eb = read_tree_block(gfs_info, parent, 0, 0, 0, NULL);
eb = read_tree_block(gfs_info, parent, &check);
if (!extent_buffer_uptodate(eb)) {
ret = -EIO;
goto out;
@ -1116,8 +1118,9 @@ int get_extent_item_generation(u64 bytenr, u64 *gen_ret)
if (btrfs_extent_flags(path.nodes[0], ei) &
BTRFS_EXTENT_FLAG_TREE_BLOCK) {
struct extent_buffer *eb;
struct btrfs_tree_parent_check check = { 0 };
eb = read_tree_block(gfs_info, bytenr, 0, 0, 0, NULL);
eb = read_tree_block(gfs_info, bytenr, &check);
if (extent_buffer_uptodate(eb)) {
*gen_ret = btrfs_header_generation(eb);
ret = 0;

View File

@ -3684,6 +3684,7 @@ static int query_tree_block_level(u64 bytenr)
struct btrfs_path path = { 0 };
struct btrfs_key key;
struct btrfs_extent_item *ei;
struct btrfs_tree_parent_check check = { 0 };
u64 flags;
u64 transid;
u8 backref_level;
@ -3731,7 +3732,8 @@ 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, 0, transid, 0, NULL);
check.transid = transid;
eb = read_tree_block(gfs_info, bytenr, &check);
if (!extent_buffer_uptodate(eb)) {
free_extent_buffer(eb);
return -EIO;
@ -3760,6 +3762,9 @@ static int check_tree_block_backref(u64 root_id, u64 bytenr, int level)
struct btrfs_path path = { 0 };
struct extent_buffer *eb;
struct extent_buffer *node;
struct btrfs_tree_parent_check check = {
.owner_root = root_id,
};
u32 nodesize = btrfs_super_nodesize(gfs_info->super_copy);
int err = 0;
int ret;
@ -3783,7 +3788,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, root_id, 0, 0, NULL);
eb = read_tree_block(gfs_info, bytenr, &check);
if (!extent_buffer_uptodate(eb)) {
err |= REFERENCER_MISSING;
free_extent_buffer(eb);
@ -3877,11 +3882,12 @@ static int is_tree_reloc_root(struct extent_buffer *eb)
static int check_shared_block_backref(u64 parent, u64 bytenr, int level)
{
struct extent_buffer *eb;
struct btrfs_tree_parent_check check = { 0 };
u32 nr;
int found_parent = 0;
int i;
eb = read_tree_block(gfs_info, parent, 0, 0, 0, NULL);
eb = read_tree_block(gfs_info, parent, &check);
if (!extent_buffer_uptodate(eb))
goto out;
@ -4048,11 +4054,12 @@ static int check_shared_data_backref(u64 parent, u64 bytenr)
struct extent_buffer *eb;
struct btrfs_key key;
struct btrfs_file_extent_item *fi;
struct btrfs_tree_parent_check check = { 0 };
u32 nr;
int found_parent = 0;
int i;
eb = read_tree_block(gfs_info, parent, 0, 0, 0, NULL);
eb = read_tree_block(gfs_info, parent, &check);
if (!extent_buffer_uptodate(eb))
goto out;
@ -5018,11 +5025,15 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
next = btrfs_find_tree_block(gfs_info, bytenr, gfs_info->nodesize);
if (!next || !btrfs_buffer_uptodate(next, ptr_gen, 0)) {
struct btrfs_tree_parent_check check = {
.owner_root = btrfs_header_owner(cur),
.transid = ptr_gen,
.level = *level - 1,
};
free_extent_buffer(next);
reada_walk_down(root, cur, path->slots[*level]);
next = read_tree_block(gfs_info, bytenr,
btrfs_header_owner(cur),
ptr_gen, *level - 1, NULL);
next = read_tree_block(gfs_info, bytenr, &check);
if (!extent_buffer_uptodate(next)) {
struct btrfs_key node_key;

View File

@ -30,6 +30,7 @@
#include "kernel-shared/ulist.h"
#include "kernel-shared/extent_io.h"
#include "kernel-shared/transaction.h"
#include "kernel-shared/tree-checker.h"
#include "common/messages.h"
#include "common/rbtree-utils.h"
#include "check/repair.h"
@ -716,14 +717,16 @@ static int travel_tree(struct btrfs_fs_info *info, struct btrfs_root *root,
{
int ret, nr, i;
struct extent_buffer *eb;
struct btrfs_tree_parent_check check = {
.owner_root = btrfs_root_id(root),
};
u64 new_bytenr;
u64 new_num_bytes;
// printf("travel_tree: bytenr: %llu\tnum_bytes: %llu\tref_parent: %llu\n",
// bytenr, num_bytes, ref_parent);
eb = read_tree_block(info, bytenr, btrfs_root_id(root), 0,
0, NULL);
eb = read_tree_block(info, bytenr, &check);
if (!extent_buffer_uptodate(eb))
return -EIO;
@ -1056,7 +1059,6 @@ static int simple_quota_account_extent(struct btrfs_fs_info *info,
struct ulist *roots = ulist_alloc(0);
int ret;
struct extent_buffer *node_eb;
u64 extent_root;
generation = btrfs_extent_generation(leaf, ei);
if (generation < counts.enable_gen)
@ -1073,8 +1075,10 @@ static int simple_quota_account_extent(struct btrfs_fs_info *info,
return 0;
}
} else {
extent_root = btrfs_root_id(btrfs_extent_root(info, key->objectid));
node_eb = read_tree_block(info, key->objectid, extent_root, 0, 0, NULL);
struct btrfs_tree_parent_check check = { 0 };
check.owner_root = btrfs_root_id(btrfs_extent_root(info, key->objectid));
node_eb = read_tree_block(info, key->objectid, &check);
if (!extent_buffer_uptodate(node_eb))
return -EIO;
root = btrfs_header_owner(node_eb);

View File

@ -132,6 +132,8 @@ static int traverse_tree_blocks(struct extent_io_tree *tree,
nritems = btrfs_header_nritems(eb);
for (i = 0; i < nritems; i++) {
struct btrfs_tree_parent_check check = { 0 };
if (level == 0) {
bool is_extent_root;
btrfs_item_key_to_cpu(eb, &key, i);
@ -145,15 +147,16 @@ static int traverse_tree_blocks(struct extent_io_tree *tree,
ri = btrfs_item_ptr(eb, i, struct btrfs_root_item);
bytenr = btrfs_disk_root_bytenr(eb, ri);
check.owner_root = key.objectid;
check.level = btrfs_disk_root_level(eb, ri);
/*
* If at any point we start needing the real root we
* will have to build a stump root for the root we are
* in, but for now this doesn't actually use the root so
* just pass in extent_root.
*/
tmp = read_tree_block(fs_info, bytenr, key.objectid, 0,
btrfs_disk_root_level(eb, ri),
NULL);
tmp = read_tree_block(fs_info, bytenr, &check);
if (!extent_buffer_uptodate(tmp)) {
fprintf(stderr, "Error reading root block\n");
return -EIO;
@ -178,9 +181,10 @@ static int traverse_tree_blocks(struct extent_io_tree *tree,
continue;
}
tmp = read_tree_block(fs_info, bytenr,
btrfs_header_owner(eb), 0,
level - 1, NULL);
check.owner_root = btrfs_header_owner(eb);
check.level = level - 1;
tmp = read_tree_block(fs_info, bytenr, &check);
if (!extent_buffer_uptodate(tmp)) {
fprintf(stderr, "Error reading tree block\n");
return -EIO;

View File

@ -32,6 +32,7 @@
#include "kernel-shared/print-tree.h"
#include "kernel-shared/volumes.h"
#include "kernel-shared/extent_io.h"
#include "kernel-shared/tree-checker.h"
#include "common/defs.h"
#include "common/extent-cache.h"
#include "common/messages.h"
@ -58,10 +59,14 @@ static void print_extents(struct extent_buffer *eb)
nr = btrfs_header_nritems(eb);
for (i = 0; i < nr; i++) {
struct btrfs_tree_parent_check check = {
.owner_root = btrfs_header_owner(eb),
.transid = btrfs_node_ptr_generation(eb, i),
.level = btrfs_header_level(eb) - 1,
};
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);
&check);
if (!extent_buffer_uptodate(next))
continue;
if (btrfs_is_leaf(next) && btrfs_header_level(eb) != 1) {
@ -270,6 +275,7 @@ static int dump_print_tree_blocks(struct btrfs_fs_info *fs_info,
{
struct cache_extent *ce;
struct extent_buffer *eb;
struct btrfs_tree_parent_check check = { 0 };
u64 bytenr;
int ret = 0;
@ -290,7 +296,7 @@ static int dump_print_tree_blocks(struct btrfs_fs_info *fs_info,
goto next;
}
eb = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL);
eb = read_tree_block(fs_info, bytenr, &check);
if (!extent_buffer_uptodate(eb)) {
error("failed to read tree block %llu", bytenr);
ret = -EIO;
@ -593,12 +599,14 @@ again:
if (found_key.type == BTRFS_ROOT_ITEM_KEY) {
unsigned long offset;
struct extent_buffer *buf;
struct btrfs_tree_parent_check check = {
.owner_root = key.objectid,
};
bool skip = (extent_only || device_only || uuid_tree_only);
offset = btrfs_item_ptr_offset(leaf, slot);
read_extent_buffer(leaf, &ri, offset, sizeof(ri));
buf = read_tree_block(info, btrfs_root_bytenr(&ri),
key.objectid, 0, 0, NULL);
buf = read_tree_block(info, btrfs_root_bytenr(&ri), &check);
if (!extent_buffer_uptodate(buf))
goto next;
if (tree_id && found_key.objectid != tree_id) {

View File

@ -29,6 +29,7 @@
#include "kernel-shared/disk-io.h"
#include "kernel-shared/extent_io.h"
#include "kernel-shared/file-item.h"
#include "kernel-shared/tree-checker.h"
#include "common/utils.h"
#include "common/help.h"
#include "common/messages.h"
@ -152,10 +153,12 @@ 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_header_owner(b),
btrfs_node_ptr_generation(b, i),
level - 1, NULL);
struct btrfs_tree_parent_check check = {
.owner_root = btrfs_header_owner(b),
.transid = btrfs_node_ptr_generation(b, i),
.level = level - 1,
};
tmp = read_tree_block(root->fs_info, cur_blocknr, &check);
if (!extent_buffer_uptodate(tmp)) {
error("failed to read blocknr %llu",
btrfs_node_blockptr(b, i));

View File

@ -45,6 +45,7 @@
#include "kernel-shared/extent_io.h"
#include "kernel-shared/compression.h"
#include "kernel-shared/file-item.h"
#include "kernel-shared/tree-checker.h"
#include "common/utils.h"
#include "common/help.h"
#include "common/open-utils.h"
@ -1241,15 +1242,17 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location,
* the fs_root.
*/
if (!extent_buffer_uptodate(fs_info->tree_root->node)) {
struct btrfs_tree_parent_check check = { 0 };
u64 generation;
root = fs_info->tree_root;
if (!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,
btrfs_root_id(root), generation,
0, NULL);
check.owner_root = btrfs_root_id(root);
check.transid = generation;
root->node = read_tree_block(fs_info, root_location, &check);
if (!extent_buffer_uptodate(root->node)) {
error("opening tree root failed");
close_ctree(root);
@ -1514,9 +1517,9 @@ static int cmd_restore(const struct cmd_struct *cmd, int argc, char **argv)
goto out;
if (fs_location != 0) {
struct btrfs_tree_parent_check check = { 0 };
free_extent_buffer(root->node);
root->node = read_tree_block(root->fs_info, fs_location, 0, 0,
0, NULL);
root->node = read_tree_block(root->fs_info, fs_location, &check);
if (!extent_buffer_uptodate(root->node)) {
error("failed to read fs location");
ret = 1;

View File

@ -21,6 +21,7 @@
#include "kernel-shared/file-item.h"
#include "kernel-shared/disk-io.h"
#include "kernel-shared/volumes.h"
#include "kernel-shared/tree-checker.h"
#include "crypto/crc32c.h"
#include "common/internal.h"
#include "common/messages.h"
@ -437,11 +438,11 @@ static int flush_pending(struct metadump_struct *md, int done)
}
while (!md->data && size > 0) {
struct btrfs_tree_parent_check check = { 0 };
u64 this_read = min((u64)md->root->fs_info->nodesize,
size);
eb = read_tree_block(md->root->fs_info, start, 0, 0, 0,
NULL);
eb = read_tree_block(md->root->fs_info, start, &check);
if (!extent_buffer_uptodate(eb)) {
free(async->buffer);
free(async);
@ -510,6 +511,7 @@ static int copy_tree_blocks(struct btrfs_root *root, struct extent_buffer *eb,
struct btrfs_root_item *ri;
struct btrfs_key key;
struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_tree_parent_check check = { 0 };
u64 bytenr;
int level;
int nritems = 0;
@ -545,7 +547,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, 0, 0, NULL);
tmp = read_tree_block(fs_info, bytenr, &check);
if (!extent_buffer_uptodate(tmp)) {
error("unable to read log root block");
return -EIO;
@ -556,7 +558,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, 0, 0, NULL);
tmp = read_tree_block(fs_info, bytenr, &check);
if (!extent_buffer_uptodate(tmp)) {
error("unable to read log root block");
return -EIO;

View File

@ -20,6 +20,7 @@
#include "kernel-shared/disk-io.h"
#include "kernel-shared/volumes.h"
#include "kernel-shared/transaction.h"
#include "kernel-shared/tree-checker.h"
#include "common/internal.h"
#include "common/messages.h"
#include "common/open-utils.h"
@ -1366,6 +1367,7 @@ static int iter_tree_blocks(struct btrfs_fs_info *fs_info,
struct extent_buffer *eb, bool pin)
{
void (*func)(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes);
struct btrfs_tree_parent_check check = { 0 };
int nritems;
int level;
int i;
@ -1396,7 +1398,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, 0, 0, NULL);
tmp = read_tree_block(fs_info, bytenr, &check);
if (!extent_buffer_uptodate(tmp)) {
error("unable to read log root block");
return -EIO;
@ -1407,7 +1409,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, 0, 0, NULL);
tmp = read_tree_block(fs_info, bytenr, &check);
if (!extent_buffer_uptodate(tmp)) {
error("unable to read log root block");
return -EIO;

View File

@ -41,6 +41,7 @@
#include "kernel-shared/volumes.h"
#include "kernel-shared/extent_io.h"
#include "kernel-shared/file-item.h"
#include "kernel-shared/tree-checker.h"
#include "crypto/crc32c.h"
#include "crypto/hash.h"
#include "common/internal.h"

View File

@ -23,6 +23,7 @@
#include "kernel-shared/ulist.h"
#include "kernel-shared/transaction.h"
#include "kernel-shared/messages.h"
#include "kernel-shared/tree-checker.h"
#include "common/internal.h"
#define pr_debug(...) do { } while (0)
@ -454,6 +455,7 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info,
while (!list_empty(&prefstate->pending_missing_keys)) {
struct __prelim_ref *ref;
struct btrfs_tree_parent_check check;
ref = list_first_pref(&prefstate->pending_missing_keys);
@ -461,8 +463,13 @@ 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,
ref->root_id, 0, ref->level - 1, NULL);
check.owner_root = ref->root_id;
check.transid = 0;
check.has_first_key = false;
check.level = ref->level - 1;
eb = read_tree_block(fs_info, ref->wanted_disk_byte, &check);
if (!extent_buffer_uptodate(eb)) {
free_extent_buffer(eb);
return -EIO;
@ -823,9 +830,11 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
if (extent_item_pos && !ref->inode_list &&
ref->level == 0) {
struct extent_buffer *eb;
struct btrfs_tree_parent_check check = {
.level = ref->level,
};
eb = read_tree_block(fs_info, ref->parent, 0,
0, ref->level, NULL);
eb = read_tree_block(fs_info, ref->parent, &check);
if (!extent_buffer_uptodate(eb)) {
free_extent_buffer(eb);
ret = -EIO;

View File

@ -832,6 +832,7 @@ struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent,
{
struct btrfs_fs_info *fs_info = parent->fs_info;
struct extent_buffer *ret;
struct btrfs_tree_parent_check check = { 0 };
int level = btrfs_header_level(parent);
if (slot < 0)
@ -842,10 +843,12 @@ struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent,
if (level == 0)
return NULL;
check.owner_root = btrfs_header_owner(parent);
check.transid = btrfs_node_ptr_generation(parent, slot);
check.level = level - 1;
ret = read_tree_block(fs_info, btrfs_node_blockptr(parent, slot),
btrfs_header_owner(parent),
btrfs_node_ptr_generation(parent, slot),
level - 1, NULL);
&check);
if (!extent_buffer_uptodate(ret))
return ERR_PTR(-EIO);

View File

@ -417,23 +417,12 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb,
}
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)
struct btrfs_tree_parent_check *check)
{
struct btrfs_tree_parent_check check = {
.owner_root = owner_root,
.transid = parent_transid,
.level = level,
};
int ret;
struct extent_buffer *eb;
u32 sectorsize = fs_info->sectorsize;
if (first_key) {
check.has_first_key = true;
memcpy(&check.first_key, first_key, sizeof(*first_key));
}
/*
* Don't even try to create tree block for unaligned tree block
* bytenr.
@ -450,10 +439,10 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
if (!eb)
return ERR_PTR(-ENOMEM);
if (btrfs_buffer_uptodate(eb, parent_transid, 0))
if (btrfs_buffer_uptodate(eb, check->transid, 0))
return eb;
ret = btrfs_read_extent_buffer(eb, &check);
ret = btrfs_read_extent_buffer(eb, check);
if (ret) {
/*
* We failed to read this tree block, it be should deleted right
@ -508,8 +497,13 @@ 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, btrfs_root_id(root),
gen, level, NULL);
struct btrfs_tree_parent_check check = {
.owner_root = btrfs_root_id(root),
.transid = gen,
.level = level,
};
root->node = read_tree_block(fs_info, bytenr, &check);
if (!extent_buffer_uptodate(root->node))
goto err;
if (btrfs_header_level(root->node) != level) {

View File

@ -152,8 +152,7 @@ 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 owner_root, u64 parent_transid,
int level, struct btrfs_key *first_key);
struct btrfs_tree_parent_check *check);
void readahead_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
u64 parent_transid);

View File

@ -28,6 +28,7 @@
#include "kernel-shared/compression.h"
#include "kernel-shared/accessors.h"
#include "kernel-shared/file-item.h"
#include "kernel-shared/tree-checker.h"
#include "common/utils.h"
static void print_dir_item_type(struct extent_buffer *eb,
@ -1687,10 +1688,13 @@ static void dfs_print_children(struct extent_buffer *root_eb, unsigned int mode)
mode &= ~(BTRFS_PRINT_TREE_BFS);
for (i = 0; i < nr; i++) {
struct btrfs_tree_parent_check check = {
.owner_root = btrfs_header_owner(root_eb),
.transid = btrfs_node_ptr_generation(root_eb, i),
.level = root_eb_level,
};
next = read_tree_block(fs_info, btrfs_node_blockptr(root_eb, i),
btrfs_header_owner(root_eb),
btrfs_node_ptr_generation(root_eb, i),
root_eb_level, NULL);
&check);
if (!extent_buffer_uptodate(next)) {
fprintf(stderr, "failed to read %llu in tree %llu\n",
btrfs_node_blockptr(root_eb, i),

View File

@ -24,6 +24,7 @@
#include "kernel-shared/disk-io.h"
#include "kernel-shared/extent_io.h"
#include "kernel-shared/volumes.h"
#include "kernel-shared/tree-checker.h"
#include "common/defs.h"
#include "common/messages.h"
#include "tune/tune.h"
@ -97,6 +98,7 @@ static int change_extent_tree_uuid(struct btrfs_fs_info *fs_info, uuid_t new_fsi
while (1) {
struct btrfs_extent_item *ei;
struct extent_buffer *eb;
struct btrfs_tree_parent_check check = { 0 };
u64 flags;
u64 bytenr;
@ -111,7 +113,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, 0, 0, NULL);
eb = read_tree_block(fs_info, bytenr, &check);
if (IS_ERR(eb)) {
error("failed to read tree block: %llu", bytenr);
ret = PTR_ERR(eb);