Re: [PATCH] btrfs: disable large folios for systems with highmem
Qu Wenruo <[email protected]> Tue, 21 Jul 2026 07:03:05 +0930
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <[email protected]> |
在 2026/7/20 19:19, Qu Wenruo 写道: > [BUG] > There is a bug report that on 32bit systems (i686), btrfs crashes when > trying to do zstd compression: > > BUG: unable to handle page fault for address: fffbc000 > #PF: supervisor read access in kernel mode > #PF: error_code(0x0000) - not-present page > CPU: 0 UID: 0 PID: 61 Comm: kworker/u8:5 Tainted: G N 7.2.0-rc3-P3 #2 PREEMPTLAZY > Hardware name: LENOVO 2007F2G/2007F2G, BIOS 79ETE7WW (2.27 ) 03/21/2011 > Workqueue: btrfs-delalloc btrfs_work_helper > EIP: ZSTD_compressStream2+0x221/0x5fc > Call Trace: > ZSTD_compressStream+0xd/0x48 > zstd_compress_stream+0x8/0x10 > zstd_compress_bio+0x20a/0x564 > btrfs_compress_bio+0x94/0xc0 > compress_file_range+0x20a/0x380 > btrfs_work_helper+0xc1/0x1b4 > process_scheduled_works+0x15f/0x204 > worker_thread+0x10c/0x178 > kthread+0xe1/0xe8 > ret_from_fork+0x1d/0x14c > ret_from_fork_asm+0x12/0x18 > entry_INT80_32+0xf0/0xf0 > CR2: 00000000fffbc000 > ---[ end trace 0000000000000000 ]--- > > [CAUSE] > Inside zstd_compress_bio(), we assume the whole page cache folio can be > mapped in one go. > > However that assumption is not true on systems with CONFIG_HIGHMEM, the > pages of the large folio can be in HIGHMEM, which needs to be mapped > before access. > > Meanwhile zstd_compress_bio() only map the page of a large folio where > the start filepos is, the remaining pages are not mapped, and accessing > the remaining pages will trigger the above crash. > > [FIX] > Do not enable large folios when the kernel has CONFIG_HIGHMEM enabled. > > This is the same handling for bs > ps support. > > Link: https://github.com/kdave/btrfs-progs/issues/1146 Reported-by: Erhard Furtner <[email protected]> > Fixes: 9bce95edb1b4 ("btrfs: move large data folios out of experimental features") > Signed-off-by: Qu Wenruo <[email protected]> > --- > fs/btrfs/disk-io.c | 10 +++++++++- > 1 file changed, 9 insertions(+), 1 deletion(-) > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 37fc0d6b960d..5de8210070eb 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -3477,7 +3477,15 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device > fs_info->sectorsize = sectorsize; > fs_info->sectorsize_bits = ilog2(sectorsize); > fs_info->block_min_order = ilog2(round_up(sectorsize, PAGE_SIZE) >> PAGE_SHIFT); > - fs_info->block_max_order = calc_block_max_order(fs_info->sectorsize_bits); > + /* > + * For HIGHMEM, a large folio cannot be mapped in one go, breaking a lot > + * of basic assumptions for btrfs IOs. > + * Disable large folios for such 32-bit systems. > + */ > + if (IS_ENABLED(CONFIG_HIGHMEM)) > + fs_info->block_max_order = fs_info->block_min_order; > + else > + fs_info->block_max_order = calc_block_max_order(fs_info->sectorsize_bits); > fs_info->csums_per_leaf = BTRFS_MAX_ITEM_SIZE(fs_info) / fs_info->csum_size; > fs_info->fs_devices->fs_info = fs_info; >