xref: /linux/drivers/block/zram/backend_deflate.c (revision b8f03cb703a160e14f87a467a4443adc5d940087)
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 
19*b8f03cb7SSergey Senozhatsky static void deflate_release_params(struct zcomp_params *params)
20*b8f03cb7SSergey Senozhatsky {
21*b8f03cb7SSergey Senozhatsky }
22*b8f03cb7SSergey Senozhatsky 
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 
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 
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 
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 
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