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