Skip to content

Commit

Permalink
btrfs: make btrfs_submit_compressed_read() subpage compatible
Browse files Browse the repository at this point in the history
For compressed read, we always submit page read using page size.  This
doesn't work well with subpage, as for subpage one page can contain
several sectors.  Such submission will read range out of what we want,
and cause problems.

Thankfully to make it subpage compatible, we only need to change how the
last page of the compressed extent is read.

Instead of always adding a full page to the compressed read bio, if we're
at the last page, calculate the size using compressed length, so that we
only add part of the range into the compressed read bio.

Since we are here, also change the PAGE_SIZE used in
lookup_extent_mapping() to sectorsize.
This modification won't cause any functional change, as
lookup_extent_mapping() can handle the case where the search range is
larger than found extent range.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
Qu Wenruo authored and David Sterba committed Feb 22, 2021
1 parent d70cef0 commit be6a136
Showing 1 changed file with 17 additions and 6 deletions.
23 changes: 17 additions & 6 deletions fs/btrfs/compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
read_lock(&em_tree->lock);
em = lookup_extent_mapping(em_tree,
page_offset(bio_first_page_all(bio)),
PAGE_SIZE);
fs_info->sectorsize);
read_unlock(&em_tree->lock);
if (!em)
return BLK_STS_IOERR;
Expand Down Expand Up @@ -698,19 +698,30 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
refcount_set(&cb->pending_bios, 1);

for (pg_index = 0; pg_index < nr_pages; pg_index++) {
u32 pg_len = PAGE_SIZE;
int submit = 0;

/*
* To handle subpage case, we need to make sure the bio only
* covers the range we need.
*
* If we're at the last page, truncate the length to only cover
* the remaining part.
*/
if (pg_index == nr_pages - 1)
pg_len = min_t(u32, PAGE_SIZE,
compressed_len - pg_index * PAGE_SIZE);

page = cb->compressed_pages[pg_index];
page->mapping = inode->i_mapping;
page->index = em_start >> PAGE_SHIFT;

if (comp_bio->bi_iter.bi_size)
submit = btrfs_bio_fits_in_stripe(page, PAGE_SIZE,
submit = btrfs_bio_fits_in_stripe(page, pg_len,
comp_bio, 0);

page->mapping = NULL;
if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) <
PAGE_SIZE) {
if (submit || bio_add_page(comp_bio, page, pg_len, 0) < pg_len) {
unsigned int nr_sectors;

ret = btrfs_bio_wq_end_io(fs_info, comp_bio,
Expand Down Expand Up @@ -743,9 +754,9 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
comp_bio->bi_private = cb;
comp_bio->bi_end_io = end_compressed_bio_read;

bio_add_page(comp_bio, page, PAGE_SIZE, 0);
bio_add_page(comp_bio, page, pg_len, 0);
}
cur_disk_byte += PAGE_SIZE;
cur_disk_byte += pg_len;
}

ret = btrfs_bio_wq_end_io(fs_info, comp_bio, BTRFS_WQ_ENDIO_DATA);
Expand Down

0 comments on commit be6a136

Please sign in to comment.