Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

crypto: zstd - convert to acomp

Convert the implementation to a native acomp interface using zstd
streaming APIs, eliminating the need for buffer linearization.

This includes:
- Removal of the scomp interface in favor of acomp
- Refactoring of stream allocation, initialization, and handling for
both compression and decompression using Zstandard streaming APIs
- Replacement of crypto_register_scomp() with crypto_register_acomp()
for module registration

Signed-off-by: Suman Kumar Chakraborty <suman.kumar.chakraborty@intel.com>
Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Suman Kumar Chakraborty and committed by
Herbert Xu
f5ad93ff 1adaaeeb

+249 -137
+249 -137
crypto/zstd.c
··· 12 12 #include <linux/net.h> 13 13 #include <linux/vmalloc.h> 14 14 #include <linux/zstd.h> 15 - #include <crypto/internal/scompress.h> 15 + #include <crypto/internal/acompress.h> 16 + #include <crypto/scatterwalk.h> 16 17 17 18 18 - #define ZSTD_DEF_LEVEL 3 19 + #define ZSTD_DEF_LEVEL 3 20 + #define ZSTD_MAX_WINDOWLOG 18 21 + #define ZSTD_MAX_SIZE BIT(ZSTD_MAX_WINDOWLOG) 19 22 20 23 struct zstd_ctx { 21 24 zstd_cctx *cctx; 22 25 zstd_dctx *dctx; 23 - void *cwksp; 24 - void *dwksp; 26 + size_t wksp_size; 27 + zstd_parameters params; 28 + u8 wksp[0] __aligned(8); 25 29 }; 26 30 27 - static zstd_parameters zstd_params(void) 31 + static DEFINE_MUTEX(zstd_stream_lock); 32 + 33 + static void *zstd_alloc_stream(void) 28 34 { 29 - return zstd_get_params(ZSTD_DEF_LEVEL, 0); 30 - } 31 - 32 - static int zstd_comp_init(struct zstd_ctx *ctx) 33 - { 34 - int ret = 0; 35 - const zstd_parameters params = zstd_params(); 36 - const size_t wksp_size = zstd_cctx_workspace_bound(&params.cParams); 37 - 38 - ctx->cwksp = vzalloc(wksp_size); 39 - if (!ctx->cwksp) { 40 - ret = -ENOMEM; 41 - goto out; 42 - } 43 - 44 - ctx->cctx = zstd_init_cctx(ctx->cwksp, wksp_size); 45 - if (!ctx->cctx) { 46 - ret = -EINVAL; 47 - goto out_free; 48 - } 49 - out: 50 - return ret; 51 - out_free: 52 - vfree(ctx->cwksp); 53 - goto out; 54 - } 55 - 56 - static int zstd_decomp_init(struct zstd_ctx *ctx) 57 - { 58 - int ret = 0; 59 - const size_t wksp_size = zstd_dctx_workspace_bound(); 60 - 61 - ctx->dwksp = vzalloc(wksp_size); 62 - if (!ctx->dwksp) { 63 - ret = -ENOMEM; 64 - goto out; 65 - } 66 - 67 - ctx->dctx = zstd_init_dctx(ctx->dwksp, wksp_size); 68 - if (!ctx->dctx) { 69 - ret = -EINVAL; 70 - goto out_free; 71 - } 72 - out: 73 - return ret; 74 - out_free: 75 - vfree(ctx->dwksp); 76 - goto out; 77 - } 78 - 79 - static void zstd_comp_exit(struct zstd_ctx *ctx) 80 - { 81 - vfree(ctx->cwksp); 82 - ctx->cwksp = NULL; 83 - ctx->cctx = NULL; 84 - } 85 - 86 - static void zstd_decomp_exit(struct zstd_ctx *ctx) 87 - { 88 - vfree(ctx->dwksp); 89 - ctx->dwksp = NULL; 90 - ctx->dctx = NULL; 91 - } 92 - 93 - static int __zstd_init(void *ctx) 94 - { 95 - int ret; 96 - 97 - ret = zstd_comp_init(ctx); 98 - if (ret) 99 - return ret; 100 - ret = zstd_decomp_init(ctx); 101 - if (ret) 102 - zstd_comp_exit(ctx); 103 - return ret; 104 - } 105 - 106 - static void *zstd_alloc_ctx(void) 107 - { 108 - int ret; 35 + zstd_parameters params; 109 36 struct zstd_ctx *ctx; 37 + size_t wksp_size; 110 38 111 - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 39 + params = zstd_get_params(ZSTD_DEF_LEVEL, ZSTD_MAX_SIZE); 40 + 41 + wksp_size = max_t(size_t, 42 + zstd_cstream_workspace_bound(&params.cParams), 43 + zstd_dstream_workspace_bound(ZSTD_MAX_SIZE)); 44 + if (!wksp_size) 45 + return ERR_PTR(-EINVAL); 46 + 47 + ctx = kvmalloc(sizeof(*ctx) + wksp_size, GFP_KERNEL); 112 48 if (!ctx) 113 49 return ERR_PTR(-ENOMEM); 114 50 115 - ret = __zstd_init(ctx); 116 - if (ret) { 117 - kfree(ctx); 118 - return ERR_PTR(ret); 119 - } 51 + ctx->params = params; 52 + ctx->wksp_size = wksp_size; 120 53 121 54 return ctx; 122 55 } 123 56 124 - static void __zstd_exit(void *ctx) 57 + static struct crypto_acomp_streams zstd_streams = { 58 + .alloc_ctx = zstd_alloc_stream, 59 + .cfree_ctx = kvfree, 60 + }; 61 + 62 + static int zstd_init(struct crypto_acomp *acomp_tfm) 125 63 { 126 - zstd_comp_exit(ctx); 127 - zstd_decomp_exit(ctx); 64 + int ret = 0; 65 + 66 + mutex_lock(&zstd_stream_lock); 67 + ret = crypto_acomp_alloc_streams(&zstd_streams); 68 + mutex_unlock(&zstd_stream_lock); 69 + 70 + return ret; 128 71 } 129 72 130 - static void zstd_free_ctx(void *ctx) 73 + static void zstd_exit(struct crypto_acomp *acomp_tfm) 131 74 { 132 - __zstd_exit(ctx); 133 - kfree_sensitive(ctx); 75 + crypto_acomp_free_streams(&zstd_streams); 134 76 } 135 77 136 - static int __zstd_compress(const u8 *src, unsigned int slen, 137 - u8 *dst, unsigned int *dlen, void *ctx) 78 + static int zstd_compress_one(struct acomp_req *req, struct zstd_ctx *ctx, 79 + const void *src, void *dst, unsigned int *dlen) 138 80 { 139 - size_t out_len; 140 - struct zstd_ctx *zctx = ctx; 141 - const zstd_parameters params = zstd_params(); 81 + unsigned int out_len; 142 82 143 - out_len = zstd_compress_cctx(zctx->cctx, dst, *dlen, src, slen, &params); 83 + ctx->cctx = zstd_init_cctx(ctx->wksp, ctx->wksp_size); 84 + if (!ctx->cctx) 85 + return -EINVAL; 86 + 87 + out_len = zstd_compress_cctx(ctx->cctx, dst, req->dlen, src, req->slen, 88 + &ctx->params); 144 89 if (zstd_is_error(out_len)) 145 90 return -EINVAL; 91 + 146 92 *dlen = out_len; 93 + 147 94 return 0; 148 95 } 149 96 150 - static int zstd_scompress(struct crypto_scomp *tfm, const u8 *src, 151 - unsigned int slen, u8 *dst, unsigned int *dlen, 152 - void *ctx) 97 + static int zstd_compress(struct acomp_req *req) 153 98 { 154 - return __zstd_compress(src, slen, dst, dlen, ctx); 155 - } 99 + struct crypto_acomp_stream *s; 100 + unsigned int pos, scur, dcur; 101 + unsigned int total_out = 0; 102 + bool data_available = true; 103 + zstd_out_buffer outbuf; 104 + struct acomp_walk walk; 105 + zstd_in_buffer inbuf; 106 + struct zstd_ctx *ctx; 107 + size_t pending_bytes; 108 + size_t num_bytes; 109 + int ret; 156 110 157 - static int __zstd_decompress(const u8 *src, unsigned int slen, 158 - u8 *dst, unsigned int *dlen, void *ctx) 159 - { 160 - size_t out_len; 161 - struct zstd_ctx *zctx = ctx; 111 + s = crypto_acomp_lock_stream_bh(&zstd_streams); 112 + ctx = s->ctx; 162 113 163 - out_len = zstd_decompress_dctx(zctx->dctx, dst, *dlen, src, slen); 164 - if (zstd_is_error(out_len)) 165 - return -EINVAL; 166 - *dlen = out_len; 167 - return 0; 168 - } 114 + ret = acomp_walk_virt(&walk, req, true); 115 + if (ret) 116 + goto out; 169 117 170 - static int zstd_sdecompress(struct crypto_scomp *tfm, const u8 *src, 171 - unsigned int slen, u8 *dst, unsigned int *dlen, 172 - void *ctx) 173 - { 174 - return __zstd_decompress(src, slen, dst, dlen, ctx); 175 - } 176 - 177 - static struct scomp_alg scomp = { 178 - .alloc_ctx = zstd_alloc_ctx, 179 - .free_ctx = zstd_free_ctx, 180 - .compress = zstd_scompress, 181 - .decompress = zstd_sdecompress, 182 - .base = { 183 - .cra_name = "zstd", 184 - .cra_driver_name = "zstd-scomp", 185 - .cra_module = THIS_MODULE, 118 + ctx->cctx = zstd_init_cstream(&ctx->params, 0, ctx->wksp, ctx->wksp_size); 119 + if (!ctx->cctx) { 120 + ret = -EINVAL; 121 + goto out; 186 122 } 123 + 124 + do { 125 + dcur = acomp_walk_next_dst(&walk); 126 + if (!dcur) { 127 + ret = -ENOSPC; 128 + goto out; 129 + } 130 + 131 + outbuf.pos = 0; 132 + outbuf.dst = (u8 *)walk.dst.virt.addr; 133 + outbuf.size = dcur; 134 + 135 + do { 136 + scur = acomp_walk_next_src(&walk); 137 + if (dcur == req->dlen && scur == req->slen) { 138 + ret = zstd_compress_one(req, ctx, walk.src.virt.addr, 139 + walk.dst.virt.addr, &total_out); 140 + acomp_walk_done_src(&walk, scur); 141 + acomp_walk_done_dst(&walk, dcur); 142 + goto out; 143 + } 144 + 145 + if (scur) { 146 + inbuf.pos = 0; 147 + inbuf.src = walk.src.virt.addr; 148 + inbuf.size = scur; 149 + } else { 150 + data_available = false; 151 + break; 152 + } 153 + 154 + num_bytes = zstd_compress_stream(ctx->cctx, &outbuf, &inbuf); 155 + if (ZSTD_isError(num_bytes)) { 156 + ret = -EIO; 157 + goto out; 158 + } 159 + 160 + pending_bytes = zstd_flush_stream(ctx->cctx, &outbuf); 161 + if (ZSTD_isError(pending_bytes)) { 162 + ret = -EIO; 163 + goto out; 164 + } 165 + acomp_walk_done_src(&walk, inbuf.pos); 166 + } while (dcur != outbuf.pos); 167 + 168 + total_out += outbuf.pos; 169 + acomp_walk_done_dst(&walk, dcur); 170 + } while (data_available); 171 + 172 + pos = outbuf.pos; 173 + num_bytes = zstd_end_stream(ctx->cctx, &outbuf); 174 + if (ZSTD_isError(num_bytes)) 175 + ret = -EIO; 176 + else 177 + total_out += (outbuf.pos - pos); 178 + 179 + out: 180 + if (ret) 181 + req->dlen = 0; 182 + else 183 + req->dlen = total_out; 184 + 185 + crypto_acomp_unlock_stream_bh(s); 186 + 187 + return ret; 188 + } 189 + 190 + static int zstd_decompress_one(struct acomp_req *req, struct zstd_ctx *ctx, 191 + const void *src, void *dst, unsigned int *dlen) 192 + { 193 + size_t out_len; 194 + 195 + ctx->dctx = zstd_init_dctx(ctx->wksp, ctx->wksp_size); 196 + if (!ctx->dctx) 197 + return -EINVAL; 198 + 199 + out_len = zstd_decompress_dctx(ctx->dctx, dst, req->dlen, src, req->slen); 200 + if (zstd_is_error(out_len)) 201 + return -EINVAL; 202 + 203 + *dlen = out_len; 204 + 205 + return 0; 206 + } 207 + 208 + static int zstd_decompress(struct acomp_req *req) 209 + { 210 + struct crypto_acomp_stream *s; 211 + unsigned int total_out = 0; 212 + unsigned int scur, dcur; 213 + zstd_out_buffer outbuf; 214 + struct acomp_walk walk; 215 + zstd_in_buffer inbuf; 216 + struct zstd_ctx *ctx; 217 + size_t pending_bytes; 218 + int ret; 219 + 220 + s = crypto_acomp_lock_stream_bh(&zstd_streams); 221 + ctx = s->ctx; 222 + 223 + ret = acomp_walk_virt(&walk, req, true); 224 + if (ret) 225 + goto out; 226 + 227 + ctx->dctx = zstd_init_dstream(ZSTD_MAX_SIZE, ctx->wksp, ctx->wksp_size); 228 + if (!ctx->dctx) { 229 + ret = -EINVAL; 230 + goto out; 231 + } 232 + 233 + do { 234 + scur = acomp_walk_next_src(&walk); 235 + if (scur) { 236 + inbuf.pos = 0; 237 + inbuf.size = scur; 238 + inbuf.src = walk.src.virt.addr; 239 + } else { 240 + break; 241 + } 242 + 243 + do { 244 + dcur = acomp_walk_next_dst(&walk); 245 + if (dcur == req->dlen && scur == req->slen) { 246 + ret = zstd_decompress_one(req, ctx, walk.src.virt.addr, 247 + walk.dst.virt.addr, &total_out); 248 + acomp_walk_done_dst(&walk, dcur); 249 + acomp_walk_done_src(&walk, scur); 250 + goto out; 251 + } 252 + 253 + if (!dcur) { 254 + ret = -ENOSPC; 255 + goto out; 256 + } 257 + 258 + outbuf.pos = 0; 259 + outbuf.dst = (u8 *)walk.dst.virt.addr; 260 + outbuf.size = dcur; 261 + 262 + pending_bytes = zstd_decompress_stream(ctx->dctx, &outbuf, &inbuf); 263 + if (ZSTD_isError(pending_bytes)) { 264 + ret = -EIO; 265 + goto out; 266 + } 267 + 268 + total_out += outbuf.pos; 269 + 270 + acomp_walk_done_dst(&walk, outbuf.pos); 271 + } while (scur != inbuf.pos); 272 + 273 + if (scur) 274 + acomp_walk_done_src(&walk, scur); 275 + } while (ret == 0); 276 + 277 + out: 278 + if (ret) 279 + req->dlen = 0; 280 + else 281 + req->dlen = total_out; 282 + 283 + crypto_acomp_unlock_stream_bh(s); 284 + 285 + return ret; 286 + } 287 + 288 + static struct acomp_alg zstd_acomp = { 289 + .base = { 290 + .cra_name = "zstd", 291 + .cra_driver_name = "zstd-generic", 292 + .cra_flags = CRYPTO_ALG_REQ_VIRT, 293 + .cra_module = THIS_MODULE, 294 + }, 295 + .init = zstd_init, 296 + .exit = zstd_exit, 297 + .compress = zstd_compress, 298 + .decompress = zstd_decompress, 187 299 }; 188 300 189 301 static int __init zstd_mod_init(void) 190 302 { 191 - return crypto_register_scomp(&scomp); 303 + return crypto_register_acomp(&zstd_acomp); 192 304 } 193 305 194 306 static void __exit zstd_mod_fini(void) 195 307 { 196 - crypto_unregister_scomp(&scomp); 308 + crypto_unregister_acomp(&zstd_acomp); 197 309 } 198 310 199 311 module_init(zstd_mod_init);