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;
>