Commit 5118130e authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: fix an incorrect ASSERT() condition inside lzo_decompress_bio()



[BUG]
When running btrfs/284 with 64K page size and 4K fs block size, it
crashes with the following ASSERT() triggered:

  BTRFS info (device dm-3): use lzo compression, level 1
  assertion failed: folio_size(fi.folio) == sectorsize :: 0, in lzo.c:450
  ------------[ cut here ]------------
  kernel BUG at lzo.c:450!
  Internal error: Oops - BUG: 00000000f2000800 [#1]  SMP
  CPU: 4 UID: 0 PID: 329 Comm: kworker/u37:2 Tainted: G           OE       6.19.0-rc8-custom+ #185 PREEMPT(voluntary)
  Hardware name: QEMU KVM Virtual Machine, BIOS unknown 2/2/2022
  Workqueue: btrfs-endio simple_end_io_work [btrfs]
  pc : lzo_decompress_bio+0x61c/0x630 [btrfs]
  lr : lzo_decompress_bio+0x61c/0x630 [btrfs]
  Call trace:
   lzo_decompress_bio+0x61c/0x630 [btrfs] (P)
   end_bbio_compressed_read+0x2a8/0x2c0 [btrfs]
   btrfs_bio_end_io+0xc4/0x258 [btrfs]
   btrfs_check_read_bio+0x424/0x7e0 [btrfs]
   simple_end_io_work+0x40/0xa8 [btrfs]
   process_one_work+0x168/0x3f0
   worker_thread+0x25c/0x398
   kthread+0x154/0x250
   ret_from_fork+0x10/0x20
  Code: 912a2021 b0000e00 91246000 940244e9 (d4210000)
  ---[ end trace 0000000000000000 ]---

[CAUSE]
Commit 37cc07ca ("btrfs: lzo: use folio_iter to handle
lzo_decompress_bio()") added the ASSERT() to make sure the folio size
matches the fs block size.

But the check is completely wrong, the original intention is to make
sure for bs > ps cases, we always got a large folio that covers a full fs
block.

However for bs < ps cases, a folio can never be smaller than page size,
and the ASSERT() gets triggered immediately.

[FIX]
Check the folio size against @min_folio_size instead, which will never
be smaller than PAGE_SIZE, and still cover bs > ps cases.

Fixes: 37cc07ca ("btrfs: lzo: use folio_iter to handle lzo_decompress_bio()")
Reviewed-by: default avatarFilipe Manana <fdmanana@suse.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 96a2d235
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -429,7 +429,7 @@ static void copy_compressed_segment(struct compressed_bio *cb,
int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
{
	struct workspace *workspace = list_entry(ws, struct workspace, list);
	const struct btrfs_fs_info *fs_info = cb->bbio.inode->root->fs_info;
	struct btrfs_fs_info *fs_info = cb->bbio.inode->root->fs_info;
	const u32 sectorsize = fs_info->sectorsize;
	struct folio_iter fi;
	char *kaddr;
@@ -447,7 +447,7 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
	/* There must be a compressed folio and matches the sectorsize. */
	if (unlikely(!fi.folio))
		return -EINVAL;
	ASSERT(folio_size(fi.folio) == sectorsize);
	ASSERT(folio_size(fi.folio) == btrfs_min_folio_size(fs_info));
	kaddr = kmap_local_folio(fi.folio, 0);
	len_in = read_compress_length(kaddr);
	kunmap_local(kaddr);