Commit fb4f644e authored by Sergey Senozhatsky's avatar Sergey Senozhatsky Committed by Andrew Morton

zram: add dictionary support to lz4

Support pre-trained dictionary param.  lz4 doesn't mandate specific format
of the dictionary and even zstd --train can be used to train a dictionary
for lz4, according to [1].

TEST
====

*** lz4
/sys/block/zram0/mm_stat
1750654976 664188565 676864000        0 676864000        1        0    34288    34288

*** lz4 dict=/etc/lz4-dict-amd64
/sys/block/zram0/mm_stat
1750638592 619891141 632053760        0 632053760        1        0    34278    34278

*** lz4 level=5 dict=/etc/lz4-dict-amd64
/sys/block/zram0/mm_stat
1750638592 727174243 740810752        0 740810752        1        0    34437    34437

[1] https://github.com/lz4/lz4/issues/557

Link: https://lkml.kernel.org/r/20240902105656.1383858-21-senozhatsky@chromium.orgSigned-off-by: default avatarSergey Senozhatsky <senozhatsky@chromium.org>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Nick Terrell <terrelln@fb.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent b8f03cb7
......@@ -5,6 +5,13 @@
#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)
{
}
......@@ -19,25 +26,66 @@ static int lz4_setup_params(struct zcomp_params *params)
static void lz4_destroy(struct zcomp_ctx *ctx)
{
vfree(ctx->context);
struct lz4_ctx *zctx = ctx->context;
if (!zctx)
return;
vfree(zctx->mem);
kfree(zctx->dstrm);
kfree(zctx->cstrm);
kfree(zctx);
}
static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
ctx->context = vmalloc(LZ4_MEM_COMPRESS);
if (!ctx->context)
struct lz4_ctx *zctx;
zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
if (!zctx)
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(sizeof(*zctx->dstrm), GFP_KERNEL);
if (!zctx->dstrm)
goto error;
zctx->cstrm = kzalloc(sizeof(*zctx->cstrm), GFP_KERNEL);
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;
ret = LZ4_compress_fast(req->src, req->dst, req->src_len,
req->dst_len, params->level, ctx->context);
if (!zctx->cstrm) {
ret = LZ4_compress_fast(req->src, req->dst, req->src_len,
req->dst_len, params->level,
zctx->mem);
} else {
/* Cstrm needs to be reset */
ret = LZ4_loadDict(zctx->cstrm, params->dict, params->dict_sz);
if (ret != params->dict_sz)
return -EINVAL;
ret = LZ4_compress_fast_continue(zctx->cstrm, req->src,
req->dst, req->src_len,
req->dst_len, params->level);
}
if (!ret)
return -EINVAL;
req->dst_len = ret;
......@@ -47,10 +95,22 @@ 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;
ret = LZ4_decompress_safe(req->src, req->dst, req->src_len,
req->dst_len);
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);
}
if (ret < 0)
return -EINVAL;
return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment