Skip to content

Commit be6a136

Browse files
adam900710kdave
authored andcommitted
btrfs: make btrfs_submit_compressed_read() subpage compatible
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>
1 parent d70cef0 commit be6a136

1 file changed

Lines changed: 17 additions & 6 deletions

File tree

fs/btrfs/compression.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
640640
read_lock(&em_tree->lock);
641641
em = lookup_extent_mapping(em_tree,
642642
page_offset(bio_first_page_all(bio)),
643-
PAGE_SIZE);
643+
fs_info->sectorsize);
644644
read_unlock(&em_tree->lock);
645645
if (!em)
646646
return BLK_STS_IOERR;
@@ -698,19 +698,30 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
698698
refcount_set(&cb->pending_bios, 1);
699699

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

704+
/*
705+
* To handle subpage case, we need to make sure the bio only
706+
* covers the range we need.
707+
*
708+
* If we're at the last page, truncate the length to only cover
709+
* the remaining part.
710+
*/
711+
if (pg_index == nr_pages - 1)
712+
pg_len = min_t(u32, PAGE_SIZE,
713+
compressed_len - pg_index * PAGE_SIZE);
714+
703715
page = cb->compressed_pages[pg_index];
704716
page->mapping = inode->i_mapping;
705717
page->index = em_start >> PAGE_SHIFT;
706718

707719
if (comp_bio->bi_iter.bi_size)
708-
submit = btrfs_bio_fits_in_stripe(page, PAGE_SIZE,
720+
submit = btrfs_bio_fits_in_stripe(page, pg_len,
709721
comp_bio, 0);
710722

711723
page->mapping = NULL;
712-
if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) <
713-
PAGE_SIZE) {
724+
if (submit || bio_add_page(comp_bio, page, pg_len, 0) < pg_len) {
714725
unsigned int nr_sectors;
715726

716727
ret = btrfs_bio_wq_end_io(fs_info, comp_bio,
@@ -743,9 +754,9 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
743754
comp_bio->bi_private = cb;
744755
comp_bio->bi_end_io = end_compressed_bio_read;
745756

746-
bio_add_page(comp_bio, page, PAGE_SIZE, 0);
757+
bio_add_page(comp_bio, page, pg_len, 0);
747758
}
748-
cur_disk_byte += PAGE_SIZE;
759+
cur_disk_byte += pg_len;
749760
}
750761

751762
ret = btrfs_bio_wq_end_io(fs_info, comp_bio, BTRFS_WQ_ENDIO_DATA);

0 commit comments

Comments
 (0)