From: Qu Wenruo Date: Thu, 19 Feb 2026 08:21:14 +0000 (+1030) Subject: btrfs: fix an incorrect ASSERT() condition inside lzo_decompress_bio() X-Git-Tag: v7.0-rc5~13^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5118130e722b1261a2e92b2fb0b067463c39ecc7;p=thirdparty%2Flinux.git 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 37cc07cab7dc ("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: 37cc07cab7dc ("btrfs: lzo: use folio_iter to handle lzo_decompress_bio()") Reviewed-by: Filipe Manana Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c index 8e20497afffe..971c2ea98e18 100644 --- a/fs/btrfs/lzo.c +++ b/fs/btrfs/lzo.c @@ -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);