提交 77bf40a2 编写于 作者: Q Qu Wenruo 提交者: David Sterba

btrfs: extract extent buffer verification from btrfs_validate_metadata_buffer()

Currently btrfs_validate_metadata_buffer() only needs to handle one
extent buffer as currently one page maps to at most one extent buffer.

For incoming subpage support, we need to extend the support where one
page could contain multiple extent buffers.

Split the function so we can call validate_extent_buffer on extent
buffers independently.
Reviewed-by: NNikolay Borisov <nborisov@suse.com>
Signed-off-by: NQu Wenruo <wqu@suse.com>
Reviewed-by: NDavid Sterba <dsterba@suse.com>
Signed-off-by: NDavid Sterba <dsterba@suse.com>
上级 a26663e7
...@@ -523,60 +523,35 @@ static int check_tree_block_fsid(struct extent_buffer *eb) ...@@ -523,60 +523,35 @@ static int check_tree_block_fsid(struct extent_buffer *eb)
return 1; return 1;
} }
int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset, /* Do basic extent buffer checks at read time */
struct page *page, u64 start, u64 end, static int validate_extent_buffer(struct extent_buffer *eb)
int mirror)
{ {
struct btrfs_fs_info *fs_info = eb->fs_info;
u64 found_start; u64 found_start;
int found_level; const u32 csum_size = fs_info->csum_size;
struct extent_buffer *eb; u8 found_level;
struct btrfs_fs_info *fs_info;
u16 csum_size;
int ret = 0;
u8 result[BTRFS_CSUM_SIZE]; u8 result[BTRFS_CSUM_SIZE];
int reads_done; int ret = 0;
if (!page->private)
goto out;
eb = (struct extent_buffer *)page->private;
fs_info = eb->fs_info;
csum_size = fs_info->csum_size;
/* the pending IO might have been the only thing that kept this buffer
* in memory. Make sure we have a ref for all this other checks
*/
atomic_inc(&eb->refs);
reads_done = atomic_dec_and_test(&eb->io_pages);
if (!reads_done)
goto err;
eb->read_mirror = mirror;
if (test_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags)) {
ret = -EIO;
goto err;
}
found_start = btrfs_header_bytenr(eb); found_start = btrfs_header_bytenr(eb);
if (found_start != eb->start) { if (found_start != eb->start) {
btrfs_err_rl(fs_info, "bad tree block start, want %llu have %llu", btrfs_err_rl(fs_info, "bad tree block start, want %llu have %llu",
eb->start, found_start); eb->start, found_start);
ret = -EIO; ret = -EIO;
goto err; goto out;
} }
if (check_tree_block_fsid(eb)) { if (check_tree_block_fsid(eb)) {
btrfs_err_rl(fs_info, "bad fsid on block %llu", btrfs_err_rl(fs_info, "bad fsid on block %llu",
eb->start); eb->start);
ret = -EIO; ret = -EIO;
goto err; goto out;
} }
found_level = btrfs_header_level(eb); found_level = btrfs_header_level(eb);
if (found_level >= BTRFS_MAX_LEVEL) { if (found_level >= BTRFS_MAX_LEVEL) {
btrfs_err(fs_info, "bad tree block level %d on %llu", btrfs_err(fs_info, "bad tree block level %d on %llu",
(int)btrfs_header_level(eb), eb->start); (int)btrfs_header_level(eb), eb->start);
ret = -EIO; ret = -EIO;
goto err; goto out;
} }
btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb), btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb),
...@@ -595,7 +570,7 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset, ...@@ -595,7 +570,7 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset,
CSUM_FMT_VALUE(csum_size, result), CSUM_FMT_VALUE(csum_size, result),
btrfs_header_level(eb)); btrfs_header_level(eb));
ret = -EUCLEAN; ret = -EUCLEAN;
goto err; goto out;
} }
/* /*
...@@ -617,6 +592,37 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset, ...@@ -617,6 +592,37 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset,
btrfs_err(fs_info, btrfs_err(fs_info,
"block=%llu read time tree block corruption detected", "block=%llu read time tree block corruption detected",
eb->start); eb->start);
out:
return ret;
}
int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset,
struct page *page, u64 start, u64 end,
int mirror)
{
struct extent_buffer *eb;
int ret = 0;
int reads_done;
ASSERT(page->private);
eb = (struct extent_buffer *)page->private;
/*
* The pending IO might have been the only thing that kept this buffer
* in memory. Make sure we have a ref for all this other checks
*/
atomic_inc(&eb->refs);
reads_done = atomic_dec_and_test(&eb->io_pages);
if (!reads_done)
goto err;
eb->read_mirror = mirror;
if (test_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags)) {
ret = -EIO;
goto err;
}
ret = validate_extent_buffer(eb);
err: err:
if (reads_done && if (reads_done &&
test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
...@@ -632,7 +638,7 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset, ...@@ -632,7 +638,7 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset,
clear_extent_buffer_uptodate(eb); clear_extent_buffer_uptodate(eb);
} }
free_extent_buffer(eb); free_extent_buffer(eb);
out:
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册