1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include <linux/kernel.h> 4 #include <linux/slab.h> 5 #include <linux/vmalloc.h> 6 #include <linux/zlib.h> 7 8 #include "backend_deflate.h" 9 10 /* Use the same value as crypto API */ 11 #define DEFLATE_DEF_WINBITS (-11) 12 #define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL 13 14 struct deflate_ctx { 15 struct z_stream_s cctx; 16 struct z_stream_s dctx; 17 }; 18 19 static void deflate_release_params(struct zcomp_params *params) 20 { 21 } 22 23 static int deflate_setup_params(struct zcomp_params *params) 24 { 25 if (params->level == ZCOMP_PARAM_NOT_SET) 26 params->level = Z_DEFAULT_COMPRESSION; 27 if (params->deflate.winbits == ZCOMP_PARAM_NOT_SET) 28 params->deflate.winbits = DEFLATE_DEF_WINBITS; 29 30 return 0; 31 } 32 33 static void deflate_destroy(struct zcomp_ctx *ctx) 34 { 35 struct deflate_ctx *zctx = ctx->context; 36 37 if (!zctx) 38 return; 39 40 if (zctx->cctx.workspace) { 41 zlib_deflateEnd(&zctx->cctx); 42 vfree(zctx->cctx.workspace); 43 } 44 if (zctx->dctx.workspace) { 45 zlib_inflateEnd(&zctx->dctx); 46 vfree(zctx->dctx.workspace); 47 } 48 kfree(zctx); 49 } 50 51 static int deflate_create(struct zcomp_params *params, struct zcomp_ctx *ctx) 52 { 53 struct deflate_ctx *zctx; 54 size_t sz; 55 int ret; 56 57 zctx = kzalloc(sizeof(*zctx), GFP_KERNEL); 58 if (!zctx) 59 return -ENOMEM; 60 61 ctx->context = zctx; 62 sz = zlib_deflate_workspacesize(params->deflate.winbits, MAX_MEM_LEVEL); 63 zctx->cctx.workspace = vzalloc(sz); 64 if (!zctx->cctx.workspace) 65 goto error; 66 67 ret = zlib_deflateInit2(&zctx->cctx, params->level, Z_DEFLATED, 68 params->deflate.winbits, DEFLATE_DEF_MEMLEVEL, 69 Z_DEFAULT_STRATEGY); 70 if (ret != Z_OK) 71 goto error; 72 73 sz = zlib_inflate_workspacesize(); 74 zctx->dctx.workspace = vzalloc(sz); 75 if (!zctx->dctx.workspace) 76 goto error; 77 78 ret = zlib_inflateInit2(&zctx->dctx, params->deflate.winbits); 79 if (ret != Z_OK) 80 goto error; 81 82 return 0; 83 84 error: 85 deflate_destroy(ctx); 86 return -EINVAL; 87 } 88 89 static int deflate_compress(struct zcomp_params *params, struct zcomp_ctx *ctx, 90 struct zcomp_req *req) 91 { 92 struct deflate_ctx *zctx = ctx->context; 93 struct z_stream_s *deflate; 94 int ret; 95 96 deflate = &zctx->cctx; 97 ret = zlib_deflateReset(deflate); 98 if (ret != Z_OK) 99 return -EINVAL; 100 101 deflate->next_in = (u8 *)req->src; 102 deflate->avail_in = req->src_len; 103 deflate->next_out = (u8 *)req->dst; 104 deflate->avail_out = req->dst_len; 105 106 ret = zlib_deflate(deflate, Z_FINISH); 107 if (ret != Z_STREAM_END) 108 return -EINVAL; 109 110 req->dst_len = deflate->total_out; 111 return 0; 112 } 113 114 static int deflate_decompress(struct zcomp_params *params, 115 struct zcomp_ctx *ctx, 116 struct zcomp_req *req) 117 { 118 struct deflate_ctx *zctx = ctx->context; 119 struct z_stream_s *inflate; 120 int ret; 121 122 inflate = &zctx->dctx; 123 124 ret = zlib_inflateReset(inflate); 125 if (ret != Z_OK) 126 return -EINVAL; 127 128 inflate->next_in = (u8 *)req->src; 129 inflate->avail_in = req->src_len; 130 inflate->next_out = (u8 *)req->dst; 131 inflate->avail_out = req->dst_len; 132 133 ret = zlib_inflate(inflate, Z_SYNC_FLUSH); 134 if (ret != Z_STREAM_END) 135 return -EINVAL; 136 137 return 0; 138 } 139 140 const struct zcomp_ops backend_deflate = { 141 .compress = deflate_compress, 142 .decompress = deflate_decompress, 143 .create_ctx = deflate_create, 144 .destroy_ctx = deflate_destroy, 145 .setup_params = deflate_setup_params, 146 .release_params = deflate_release_params, 147 .name = "deflate", 148 }; 149