btrfs-progs: add a btrfs_read_extent_buffer helper

This exists in the kernel to do the read on an extent buffer we may have
already looked up and initialized.  Simply create this helper by
extracting out the existing code from read_tree_block and make
read_tree_block call this helper.  This gives us the helper we need to
sync ctree.c into btrfs-progs, and keeps the code the same in
btrfs-progs.

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:24:05 -04:00 committed by David Sterba
parent e176d5eab6
commit a474379935
2 changed files with 45 additions and 29 deletions

View file

@ -337,39 +337,18 @@ int read_whole_eb(struct btrfs_fs_info *info, struct extent_buffer *eb, int mirr
return 0; return 0;
} }
struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, int btrfs_read_extent_buffer(struct extent_buffer *eb, u64 parent_transid,
u64 owner_root, u64 parent_transid, int level, struct btrfs_key *first_key)
int level, struct btrfs_key *first_key)
{ {
struct btrfs_fs_info *fs_info = eb->fs_info;
int ret; int ret;
struct extent_buffer *eb;
u64 best_transid = 0; u64 best_transid = 0;
u32 sectorsize = fs_info->sectorsize;
int mirror_num = 1; int mirror_num = 1;
int good_mirror = 0; int good_mirror = 0;
int candidate_mirror = 0; int candidate_mirror = 0;
int num_copies; int num_copies;
int ignore = 0; int ignore = 0;
/*
* Don't even try to create tree block for unaligned tree block
* bytenr.
* Such unaligned tree block will free overlapping extent buffer,
* causing use-after-free bugs for fuzzed images.
*/
if (bytenr < sectorsize || !IS_ALIGNED(bytenr, sectorsize)) {
error("tree block bytenr %llu is not aligned to sectorsize %u",
bytenr, sectorsize);
return ERR_PTR(-EIO);
}
eb = btrfs_find_create_tree_block(fs_info, bytenr);
if (!eb)
return ERR_PTR(-ENOMEM);
if (btrfs_buffer_uptodate(eb, parent_transid, 0))
return eb;
num_copies = btrfs_num_copies(fs_info, eb->start, eb->len); num_copies = btrfs_num_copies(fs_info, eb->start, eb->len);
while (1) { while (1) {
ret = read_whole_eb(fs_info, eb, mirror_num); ret = read_whole_eb(fs_info, eb, mirror_num);
@ -396,7 +375,7 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
ret = btrfs_check_leaf(eb); ret = btrfs_check_leaf(eb);
if (!ret || candidate_mirror == mirror_num) { if (!ret || candidate_mirror == mirror_num) {
btrfs_set_buffer_uptodate(eb); btrfs_set_buffer_uptodate(eb);
return eb; return 0;
} }
if (candidate_mirror <= 0) if (candidate_mirror <= 0)
candidate_mirror = mirror_num; candidate_mirror = mirror_num;
@ -439,12 +418,47 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
continue; continue;
} }
} }
return ret;
}
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;
u32 sectorsize = fs_info->sectorsize;
/* /*
* We failed to read this tree block, it be should deleted right now * Don't even try to create tree block for unaligned tree block
* to avoid stale cache populate the cache. * bytenr.
* Such unaligned tree block will free overlapping extent buffer,
* causing use-after-free bugs for fuzzed images.
*/ */
free_extent_buffer_nocache(eb); if (bytenr < sectorsize || !IS_ALIGNED(bytenr, sectorsize)) {
return ERR_PTR(ret); error("tree block bytenr %llu is not aligned to sectorsize %u",
bytenr, sectorsize);
return ERR_PTR(-EIO);
}
eb = btrfs_find_create_tree_block(fs_info, bytenr);
if (!eb)
return ERR_PTR(-ENOMEM);
if (btrfs_buffer_uptodate(eb, parent_transid, 0))
return eb;
ret = btrfs_read_extent_buffer(eb, parent_transid, level, first_key);
if (ret) {
/*
* We failed to read this tree block, it be should deleted right
* now to avoid stale cache populate the cache.
*/
free_extent_buffer_nocache(eb);
return ERR_PTR(ret);
}
return eb;
} }
int write_and_map_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) int write_and_map_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb)

View file

@ -233,6 +233,8 @@ int btrfs_global_root_insert(struct btrfs_fs_info *fs_info,
int btrfs_find_and_setup_root(struct btrfs_root *tree_root, int btrfs_find_and_setup_root(struct btrfs_root *tree_root,
struct btrfs_fs_info *fs_info, struct btrfs_fs_info *fs_info,
u64 objectid, struct btrfs_root *root); u64 objectid, struct btrfs_root *root);
int btrfs_read_extent_buffer(struct extent_buffer *eb, u64 parent_transid,
int level, struct btrfs_key *first_key);
static inline struct btrfs_root *btrfs_block_group_root( static inline struct btrfs_root *btrfs_block_group_root(
struct btrfs_fs_info *fs_info) struct btrfs_fs_info *fs_info)