[PATCH 05/10] zram: lz4: use LZ4_decompress_safe_usingDict()
From: Sergey Senozhatsky
Date: Mon Oct 05 2026 - 08:23:52 EST
Use LZ4_decompress_safe_usingDict() in lz4_decompress() and drop the
per-CPU dstrm allocation. Store the compression workspace directly
in ctx->context.
Using vmalloc(LZ4_MEM_COMPRESS) instead of kzalloc() for cstrm and
dict_stream when a dictionary is configured also avoids power-of-2
page rounding (~16 KB rounded up to 32 KB), saving ~12 KB per stream.
Signed-off-by: Sergey Senozhatsky <senozhatsky@xxxxxxxxxxxx>
---
drivers/block/zram/backend_lz4.c | 76 ++++++--------------------------
1 file changed, 14 insertions(+), 62 deletions(-)
diff --git a/drivers/block/zram/backend_lz4.c b/drivers/block/zram/backend_lz4.c
index 158fd8b5e8a9..5f2e27805d75 100644
--- a/drivers/block/zram/backend_lz4.c
+++ b/drivers/block/zram/backend_lz4.c
@@ -4,18 +4,10 @@
#include <linux/kernel.h>
#include <linux/lz4.h>
-#include <linux/slab.h>
#include <linux/vmalloc.h>
#include "backend_lz4.h"
-struct lz4_ctx {
- void *mem;
-
- LZ4_streamDecode_t *dstrm;
- LZ4_stream_t *cstrm;
-};
-
static void lz4_release_params(struct zcomp_params *params)
{
LZ4_stream_t *dict_stream = params->drv_data;
@@ -24,7 +16,7 @@ static void lz4_release_params(struct zcomp_params *params)
if (!dict_stream)
return;
- kfree(dict_stream);
+ vfree(dict_stream);
}
static int lz4_setup_params(struct zcomp_params *params)
@@ -42,14 +34,14 @@ static int lz4_setup_params(struct zcomp_params *params)
if (!params->dict || !params->dict_sz)
return 0;
- dict_stream = kzalloc_obj(*dict_stream);
+ dict_stream = vzalloc(sizeof(*dict_stream));
if (!dict_stream)
return -ENOMEM;
ret = LZ4_loadDict(dict_stream,
params->dict, params->dict_sz);
if (ret != params->dict_sz) {
- kfree(dict_stream);
+ vfree(dict_stream);
return -EINVAL;
}
params->drv_data = dict_stream;
@@ -59,61 +51,32 @@ static int lz4_setup_params(struct zcomp_params *params)
static void lz4_destroy(struct zcomp_ctx *ctx)
{
- struct lz4_ctx *zctx = ctx->context;
-
- if (!zctx)
- return;
-
- vfree(zctx->mem);
- kfree(zctx->dstrm);
- kfree(zctx->cstrm);
- kfree(zctx);
+ vfree(ctx->context);
}
static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- struct lz4_ctx *zctx;
+ BUILD_BUG_ON(sizeof(LZ4_stream_t) != LZ4_MEM_COMPRESS);
- zctx = kzalloc_obj(*zctx);
- if (!zctx)
+ ctx->context = vmalloc(LZ4_MEM_COMPRESS);
+ if (!ctx->context)
return -ENOMEM;
-
- ctx->context = zctx;
- if (params->dict_sz == 0) {
- zctx->mem = vmalloc(LZ4_MEM_COMPRESS);
- if (!zctx->mem)
- goto error;
- } else {
- zctx->dstrm = kzalloc_obj(*zctx->dstrm);
- if (!zctx->dstrm)
- goto error;
-
- zctx->cstrm = kzalloc_obj(*zctx->cstrm);
- if (!zctx->cstrm)
- goto error;
- }
-
return 0;
-
-error:
- lz4_destroy(ctx);
- return -ENOMEM;
}
static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
- struct lz4_ctx *zctx = ctx->context;
int ret;
- if (!zctx->cstrm) {
+ if (!params->drv_data) {
ret = LZ4_compress_fast(req->src, req->dst, req->src_len,
req->dst_len, params->level,
- zctx->mem);
+ ctx->context);
} else {
/* Cstrm needs to be reset */
- memcpy(zctx->cstrm, params->drv_data, sizeof(*zctx->cstrm));
- ret = LZ4_compress_fast_continue(zctx->cstrm, req->src,
+ memcpy(ctx->context, params->drv_data, sizeof(LZ4_stream_t));
+ ret = LZ4_compress_fast_continue(ctx->context, req->src,
req->dst, req->src_len,
req->dst_len, params->level);
}
@@ -126,22 +89,11 @@ static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
static int lz4_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
- struct lz4_ctx *zctx = ctx->context;
int ret;
- if (!zctx->dstrm) {
- ret = LZ4_decompress_safe(req->src, req->dst, req->src_len,
- req->dst_len);
- } else {
- /* Dstrm needs to be reset */
- ret = LZ4_setStreamDecode(zctx->dstrm, params->dict,
- params->dict_sz);
- if (!ret)
- return -EINVAL;
- ret = LZ4_decompress_safe_continue(zctx->dstrm, req->src,
- req->dst, req->src_len,
- req->dst_len);
- }
+ ret = LZ4_decompress_safe_usingDict(req->src, req->dst, req->src_len,
+ req->dst_len, params->dict,
+ params->dict_sz);
if (ret < 0)
return -EINVAL;
return 0;
--
2.56.0.rc1.315.gc6ed9934b7-goog