xref: /linux/drivers/block/zram/backend_deflate.c (revision 52c7b4e2ba508a924c991e681db534e66a851adf)
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 	s32 level;
1884112e31SSergey Senozhatsky };
1984112e31SSergey Senozhatsky 
2084112e31SSergey Senozhatsky static void deflate_destroy(void *ctx)
2184112e31SSergey Senozhatsky {
2284112e31SSergey Senozhatsky 	struct deflate_ctx *zctx = ctx;
2384112e31SSergey Senozhatsky 
2484112e31SSergey Senozhatsky 	if (zctx->cctx.workspace) {
2584112e31SSergey Senozhatsky 		zlib_deflateEnd(&zctx->cctx);
2684112e31SSergey Senozhatsky 		vfree(zctx->cctx.workspace);
2784112e31SSergey Senozhatsky 	}
2884112e31SSergey Senozhatsky 	if (zctx->dctx.workspace) {
2984112e31SSergey Senozhatsky 		zlib_inflateEnd(&zctx->dctx);
3084112e31SSergey Senozhatsky 		vfree(zctx->dctx.workspace);
3184112e31SSergey Senozhatsky 	}
3284112e31SSergey Senozhatsky 	kfree(zctx);
3384112e31SSergey Senozhatsky }
3484112e31SSergey Senozhatsky 
35f2bac7adSSergey Senozhatsky static void *deflate_create(struct zcomp_params *params)
3684112e31SSergey Senozhatsky {
3784112e31SSergey Senozhatsky 	struct deflate_ctx *ctx;
3884112e31SSergey Senozhatsky 	size_t sz;
3984112e31SSergey Senozhatsky 	int ret;
4084112e31SSergey Senozhatsky 
4184112e31SSergey Senozhatsky 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
4284112e31SSergey Senozhatsky 	if (!ctx)
4384112e31SSergey Senozhatsky 		return NULL;
4484112e31SSergey Senozhatsky 
45f2bac7adSSergey Senozhatsky 	if (params->level != ZCOMP_PARAM_NO_LEVEL)
46f2bac7adSSergey Senozhatsky 		ctx->level = params->level;
47f2bac7adSSergey Senozhatsky 	else
4884112e31SSergey Senozhatsky 		ctx->level = Z_DEFAULT_COMPRESSION;
49f2bac7adSSergey Senozhatsky 
5084112e31SSergey Senozhatsky 	sz = zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL);
5184112e31SSergey Senozhatsky 	ctx->cctx.workspace = vzalloc(sz);
5284112e31SSergey Senozhatsky 	if (!ctx->cctx.workspace)
5384112e31SSergey Senozhatsky 		goto error;
5484112e31SSergey Senozhatsky 
5584112e31SSergey Senozhatsky 	ret = zlib_deflateInit2(&ctx->cctx, ctx->level, Z_DEFLATED,
5684112e31SSergey Senozhatsky 				-DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
5784112e31SSergey Senozhatsky 				Z_DEFAULT_STRATEGY);
5884112e31SSergey Senozhatsky 	if (ret != Z_OK)
5984112e31SSergey Senozhatsky 		goto error;
6084112e31SSergey Senozhatsky 
6184112e31SSergey Senozhatsky 	sz = zlib_inflate_workspacesize();
6284112e31SSergey Senozhatsky 	ctx->dctx.workspace = vzalloc(sz);
6384112e31SSergey Senozhatsky 	if (!ctx->dctx.workspace)
6484112e31SSergey Senozhatsky 		goto error;
6584112e31SSergey Senozhatsky 
6684112e31SSergey Senozhatsky 	ret = zlib_inflateInit2(&ctx->dctx, -DEFLATE_DEF_WINBITS);
6784112e31SSergey Senozhatsky 	if (ret != Z_OK)
6884112e31SSergey Senozhatsky 		goto error;
6984112e31SSergey Senozhatsky 
7084112e31SSergey Senozhatsky 	return ctx;
7184112e31SSergey Senozhatsky 
7284112e31SSergey Senozhatsky error:
7384112e31SSergey Senozhatsky 	deflate_destroy(ctx);
7484112e31SSergey Senozhatsky 	return NULL;
7584112e31SSergey Senozhatsky }
7684112e31SSergey Senozhatsky 
77*52c7b4e2SSergey Senozhatsky static int deflate_compress(void *ctx, struct zcomp_req *req)
7884112e31SSergey Senozhatsky {
7984112e31SSergey Senozhatsky 	struct deflate_ctx *zctx = ctx;
8084112e31SSergey Senozhatsky 	struct z_stream_s *deflate;
8184112e31SSergey Senozhatsky 	int ret;
8284112e31SSergey Senozhatsky 
8384112e31SSergey Senozhatsky 	deflate = &zctx->cctx;
8484112e31SSergey Senozhatsky 	ret = zlib_deflateReset(deflate);
8584112e31SSergey Senozhatsky 	if (ret != Z_OK)
8684112e31SSergey Senozhatsky 		return -EINVAL;
8784112e31SSergey Senozhatsky 
88*52c7b4e2SSergey Senozhatsky 	deflate->next_in = (u8 *)req->src;
89*52c7b4e2SSergey Senozhatsky 	deflate->avail_in = req->src_len;
90*52c7b4e2SSergey Senozhatsky 	deflate->next_out = (u8 *)req->dst;
91*52c7b4e2SSergey Senozhatsky 	deflate->avail_out = req->dst_len;
9284112e31SSergey Senozhatsky 
9384112e31SSergey Senozhatsky 	ret = zlib_deflate(deflate, Z_FINISH);
9484112e31SSergey Senozhatsky 	if (ret != Z_STREAM_END)
9584112e31SSergey Senozhatsky 		return -EINVAL;
9684112e31SSergey Senozhatsky 
97*52c7b4e2SSergey Senozhatsky 	req->dst_len = deflate->total_out;
9884112e31SSergey Senozhatsky 	return 0;
9984112e31SSergey Senozhatsky }
10084112e31SSergey Senozhatsky 
101*52c7b4e2SSergey Senozhatsky static int deflate_decompress(void *ctx, struct zcomp_req *req)
10284112e31SSergey Senozhatsky {
10384112e31SSergey Senozhatsky 	struct deflate_ctx *zctx = ctx;
10484112e31SSergey Senozhatsky 	struct z_stream_s *inflate;
10584112e31SSergey Senozhatsky 	int ret;
10684112e31SSergey Senozhatsky 
10784112e31SSergey Senozhatsky 	inflate = &zctx->dctx;
10884112e31SSergey Senozhatsky 
10984112e31SSergey Senozhatsky 	ret = zlib_inflateReset(inflate);
11084112e31SSergey Senozhatsky 	if (ret != Z_OK)
11184112e31SSergey Senozhatsky 		return -EINVAL;
11284112e31SSergey Senozhatsky 
113*52c7b4e2SSergey Senozhatsky 	inflate->next_in = (u8 *)req->src;
114*52c7b4e2SSergey Senozhatsky 	inflate->avail_in = req->src_len;
115*52c7b4e2SSergey Senozhatsky 	inflate->next_out = (u8 *)req->dst;
116*52c7b4e2SSergey Senozhatsky 	inflate->avail_out = req->dst_len;
11784112e31SSergey Senozhatsky 
11884112e31SSergey Senozhatsky 	ret = zlib_inflate(inflate, Z_SYNC_FLUSH);
11984112e31SSergey Senozhatsky 	if (ret != Z_STREAM_END)
12084112e31SSergey Senozhatsky 		return -EINVAL;
12184112e31SSergey Senozhatsky 
12284112e31SSergey Senozhatsky 	return 0;
12384112e31SSergey Senozhatsky }
12484112e31SSergey Senozhatsky 
12584112e31SSergey Senozhatsky const struct zcomp_ops backend_deflate = {
12684112e31SSergey Senozhatsky 	.compress	= deflate_compress,
12784112e31SSergey Senozhatsky 	.decompress	= deflate_decompress,
12884112e31SSergey Senozhatsky 	.create_ctx	= deflate_create,
12984112e31SSergey Senozhatsky 	.destroy_ctx	= deflate_destroy,
13084112e31SSergey Senozhatsky 	.name		= "deflate",
13184112e31SSergey Senozhatsky };
132