From 883a1a260cf84c954bc6295dc052425d51dff923 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Tue, 8 Sep 2026 16:45:40 +0930 Subject: [PATCH] btrfs: use kvmalloc() for uncompress_inline() Although btrfs doesn't support inlined extents larger than PAGE_SIZE for bs > ps cases, it's still possible for the experimental bs > ps support to mount a btrfs created on a system with a much larger page size, thus can still hit an inlined extent that is way larger than the current page size. E.g. a compressed inline extent which has 32K compressed size, is created on 64K page sized ARM64 with 64K sectorsize, then mounted on x86_64 with the experimental bs > ps support. In that case, when reading the compressed inline extent, we need to allocate a buffer that is the same size as the compressed inline extent (32K). That kmalloc() call will request physically contiguous memory for that 32K allocation, and if the system has a very fragmented memory space, such allocation can fail. But there is really no reason that we require such buffer to be physically contiguous, so change it to kvmalloc() to reduce the chance of allocation failure for bs > ps cases. And for all bs <= ps cases, the kvmalloc() call will just be fulfilled by kmalloc() so this will not bring any change to the most common cases. Only bs > ps will get the benefit of less memory allocation failure. Reviewed-by: Daniel Vacek Reviewed-by: Johannes Thumshirn Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c7bbcd11d01e..e7046e9a0e70 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7149,7 +7149,7 @@ static noinline int uncompress_inline(struct btrfs_path *path, compress_type = btrfs_file_extent_compression(leaf, item); max_size = btrfs_file_extent_ram_bytes(leaf, item); inline_size = btrfs_file_extent_inline_item_len(leaf, path->slots[0]); - tmp = kmalloc(inline_size, GFP_NOFS); + tmp = kvmalloc(inline_size, GFP_NOFS); if (!tmp) return -ENOMEM; ptr = btrfs_file_extent_inline_start(item); @@ -7170,7 +7170,7 @@ static noinline int uncompress_inline(struct btrfs_path *path, if (max_size < blocksize) folio_zero_range(folio, max_size, blocksize - max_size); - kfree(tmp); + kvfree(tmp); return ret; }