Skip to content

Commit

Permalink
zram: add dictionary support to lz4
Browse files Browse the repository at this point in the history
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] lz4/lz4#557

Link: https://lkml.kernel.org/r/20240902105656.1383858-21-senozhatsky@chromium.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Nick Terrell <terrelln@fb.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
  • Loading branch information
sergey-senozhatsky authored and akpm00 committed Sep 9, 2024
1 parent b8f03cb commit fb4f644
Showing 1 changed file with 67 additions and 7 deletions.
74 changes: 67 additions & 7 deletions drivers/block/zram/backend_lz4.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
}
Expand All @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit fb4f644

Please sign in to comment.