1c60a4ef5SSergey Senozhatsky #include <linux/kernel.h>
2c60a4ef5SSergey Senozhatsky #include <linux/lz4.h>
3c60a4ef5SSergey Senozhatsky #include <linux/slab.h>
4c60a4ef5SSergey Senozhatsky #include <linux/vmalloc.h>
5c60a4ef5SSergey Senozhatsky
6c60a4ef5SSergey Senozhatsky #include "backend_lz4hc.h"
7c60a4ef5SSergey Senozhatsky
8*1e673c8cSSergey Senozhatsky struct lz4hc_ctx {
9*1e673c8cSSergey Senozhatsky void *mem;
10*1e673c8cSSergey Senozhatsky
11*1e673c8cSSergey Senozhatsky LZ4_streamDecode_t *dstrm;
12*1e673c8cSSergey Senozhatsky LZ4_streamHC_t *cstrm;
13*1e673c8cSSergey Senozhatsky };
14*1e673c8cSSergey Senozhatsky
lz4hc_release_params(struct zcomp_params * params)15b8f03cb7SSergey Senozhatsky static void lz4hc_release_params(struct zcomp_params *params)
16b8f03cb7SSergey Senozhatsky {
17b8f03cb7SSergey Senozhatsky }
18b8f03cb7SSergey Senozhatsky
lz4hc_setup_params(struct zcomp_params * params)19b8f03cb7SSergey Senozhatsky static int lz4hc_setup_params(struct zcomp_params *params)
20b8f03cb7SSergey Senozhatsky {
21b8f03cb7SSergey Senozhatsky if (params->level == ZCOMP_PARAM_NO_LEVEL)
22b8f03cb7SSergey Senozhatsky params->level = LZ4HC_DEFAULT_CLEVEL;
23b8f03cb7SSergey Senozhatsky
24b8f03cb7SSergey Senozhatsky return 0;
25b8f03cb7SSergey Senozhatsky }
26c60a4ef5SSergey Senozhatsky
lz4hc_destroy(struct zcomp_ctx * ctx)276a81bdfeSSergey Senozhatsky static void lz4hc_destroy(struct zcomp_ctx *ctx)
28c60a4ef5SSergey Senozhatsky {
29*1e673c8cSSergey Senozhatsky struct lz4hc_ctx *zctx = ctx->context;
30*1e673c8cSSergey Senozhatsky
31*1e673c8cSSergey Senozhatsky if (!zctx)
32*1e673c8cSSergey Senozhatsky return;
33*1e673c8cSSergey Senozhatsky
34*1e673c8cSSergey Senozhatsky kfree(zctx->dstrm);
35*1e673c8cSSergey Senozhatsky kfree(zctx->cstrm);
36*1e673c8cSSergey Senozhatsky vfree(zctx->mem);
37*1e673c8cSSergey Senozhatsky kfree(zctx);
38c60a4ef5SSergey Senozhatsky }
39c60a4ef5SSergey Senozhatsky
lz4hc_create(struct zcomp_params * params,struct zcomp_ctx * ctx)406a81bdfeSSergey Senozhatsky static int lz4hc_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
41c60a4ef5SSergey Senozhatsky {
42*1e673c8cSSergey Senozhatsky struct lz4hc_ctx *zctx;
43*1e673c8cSSergey Senozhatsky
44*1e673c8cSSergey Senozhatsky zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
45*1e673c8cSSergey Senozhatsky if (!zctx)
466a81bdfeSSergey Senozhatsky return -ENOMEM;
47c60a4ef5SSergey Senozhatsky
48*1e673c8cSSergey Senozhatsky ctx->context = zctx;
49*1e673c8cSSergey Senozhatsky if (params->dict_sz == 0) {
50*1e673c8cSSergey Senozhatsky zctx->mem = vmalloc(LZ4HC_MEM_COMPRESS);
51*1e673c8cSSergey Senozhatsky if (!zctx->mem)
52*1e673c8cSSergey Senozhatsky goto error;
53*1e673c8cSSergey Senozhatsky } else {
54*1e673c8cSSergey Senozhatsky zctx->dstrm = kzalloc(sizeof(*zctx->dstrm), GFP_KERNEL);
55*1e673c8cSSergey Senozhatsky if (!zctx->dstrm)
56*1e673c8cSSergey Senozhatsky goto error;
57*1e673c8cSSergey Senozhatsky
58*1e673c8cSSergey Senozhatsky zctx->cstrm = kzalloc(sizeof(*zctx->cstrm), GFP_KERNEL);
59*1e673c8cSSergey Senozhatsky if (!zctx->cstrm)
60*1e673c8cSSergey Senozhatsky goto error;
61*1e673c8cSSergey Senozhatsky }
62*1e673c8cSSergey Senozhatsky
636a81bdfeSSergey Senozhatsky return 0;
64*1e673c8cSSergey Senozhatsky
65*1e673c8cSSergey Senozhatsky error:
66*1e673c8cSSergey Senozhatsky lz4hc_destroy(ctx);
67*1e673c8cSSergey Senozhatsky return -EINVAL;
68c60a4ef5SSergey Senozhatsky }
69c60a4ef5SSergey Senozhatsky
lz4hc_compress(struct zcomp_params * params,struct zcomp_ctx * ctx,struct zcomp_req * req)70b8f03cb7SSergey Senozhatsky static int lz4hc_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
71b8f03cb7SSergey Senozhatsky struct zcomp_req *req)
72c60a4ef5SSergey Senozhatsky {
73*1e673c8cSSergey Senozhatsky struct lz4hc_ctx *zctx = ctx->context;
74c60a4ef5SSergey Senozhatsky int ret;
75c60a4ef5SSergey Senozhatsky
76*1e673c8cSSergey Senozhatsky if (!zctx->cstrm) {
77*1e673c8cSSergey Senozhatsky ret = LZ4_compress_HC(req->src, req->dst, req->src_len,
78*1e673c8cSSergey Senozhatsky req->dst_len, params->level,
79*1e673c8cSSergey Senozhatsky zctx->mem);
80*1e673c8cSSergey Senozhatsky } else {
81*1e673c8cSSergey Senozhatsky /* Cstrm needs to be reset */
82*1e673c8cSSergey Senozhatsky LZ4_resetStreamHC(zctx->cstrm, params->level);
83*1e673c8cSSergey Senozhatsky ret = LZ4_loadDictHC(zctx->cstrm, params->dict,
84*1e673c8cSSergey Senozhatsky params->dict_sz);
85*1e673c8cSSergey Senozhatsky if (ret != params->dict_sz)
86*1e673c8cSSergey Senozhatsky return -EINVAL;
87*1e673c8cSSergey Senozhatsky ret = LZ4_compress_HC_continue(zctx->cstrm, req->src, req->dst,
88*1e673c8cSSergey Senozhatsky req->src_len, req->dst_len);
89*1e673c8cSSergey Senozhatsky }
90c60a4ef5SSergey Senozhatsky if (!ret)
91c60a4ef5SSergey Senozhatsky return -EINVAL;
9252c7b4e2SSergey Senozhatsky req->dst_len = ret;
93c60a4ef5SSergey Senozhatsky return 0;
94c60a4ef5SSergey Senozhatsky }
95c60a4ef5SSergey Senozhatsky
lz4hc_decompress(struct zcomp_params * params,struct zcomp_ctx * ctx,struct zcomp_req * req)96b8f03cb7SSergey Senozhatsky static int lz4hc_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx,
97b8f03cb7SSergey Senozhatsky struct zcomp_req *req)
98c60a4ef5SSergey Senozhatsky {
99*1e673c8cSSergey Senozhatsky struct lz4hc_ctx *zctx = ctx->context;
100c60a4ef5SSergey Senozhatsky int ret;
101c60a4ef5SSergey Senozhatsky
102*1e673c8cSSergey Senozhatsky if (!zctx->dstrm) {
10352c7b4e2SSergey Senozhatsky ret = LZ4_decompress_safe(req->src, req->dst, req->src_len,
10452c7b4e2SSergey Senozhatsky req->dst_len);
105*1e673c8cSSergey Senozhatsky } else {
106*1e673c8cSSergey Senozhatsky /* Dstrm needs to be reset */
107*1e673c8cSSergey Senozhatsky ret = LZ4_setStreamDecode(zctx->dstrm, params->dict,
108*1e673c8cSSergey Senozhatsky params->dict_sz);
109*1e673c8cSSergey Senozhatsky if (!ret)
110*1e673c8cSSergey Senozhatsky return -EINVAL;
111*1e673c8cSSergey Senozhatsky ret = LZ4_decompress_safe_continue(zctx->dstrm, req->src,
112*1e673c8cSSergey Senozhatsky req->dst, req->src_len,
113*1e673c8cSSergey Senozhatsky req->dst_len);
114*1e673c8cSSergey Senozhatsky }
115c60a4ef5SSergey Senozhatsky if (ret < 0)
116c60a4ef5SSergey Senozhatsky return -EINVAL;
117c60a4ef5SSergey Senozhatsky return 0;
118c60a4ef5SSergey Senozhatsky }
119c60a4ef5SSergey Senozhatsky
120c60a4ef5SSergey Senozhatsky const struct zcomp_ops backend_lz4hc = {
121c60a4ef5SSergey Senozhatsky .compress = lz4hc_compress,
122c60a4ef5SSergey Senozhatsky .decompress = lz4hc_decompress,
123c60a4ef5SSergey Senozhatsky .create_ctx = lz4hc_create,
124c60a4ef5SSergey Senozhatsky .destroy_ctx = lz4hc_destroy,
125b8f03cb7SSergey Senozhatsky .setup_params = lz4hc_setup_params,
126b8f03cb7SSergey Senozhatsky .release_params = lz4hc_release_params,
127c60a4ef5SSergey Senozhatsky .name = "lz4hc",
128c60a4ef5SSergey Senozhatsky };
129