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