[PATCH 07/10] zram: zstd: do not use kvzalloc() for zstd allocations
From: Sergey Senozhatsky
Date: Mon Oct 05 2026 - 08:21:51 EST
When a dictionary is configured, zstd allocates all of its memory (C/D
dictionaries, compression and decompression contexts and compression
workspaces) via zstd_custom_alloc(). zstd_custom_alloc() uses
kvzalloc(), which falls back to vmalloc() only when kmalloc() fails,
and kmalloc() rounds such sizes up to a power-of-two number of pages.
For example, on x86_64 with a 110K dictionary, switching from
kvzalloc() to __vmalloc() reduces allocations from:
- CDict (level 3): 512 KB -> 400 KB
- CDict (levels 12+): 2048 KB -> 1552 KB
- DCtx (per-CPU): 128 KB -> 96 KB
- CCtx workspace (level 3): 128 KB -> 84 KB (per-CPU)
- CCtx workspace (level 14+): 1024 KB -> 764 KB (per-CPU)
Use __vmalloc() for allocations larger than PAGE_SIZE (and kzalloc()
for smaller ones), which is also how zram allocates zstd workspaces
when no dictionary is configured. zstd_custom_free() already uses
kvfree(), which handles both.
Signed-off-by: Sergey Senozhatsky <senozhatsky@xxxxxxxxxxxx>
---
drivers/block/zram/backend_zstd.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/block/zram/backend_zstd.c b/drivers/block/zram/backend_zstd.c
index b367049f131d..7a8b5ff186f2 100644
--- a/drivers/block/zram/backend_zstd.c
+++ b/drivers/block/zram/backend_zstd.c
@@ -26,10 +26,17 @@ struct zstd_params {
/*
* For C/D dictionaries we need to provide zstd with zstd_custom_mem,
* which zstd uses internally to allocate/free memory when needed.
+ *
+ * zstd allocations (C/D dictionaries and contexts) are large and
+ * long-lived. Don't use kvzalloc() for them: when enough physically
+ * contiguous memory is available it serves them from kmalloc(), which
+ * rounds them up to a power-of-two number of pages.
*/
static void *zstd_custom_alloc(void *opaque, size_t size)
{
- return kvzalloc(size, GFP_NOIO | __GFP_NOWARN);
+ if (size <= PAGE_SIZE)
+ return kzalloc(size, GFP_NOIO | __GFP_NOWARN);
+ return __vmalloc(size, GFP_NOIO | __GFP_NOWARN | __GFP_ZERO);
}
static void zstd_custom_free(void *opaque, void *address)
--
2.56.0.rc1.315.gc6ed9934b7-goog