blob: 847f3334eb38248674976361cd425fc795ef9d80 [file] [log] [blame]
#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)
{
}
static int lz4_setup_params(struct zcomp_params *params)
{
if (params->level == ZCOMP_PARAM_NO_LEVEL)
params->level = LZ4_ACCELERATION_DEFAULT;
return 0;
}
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);
}
static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
{
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;
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;
return 0;
}
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);
}
if (ret < 0)
return -EINVAL;
return 0;
}
const struct zcomp_ops backend_lz4 = {
.compress = lz4_compress,
.decompress = lz4_decompress,
.create_ctx = lz4_create,
.destroy_ctx = lz4_destroy,
.setup_params = lz4_setup_params,
.release_params = lz4_release_params,
.name = "lz4",
};