Commit 371cdc07 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: introduce subpage metadata validation check

For subpage metadata validation check, there are some differences:

- Read must finish in one bvec
  Since we're just reading one subpage range in one page, it should
  never be split into two bios nor two bvecs.

- How to grab the existing eb
  Instead of grabbing eb using page->private, we have to go search radix
  tree as we don't have any direct pointer at hand.
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 4325cb22
......@@ -591,6 +591,59 @@ static int validate_extent_buffer(struct extent_buffer *eb)
return ret;
}
static int validate_subpage_buffer(struct page *page, u64 start, u64 end,
int mirror)
{
struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
struct extent_buffer *eb;
bool reads_done;
int ret = 0;
/*
* We don't allow bio merge for subpage metadata read, so we should
* only get one eb for each endio hook.
*/
ASSERT(end == start + fs_info->nodesize - 1);
ASSERT(PagePrivate(page));
eb = find_extent_buffer(fs_info, start);
/*
* When we are reading one tree block, eb must have been inserted into
* the radix tree. If not, something is wrong.
*/
ASSERT(eb);
reads_done = atomic_dec_and_test(&eb->io_pages);
/* Subpage read must finish in page read */
ASSERT(reads_done);
eb->read_mirror = mirror;
if (test_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags)) {
ret = -EIO;
goto err;
}
ret = validate_extent_buffer(eb);
if (ret < 0)
goto err;
if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
btree_readahead_hook(eb, ret);
set_extent_buffer_uptodate(eb);
free_extent_buffer(eb);
return ret;
err:
/*
* end_bio_extent_readpage decrements io_pages in case of error,
* make sure it has something to decrement.
*/
atomic_inc(&eb->io_pages);
clear_extent_buffer_uptodate(eb);
free_extent_buffer(eb);
return ret;
}
int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio,
struct page *page, u64 start, u64 end,
int mirror)
......@@ -600,6 +653,10 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio,
int reads_done;
ASSERT(page->private);
if (btrfs_sb(page->mapping->host->i_sb)->sectorsize < PAGE_SIZE)
return validate_subpage_buffer(page, start, end, mirror);
eb = (struct extent_buffer *)page->private;
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment