From b2ba99cf6f7ba3cd53fe6bb1b24a4c8cc5d74ba7 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Tue, 8 Sep 2026 07:47:39 +0930 Subject: [PATCH] btrfs: use kvmalloc() for b-tree split_item() [BUG] There is a bug report that the kmalloc() call inside split_item() failed with the following call trace, and triggered a transaction abort: kworker/u69:8: page allocation failure: order:4, mode:0x40c40(GFP_NOFS|__GFP_COMP), nodemask=(null) CPU: 3 UID: 0 PID: 1154528 Comm: kworker/u69:8 Not tainted 7.0.2 #1 PREEMPTLAZY Workqueue: events_unbound btrfs_async_reclaim_metadata_space Call Trace: dump_stack_lvl+0x47/0x60 warn_alloc.cold+0x67/0xec __alloc_pages_slowpath.constprop.0+0x9bf/0xed0 __alloc_frozen_pages_noprof+0x1ac/0x1c0 ___kmalloc_large_node+0x9d/0xc0 __kmalloc_noprof+0x17b/0x1f0 split_item+0x9e/0x2e0 btrfs_del_csums+0x285/0x400 __btrfs_free_extent.isra.0+0x6de/0x12b0 __btrfs_run_delayed_refs+0x522/0x10c0 btrfs_run_delayed_refs+0x4d/0x1d0 flush_space+0x34d/0x4e0 do_async_reclaim_metadata_space+0x89/0x1d0 btrfs_async_reclaim_metadata_space+0x44/0x60 process_one_work+0x145/0x230 worker_thread+0x185/0x2e0 kthread+0xca/0x100 ret_from_fork+0x14e/0x200 ret_from_fork_asm+0x11/0x20 BTRFS error (device dm-3 state A): Transaction aborted (error -12) BTRFS: error (device dm-3 state A) in btrfs_del_csums:1053: errno=-12 Out of memory BTRFS info (device dm-3 state EA): forced readonly BTRFS: error (device dm-3 state EA) in do_free_extent_accounting:3168: errno=-12 Out of memory BTRFS error (device dm-3 state EA): failed to run delayed ref for logical 1202913873920 num_bytes 274432 type 184 action 2 ref_mod 1: -12 BTRFS: error (device dm-3 state EA) in btrfs_run_delayed_refs:2247: errno=-12 Out of memory [CAUSE] The kmalloc() call is to allocate a buffer to store the full item. However as shown in the above call trace, the order can be high (4), and since we're using GFP_NOFS, it's impossible to reclaim memory by writing back dirty pages. When there is no physically contiguous memory left, such high order allocation can easily fail, and if such kmalloc() happens in a critical path we can trigger a transaction abort. [FIX] Instead of kmalloc(), which requires physically contiguous pages, use kvmalloc(). There is no special requirement for physically contiguous pages here, we just want virtually contiguous memory as a buffer. Reported-by: xavierbachmeyer182 Link: https://lore.kernel.org/linux-btrfs/250decb0-d940-4fe6-9b54-d06e1b293a1b@suse.com/ Reviewed-by: Johannes Thumshirn Reviewed-by: Daniel Vacek Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/ctree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 8fe330d81b8f..fef0e49dd918 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -3943,7 +3943,7 @@ static noinline int split_item(struct btrfs_trans_handle *trans, orig_offset = btrfs_item_offset(leaf, path->slots[0]); item_size = btrfs_item_size(leaf, path->slots[0]); - buf = kmalloc(item_size, GFP_NOFS); + buf = kvmalloc(item_size, GFP_NOFS); if (!buf) return -ENOMEM; @@ -3981,7 +3981,7 @@ static noinline int split_item(struct btrfs_trans_handle *trans, btrfs_mark_buffer_dirty(trans, leaf); BUG_ON(btrfs_leaf_free_space(leaf) < 0); - kfree(buf); + kvfree(buf); return 0; }