diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/compression.c | 18 | 
1 files changed, 17 insertions, 1 deletions
| diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 7f11ef559be6..56d970434b4b 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -1138,6 +1138,22 @@ void __cold btrfs_exit_compress(void)  }  /* + * The bvec is a single page bvec from a bio that contains folios from a filemap. + * + * Since the folio may be a large one, and if the bv_page is not a head page of + * a large folio, then page->index is unreliable. + * + * Thus we need this helper to grab the proper file offset. + */ +static u64 file_offset_from_bvec(const struct bio_vec *bvec) +{ +	const struct page *page = bvec->bv_page; +	const struct folio *folio = page_folio(page); + +	return (page_pgoff(folio, page) << PAGE_SHIFT) + bvec->bv_offset; +} + +/*   * Copy decompressed data from working buffer to pages.   *   * @buf:		The decompressed data buffer @@ -1188,7 +1204,7 @@ int btrfs_decompress_buf2page(const char *buf, u32 buf_len,  		 * cb->start may underflow, but subtracting that value can still  		 * give us correct offset inside the full decompressed extent.  		 */ -		bvec_offset = page_offset(bvec.bv_page) + bvec.bv_offset - cb->start; +		bvec_offset = file_offset_from_bvec(&bvec) - cb->start;  		/* Haven't reached the bvec range, exit */  		if (decompressed + buf_len <= bvec_offset) | 
