184112e31SSergey Senozhatsky // SPDX-License-Identifier: GPL-2.0-or-later
284112e31SSergey Senozhatsky
384112e31SSergey Senozhatsky #include <linux/kernel.h>
484112e31SSergey Senozhatsky #include <linux/slab.h>
584112e31SSergey Senozhatsky #include <linux/vmalloc.h>
684112e31SSergey Senozhatsky #include <linux/zlib.h>
784112e31SSergey Senozhatsky
884112e31SSergey Senozhatsky #include "backend_deflate.h"
984112e31SSergey Senozhatsky
1084112e31SSergey Senozhatsky /* Use the same value as crypto API */
1184112e31SSergey Senozhatsky #define DEFLATE_DEF_WINBITS 11
1284112e31SSergey Senozhatsky #define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL
1384112e31SSergey Senozhatsky
1484112e31SSergey Senozhatsky struct deflate_ctx {
1584112e31SSergey Senozhatsky struct z_stream_s cctx;
1684112e31SSergey Senozhatsky struct z_stream_s dctx;
1784112e31SSergey Senozhatsky };
1884112e31SSergey Senozhatsky
deflate_release_params(struct zcomp_params * params)19*b8f03cb7SSergey Senozhatsky static void deflate_release_params(struct zcomp_params *params)
20*b8f03cb7SSergey Senozhatsky {
21*b8f03cb7SSergey Senozhatsky }
22*b8f03cb7SSergey Senozhatsky
deflate_setup_params(struct zcomp_params * params)23*b8f03cb7SSergey Senozhatsky static int deflate_setup_params(struct zcomp_params *params)
24*b8f03cb7SSergey Senozhatsky {
25*b8f03cb7SSergey Senozhatsky if (params->level == ZCOMP_PARAM_NO_LEVEL)
26*b8f03cb7SSergey Senozhatsky params->level = Z_DEFAULT_COMPRESSION;
27*b8f03cb7SSergey Senozhatsky
28*b8f03cb7SSergey Senozhatsky return 0;
29*b8f03cb7SSergey Senozhatsky }
30*b8f03cb7SSergey Senozhatsky
deflate_destroy(struct zcomp_ctx * ctx)316a81bdfeSSergey Senozhatsky static void deflate_destroy(struct zcomp_ctx *ctx)
3284112e31SSergey Senozhatsky {
336a81bdfeSSergey Senozhatsky struct deflate_ctx *zctx = ctx->context;
346a81bdfeSSergey Senozhatsky
356a81bdfeSSergey Senozhatsky if (!zctx)
366a81bdfeSSergey Senozhatsky return;
3784112e31SSergey Senozhatsky
3884112e31SSergey Senozhatsky if (zctx->cctx.workspace) {
3984112e31SSergey Senozhatsky zlib_deflateEnd(&zctx->cctx);
4084112e31SSergey Senozhatsky vfree(zctx->cctx.workspace);
4184112e31SSergey Senozhatsky }
4284112e31SSergey Senozhatsky if (zctx->dctx.workspace) {
4384112e31SSergey Senozhatsky zlib_inflateEnd(&zctx->dctx);
4484112e31SSergey Senozhatsky vfree(zctx->dctx.workspace);
4584112e31SSergey Senozhatsky }
4684112e31SSergey Senozhatsky kfree(zctx);
4784112e31SSergey Senozhatsky }
4884112e31SSergey Senozhatsky
deflate_create(struct zcomp_params * params,struct zcomp_ctx * ctx)496a81bdfeSSergey Senozhatsky static int deflate_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
5084112e31SSergey Senozhatsky {
516a81bdfeSSergey Senozhatsky struct deflate_ctx *zctx;
5284112e31SSergey Senozhatsky size_t sz;
5384112e31SSergey Senozhatsky int ret;
5484112e31SSergey Senozhatsky
556a81bdfeSSergey Senozhatsky zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
566a81bdfeSSergey Senozhatsky if (!zctx)
576a81bdfeSSergey Senozhatsky return -ENOMEM;
5884112e31SSergey Senozhatsky
596a81bdfeSSergey Senozhatsky ctx->context = zctx;
6084112e31SSergey Senozhatsky sz = zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL);
616a81bdfeSSergey Senozhatsky zctx->cctx.workspace = vzalloc(sz);
626a81bdfeSSergey Senozhatsky if (!zctx->cctx.workspace)
6384112e31SSergey Senozhatsky goto error;
6484112e31SSergey Senozhatsky
65*b8f03cb7SSergey Senozhatsky ret = zlib_deflateInit2(&zctx->cctx, params->level, Z_DEFLATED,
6684112e31SSergey Senozhatsky -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
6784112e31SSergey Senozhatsky Z_DEFAULT_STRATEGY);
6884112e31SSergey Senozhatsky if (ret != Z_OK)
6984112e31SSergey Senozhatsky goto error;
7084112e31SSergey Senozhatsky
7184112e31SSergey Senozhatsky sz = zlib_inflate_workspacesize();
726a81bdfeSSergey Senozhatsky zctx->dctx.workspace = vzalloc(sz);
736a81bdfeSSergey Senozhatsky if (!zctx->dctx.workspace)
7484112e31SSergey Senozhatsky goto error;
7584112e31SSergey Senozhatsky
766a81bdfeSSergey Senozhatsky ret = zlib_inflateInit2(&zctx->dctx, -DEFLATE_DEF_WINBITS);
7784112e31SSergey Senozhatsky if (ret != Z_OK)
7884112e31SSergey Senozhatsky goto error;
7984112e31SSergey Senozhatsky
806a81bdfeSSergey Senozhatsky return 0;
8184112e31SSergey Senozhatsky
8284112e31SSergey Senozhatsky error:
8384112e31SSergey Senozhatsky deflate_destroy(ctx);
846a81bdfeSSergey Senozhatsky return -EINVAL;
8584112e31SSergey Senozhatsky }
8684112e31SSergey Senozhatsky
deflate_compress(struct zcomp_params * params,struct zcomp_ctx * ctx,struct zcomp_req * req)87*b8f03cb7SSergey Senozhatsky static int deflate_compress(struct zcomp_params *params, struct zcomp_ctx *ctx,
88*b8f03cb7SSergey Senozhatsky struct zcomp_req *req)
8984112e31SSergey Senozhatsky {
906a81bdfeSSergey Senozhatsky struct deflate_ctx *zctx = ctx->context;
9184112e31SSergey Senozhatsky struct z_stream_s *deflate;
9284112e31SSergey Senozhatsky int ret;
9384112e31SSergey Senozhatsky
9484112e31SSergey Senozhatsky deflate = &zctx->cctx;
9584112e31SSergey Senozhatsky ret = zlib_deflateReset(deflate);
9684112e31SSergey Senozhatsky if (ret != Z_OK)
9784112e31SSergey Senozhatsky return -EINVAL;
9884112e31SSergey Senozhatsky
9952c7b4e2SSergey Senozhatsky deflate->next_in = (u8 *)req->src;
10052c7b4e2SSergey Senozhatsky deflate->avail_in = req->src_len;
10152c7b4e2SSergey Senozhatsky deflate->next_out = (u8 *)req->dst;
10252c7b4e2SSergey Senozhatsky deflate->avail_out = req->dst_len;
10384112e31SSergey Senozhatsky
10484112e31SSergey Senozhatsky ret = zlib_deflate(deflate, Z_FINISH);
10584112e31SSergey Senozhatsky if (ret != Z_STREAM_END)
10684112e31SSergey Senozhatsky return -EINVAL;
10784112e31SSergey Senozhatsky
10852c7b4e2SSergey Senozhatsky req->dst_len = deflate->total_out;
10984112e31SSergey Senozhatsky return 0;
11084112e31SSergey Senozhatsky }
11184112e31SSergey Senozhatsky
deflate_decompress(struct zcomp_params * params,struct zcomp_ctx * ctx,struct zcomp_req * req)112*b8f03cb7SSergey Senozhatsky static int deflate_decompress(struct zcomp_params *params,
113*b8f03cb7SSergey Senozhatsky struct zcomp_ctx *ctx,
114*b8f03cb7SSergey Senozhatsky struct zcomp_req *req)
11584112e31SSergey Senozhatsky {
1166a81bdfeSSergey Senozhatsky struct deflate_ctx *zctx = ctx->context;
11784112e31SSergey Senozhatsky struct z_stream_s *inflate;
11884112e31SSergey Senozhatsky int ret;
11984112e31SSergey Senozhatsky
12084112e31SSergey Senozhatsky inflate = &zctx->dctx;
12184112e31SSergey Senozhatsky
12284112e31SSergey Senozhatsky ret = zlib_inflateReset(inflate);
12384112e31SSergey Senozhatsky if (ret != Z_OK)
12484112e31SSergey Senozhatsky return -EINVAL;
12584112e31SSergey Senozhatsky
12652c7b4e2SSergey Senozhatsky inflate->next_in = (u8 *)req->src;
12752c7b4e2SSergey Senozhatsky inflate->avail_in = req->src_len;
12852c7b4e2SSergey Senozhatsky inflate->next_out = (u8 *)req->dst;
12952c7b4e2SSergey Senozhatsky inflate->avail_out = req->dst_len;
13084112e31SSergey Senozhatsky
13184112e31SSergey Senozhatsky ret = zlib_inflate(inflate, Z_SYNC_FLUSH);
13284112e31SSergey Senozhatsky if (ret != Z_STREAM_END)
13384112e31SSergey Senozhatsky return -EINVAL;
13484112e31SSergey Senozhatsky
13584112e31SSergey Senozhatsky return 0;
13684112e31SSergey Senozhatsky }
13784112e31SSergey Senozhatsky
13884112e31SSergey Senozhatsky const struct zcomp_ops backend_deflate = {
13984112e31SSergey Senozhatsky .compress = deflate_compress,
14084112e31SSergey Senozhatsky .decompress = deflate_decompress,
14184112e31SSergey Senozhatsky .create_ctx = deflate_create,
14284112e31SSergey Senozhatsky .destroy_ctx = deflate_destroy,
143*b8f03cb7SSergey Senozhatsky .setup_params = deflate_setup_params,
144*b8f03cb7SSergey Senozhatsky .release_params = deflate_release_params,
14584112e31SSergey Senozhatsky .name = "deflate",
14684112e31SSergey Senozhatsky };
147