]> git.hungrycats.org Git - linux/commitdiff
btrfs: use kvmalloc() for uncompress_inline()
authorQu Wenruo <wqu@suse.com>
Tue, 8 Sep 2026 07:15:40 +0000 (16:45 +0930)
committerDavid Sterba <dsterba@suse.com>
Mon, 14 Sep 2026 11:23:37 +0000 (13:23 +0200)
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 <neelx@suse.com>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/inode.c

index 59e92908c6c5939e7e14fd626afefc831a4dc655..a85a7c561cf8e9842e71df875a3c90690276ffb8 100644 (file)
@@ -7133,7 +7133,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);
@@ -7154,7 +7154,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;
 }