From: Qu Wenruo Date: Thu, 19 Feb 2026 08:21:12 +0000 (+1030) Subject: btrfs: do not touch page cache for encoded writes X-Git-Tag: v7.0-rc5~13^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3adf8f14152fba1cae51f9b0d3570a1da2153b16;p=thirdparty%2Fkernel%2Flinux.git btrfs: do not touch page cache for encoded writes [BUG] When running btrfs/284, the following ASSERT() will be triggered with 64K page size and 4K fs block size: assertion failed: folio_test_writeback(folio) :: 0, in subpage.c:476 ------------[ cut here ]------------ kernel BUG at subpage.c:476! Internal error: Oops - BUG: 00000000f2000800 [#1] SMP CPU: 4 UID: 0 PID: 2313 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 : btrfs_subpage_clear_writeback+0x148/0x160 [btrfs] lr : btrfs_subpage_clear_writeback+0x148/0x160 [btrfs] Call trace: btrfs_subpage_clear_writeback+0x148/0x160 [btrfs] (P) btrfs_folio_clamp_clear_writeback+0xb4/0xd0 [btrfs] end_compressed_writeback+0xe0/0x1e0 [btrfs] end_bbio_compressed_write+0x1e8/0x218 [btrfs] btrfs_bio_end_io+0x108/0x258 [btrfs] simple_end_io_work+0x68/0xa8 [btrfs] process_one_work+0x168/0x3f0 worker_thread+0x25c/0x398 kthread+0x154/0x250 ret_from_fork+0x10/0x20 ---[ end trace 0000000000000000 ]--- [CAUSE] The offending bio is from an encoded write, where the compressed data is directly written as a data extent, without touching the page cache. However the encoded write still utilizes the regular buffered write path for compressed data, by setting the compressed_bio::writeback flag. When that flag is set, at end_bbio_compressed_write() btrfs will go clearing the writeback flag of the folios in the page cache. However for bs < ps cases, the subpage helper has one extra check to make sure the folio has a writeback flag set in the first place. But since it's an encoded write, we never go through page cache, thus the folio has no writeback flag and triggers the ASSERT(). [FIX] Do not set compressed_bio::writeback flag for encoded writes, and change the ASSERT() in btrfs_submit_compressed_write() to make sure that flag is not set. Fixes: e1bc83f8b157 ("btrfs: get rid of compressed_folios[] usage for encoded writes") Reviewed-by: Filipe Manana Signed-off-by: Qu Wenruo Signed-off-by: David Sterba --- diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index ac995ec78e05..dc61f7e3cbbf 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -320,7 +320,12 @@ void btrfs_submit_compressed_write(struct btrfs_ordered_extent *ordered, ASSERT(IS_ALIGNED(ordered->file_offset, fs_info->sectorsize)); ASSERT(IS_ALIGNED(ordered->num_bytes, fs_info->sectorsize)); - ASSERT(cb->writeback); + /* + * This flag determines if we should clear the writeback flag from the + * page cache. But this function is only utilized by encoded writes, it + * never goes through the page cache. + */ + ASSERT(!cb->writeback); cb->start = ordered->file_offset; cb->len = ordered->num_bytes; @@ -346,8 +351,7 @@ struct compressed_bio *btrfs_alloc_compressed_write(struct btrfs_inode *inode, cb = alloc_compressed_bio(inode, start, REQ_OP_WRITE, end_bbio_compressed_write); cb->start = start; cb->len = len; - cb->writeback = true; - + cb->writeback = false; return cb; }