Re: [PATCH 3/3] btrfs: use kvmalloc() to allocate compression workspace buffer
From: Daniel Vacek <hidden>
Date: 2026-09-08 07:39:03
On Tue, 8 Sept 2026 at 09:35, Qu Wenruo [off-list ref] wrote:
With the experimental bs > ps support, the workspace buffer for both zlib and zstd can be as large as 64K, and on 4K page sized systems such kmalloc() calls have a much higher chance to fail, as that requires physically contiguous memory to fulfill such allocation. The same also applies to S390's hardware accelerated path, which requires a buffer size of 4 pages. Meanwhile lzo is already using kvmalloc() for its buffer, and there is no special requirement for any physically contiguous memory anyway. So change the zlib and zstd workspace buffer allocation to use kvmalloc() to reduce the chance of memory allocation failure. Signed-off-by: Qu Wenruo <redacted>
LGTM Reviewed-by: Daniel Vacek <redacted>
quoted hunk ↗ jump to hunk
--- fs/btrfs/zlib.c | 10 +++++----- fs/btrfs/zstd.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-)diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c index 486b52db583e..e995d0b1452b 100644 --- a/fs/btrfs/zlib.c +++ b/fs/btrfs/zlib.c@@ -49,7 +49,7 @@ void zlib_free_workspace(struct list_head *ws) struct workspace *workspace = list_entry(ws, struct workspace, list); kvfree(workspace->strm.workspace); - kfree(workspace->buf); + kvfree(workspace->buf); kfree(workspace); }@@ -84,13 +84,13 @@ struct list_head *zlib_alloc_workspace(struct btrfs_fs_info *fs_info, unsigned i workspace->level = level; workspace->buf = NULL; if (need_special_buffer(fs_info)) { - workspace->buf = kmalloc(ZLIB_DFLTCC_BUF_SIZE, - __GFP_NOMEMALLOC | __GFP_NORETRY | - __GFP_NOWARN | GFP_NOIO); + workspace->buf = kvmalloc(ZLIB_DFLTCC_BUF_SIZE, + __GFP_NOMEMALLOC | __GFP_NORETRY | + __GFP_NOWARN | GFP_NOIO); workspace->buf_size = ZLIB_DFLTCC_BUF_SIZE; } if (!workspace->buf) { - workspace->buf = kmalloc(fs_info->sectorsize, GFP_KERNEL); + workspace->buf = kvmalloc(fs_info->sectorsize, GFP_KERNEL); workspace->buf_size = fs_info->sectorsize; } if (!workspace->strm.workspace || !workspace->buf)diff --git a/fs/btrfs/zstd.c b/fs/btrfs/zstd.c index 280ac5273438..cc92d0b1b948 100644 --- a/fs/btrfs/zstd.c +++ b/fs/btrfs/zstd.c@@ -373,7 +373,7 @@ void zstd_free_workspace(struct list_head *ws) struct workspace *workspace = list_entry(ws, struct workspace, list); kvfree(workspace->mem); - kfree(workspace->buf); + kvfree(workspace->buf); kfree(workspace); }@@ -391,7 +391,7 @@ struct list_head *zstd_alloc_workspace(struct btrfs_fs_info *fs_info, int level) workspace->req_level = level; workspace->last_used = jiffies; workspace->mem = kvmalloc(workspace->size, GFP_KERNEL | __GFP_NOWARN); - workspace->buf = kmalloc(fs_info->sectorsize, GFP_KERNEL); + workspace->buf = kvmalloc(fs_info->sectorsize, GFP_KERNEL); if (!workspace->mem || !workspace->buf) goto fail; --2.55.0