[PATCH 06/10] zram: lz4hc: use LZ4_decompress_safe_usingDict()

From: Sergey Senozhatsky

Date: Mon Oct 05 2026 - 08:23:30 EST


Use LZ4_decompress_safe_usingDict() in lz4hc_decompress() to avoid
needing a per-CPU LZ4_streamDecode_t structure. Drop struct lz4hc_ctx
as well and store the compression workspace directly in ctx->context,
matching backend_lz4.

Using vmalloc(LZ4HC_MEM_COMPRESS) instead of kzalloc() for cstrm when a
dictionary is configured also avoids power-of-2 page rounding (~256 KB
rounded up to 512 KB), saving ~252 KB per CPU.

Signed-off-by: Sergey Senozhatsky <senozhatsky@xxxxxxxxxxxx>
---
drivers/block/zram/backend_lz4hc.c | 70 +++++-------------------------
1 file changed, 11 insertions(+), 59 deletions(-)

diff --git a/drivers/block/zram/backend_lz4hc.c b/drivers/block/zram/backend_lz4hc.c
index f3656c27af21..b62736b26622 100644
--- a/drivers/block/zram/backend_lz4hc.c
+++ b/drivers/block/zram/backend_lz4hc.c
@@ -4,18 +4,10 @@

#include <linux/kernel.h>
#include <linux/lz4.h>
-#include <linux/slab.h>
#include <linux/vmalloc.h>

#include "backend_lz4hc.h"

-struct lz4hc_ctx {
- void *mem;
-
- LZ4_streamDecode_t *dstrm;
- LZ4_streamHC_t *cstrm;
-};
-
static void lz4hc_release_params(struct zcomp_params *params)
{
LZ4_streamHC_t *dict_stream = params->drv_data;
@@ -65,61 +57,32 @@ static int lz4hc_setup_params(struct zcomp_params *params)

static void lz4hc_destroy(struct zcomp_ctx *ctx)
{
- struct lz4hc_ctx *zctx = ctx->context;
-
- if (!zctx)
- return;
-
- kfree(zctx->dstrm);
- kfree(zctx->cstrm);
- vfree(zctx->mem);
- kfree(zctx);
+ vfree(ctx->context);
}

static int lz4hc_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
- struct lz4hc_ctx *zctx;
+ BUILD_BUG_ON(sizeof(LZ4_streamHC_t) != LZ4HC_MEM_COMPRESS);

- zctx = kzalloc_obj(*zctx);
- if (!zctx)
+ ctx->context = vmalloc(LZ4HC_MEM_COMPRESS);
+ if (!ctx->context)
return -ENOMEM;
-
- ctx->context = zctx;
- if (params->dict_sz == 0) {
- zctx->mem = vmalloc(LZ4HC_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:
- lz4hc_destroy(ctx);
- return -EINVAL;
}

static int lz4hc_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
- struct lz4hc_ctx *zctx = ctx->context;
int ret;

- if (!zctx->cstrm) {
+ if (!params->drv_data) {
ret = LZ4_compress_HC(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_HC_continue(zctx->cstrm, req->src, req->dst,
+ memcpy(ctx->context, params->drv_data, sizeof(LZ4_streamHC_t));
+ ret = LZ4_compress_HC_continue(ctx->context, req->src, req->dst,
req->src_len, req->dst_len);
}
if (!ret)
@@ -131,22 +94,11 @@ static int lz4hc_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
static int lz4hc_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
struct zcomp_req *req)
{
- struct lz4hc_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