mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-13 14:04:05 +08:00
btrfs: introduce read_extent_buffer_subpage()
Introduce a helper, read_extent_buffer_subpage(), to do the subpage extent buffer read. The difference between regular and subpage routines are: - No page locking Here we completely rely on extent locking. Page locking can reduce the concurrency greatly, as if we lock one page to read one extent buffer, all the other extent buffers in the same page will have to wait. - Extent uptodate condition Despite the existing PageUptodate() and EXTENT_BUFFER_UPTODATE check, We also need to check btrfs_subpage::uptodate_bitmap. - No page iteration Just one page, no need to loop, this greatly simplified the subpage routine. This patch only implements the bio submit part, no endio support yet. Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
d1e86e3fc3
commit
4012daf769
@ -5701,6 +5701,73 @@ void set_extent_buffer_uptodate(struct extent_buffer *eb)
|
||||
}
|
||||
}
|
||||
|
||||
static int read_extent_buffer_subpage(struct extent_buffer *eb, int wait,
|
||||
int mirror_num)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = eb->fs_info;
|
||||
struct extent_io_tree *io_tree;
|
||||
struct page *page = eb->pages[0];
|
||||
struct bio *bio = NULL;
|
||||
int ret = 0;
|
||||
|
||||
ASSERT(!test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags));
|
||||
ASSERT(PagePrivate(page));
|
||||
io_tree = &BTRFS_I(fs_info->btree_inode)->io_tree;
|
||||
|
||||
if (wait == WAIT_NONE) {
|
||||
ret = try_lock_extent(io_tree, eb->start,
|
||||
eb->start + eb->len - 1);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
} else {
|
||||
ret = lock_extent(io_tree, eb->start, eb->start + eb->len - 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags) ||
|
||||
PageUptodate(page) ||
|
||||
btrfs_subpage_test_uptodate(fs_info, page, eb->start, eb->len)) {
|
||||
set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
|
||||
unlock_extent(io_tree, eb->start, eb->start + eb->len - 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
clear_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
|
||||
eb->read_mirror = 0;
|
||||
atomic_set(&eb->io_pages, 1);
|
||||
check_buffer_tree_ref(eb);
|
||||
btrfs_subpage_clear_error(fs_info, page, eb->start, eb->len);
|
||||
|
||||
ret = submit_extent_page(REQ_OP_READ | REQ_META, NULL, page, eb->start,
|
||||
eb->len, eb->start - page_offset(page), &bio,
|
||||
end_bio_extent_readpage, mirror_num, 0, 0,
|
||||
true);
|
||||
if (ret) {
|
||||
/*
|
||||
* In the endio function, if we hit something wrong we will
|
||||
* increase the io_pages, so here we need to decrease it for
|
||||
* error path.
|
||||
*/
|
||||
atomic_dec(&eb->io_pages);
|
||||
}
|
||||
if (bio) {
|
||||
int tmp;
|
||||
|
||||
tmp = submit_one_bio(bio, mirror_num, 0);
|
||||
if (tmp < 0)
|
||||
return tmp;
|
||||
}
|
||||
if (ret || wait != WAIT_COMPLETE)
|
||||
return ret;
|
||||
|
||||
wait_extent_bit(io_tree, eb->start, eb->start + eb->len - 1, EXTENT_LOCKED);
|
||||
if (!test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
|
||||
ret = -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num)
|
||||
{
|
||||
int i;
|
||||
@ -5717,6 +5784,9 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num)
|
||||
if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
|
||||
return 0;
|
||||
|
||||
if (eb->fs_info->sectorsize < PAGE_SIZE)
|
||||
return read_extent_buffer_subpage(eb, wait, mirror_num);
|
||||
|
||||
num_pages = num_extent_pages(eb);
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
page = eb->pages[i];
|
||||
|
Loading…
Reference in New Issue
Block a user