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