* [v5] crypto: zstd - convert to acomp
@ 2025-05-27 12:43 Suman Kumar Chakraborty
2025-05-30 6:30 ` kernel test robot
0 siblings, 1 reply; 2+ messages in thread
From: Suman Kumar Chakraborty @ 2025-05-27 12:43 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, qat-linux, dsterba, terrelln, clabbe.montjoie
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>
---
v4->v5
- Swapping the order of acomp_walk_done_src/dst during
decompression for a single flat buffer.
v3->v4:
- Added acomp_walk_done_src/dst calls after completing
compression/decompression for a single flat buffer
v2->v3:
- Updated the logic to verify the existence of a single flat
buffer using the acomp walk API.
v1->v2:
- Made the wksp address to be 8 byte aligned.
- Added logic to use Zstd non streaming APIs for single flat buffer.
crypto/zstd.c | 389 ++++++++++++++++++++++++++++++++------------------
1 file changed, 252 insertions(+), 137 deletions(-)
diff --git a/crypto/zstd.c b/crypto/zstd.c
index 7570e11b4ee6..f84f3aae7428 100644
--- a/crypto/zstd.c
+++ b/crypto/zstd.c
@@ -12,188 +12,303 @@
#include <linux/net.h>
#include <linux/vmalloc.h>
#include <linux/zstd.h>
-#include <crypto/internal/scompress.h>
+#include <crypto/internal/acompress.h>
+#include <crypto/scatterwalk.h>
-#define ZSTD_DEF_LEVEL 3
+#define ZSTD_DEF_LEVEL 3
+#define ZSTD_MAX_WINDOWLOG 18
+#define ZSTD_MAX_SIZE BIT(ZSTD_MAX_WINDOWLOG)
struct zstd_ctx {
zstd_cctx *cctx;
zstd_dctx *dctx;
- void *cwksp;
- void *dwksp;
+ size_t wksp_size;
+ zstd_parameters params;
+ union {
+ u8 wksp[0];
+ /* forces alignment */
+ u64 _align;
+ };
};
-static zstd_parameters zstd_params(void)
+static DEFINE_MUTEX(zstd_stream_lock);
+
+static void *zstd_alloc_stream(void)
{
- return zstd_get_params(ZSTD_DEF_LEVEL, 0);
-}
-
-static int zstd_comp_init(struct zstd_ctx *ctx)
-{
- int ret = 0;
- const zstd_parameters params = zstd_params();
- const size_t wksp_size = zstd_cctx_workspace_bound(¶ms.cParams);
-
- ctx->cwksp = vzalloc(wksp_size);
- if (!ctx->cwksp) {
- ret = -ENOMEM;
- goto out;
- }
-
- ctx->cctx = zstd_init_cctx(ctx->cwksp, wksp_size);
- if (!ctx->cctx) {
- ret = -EINVAL;
- goto out_free;
- }
-out:
- return ret;
-out_free:
- vfree(ctx->cwksp);
- goto out;
-}
-
-static int zstd_decomp_init(struct zstd_ctx *ctx)
-{
- int ret = 0;
- const size_t wksp_size = zstd_dctx_workspace_bound();
-
- ctx->dwksp = vzalloc(wksp_size);
- if (!ctx->dwksp) {
- ret = -ENOMEM;
- goto out;
- }
-
- ctx->dctx = zstd_init_dctx(ctx->dwksp, wksp_size);
- if (!ctx->dctx) {
- ret = -EINVAL;
- goto out_free;
- }
-out:
- return ret;
-out_free:
- vfree(ctx->dwksp);
- goto out;
-}
-
-static void zstd_comp_exit(struct zstd_ctx *ctx)
-{
- vfree(ctx->cwksp);
- ctx->cwksp = NULL;
- ctx->cctx = NULL;
-}
-
-static void zstd_decomp_exit(struct zstd_ctx *ctx)
-{
- vfree(ctx->dwksp);
- ctx->dwksp = NULL;
- ctx->dctx = NULL;
-}
-
-static int __zstd_init(void *ctx)
-{
- int ret;
-
- ret = zstd_comp_init(ctx);
- if (ret)
- return ret;
- ret = zstd_decomp_init(ctx);
- if (ret)
- zstd_comp_exit(ctx);
- return ret;
-}
-
-static void *zstd_alloc_ctx(void)
-{
- int ret;
+ zstd_parameters params;
struct zstd_ctx *ctx;
+ size_t wksp_size;
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ params = zstd_get_params(ZSTD_DEF_LEVEL, ZSTD_MAX_SIZE);
+
+ wksp_size = max_t(size_t,
+ zstd_cstream_workspace_bound(¶ms.cParams),
+ zstd_dstream_workspace_bound(ZSTD_MAX_SIZE));
+ if (!wksp_size)
+ return ERR_PTR(-EINVAL);
+
+ ctx = kvmalloc(sizeof(*ctx) + wksp_size, GFP_KERNEL);
if (!ctx)
return ERR_PTR(-ENOMEM);
- ret = __zstd_init(ctx);
- if (ret) {
- kfree(ctx);
- return ERR_PTR(ret);
- }
+ ctx->params = params;
+ ctx->wksp_size = wksp_size;
return ctx;
}
-static void __zstd_exit(void *ctx)
+static struct crypto_acomp_streams zstd_streams = {
+ .alloc_ctx = zstd_alloc_stream,
+ .cfree_ctx = kvfree,
+};
+
+static int zstd_init(struct crypto_acomp *acomp_tfm)
{
- zstd_comp_exit(ctx);
- zstd_decomp_exit(ctx);
+ int ret = 0;
+
+ mutex_lock(&zstd_stream_lock);
+ ret = crypto_acomp_alloc_streams(&zstd_streams);
+ mutex_unlock(&zstd_stream_lock);
+
+ return ret;
}
-static void zstd_free_ctx(void *ctx)
+static void zstd_exit(struct crypto_acomp *acomp_tfm)
{
- __zstd_exit(ctx);
- kfree_sensitive(ctx);
+ crypto_acomp_free_streams(&zstd_streams);
}
-static int __zstd_compress(const u8 *src, unsigned int slen,
- u8 *dst, unsigned int *dlen, void *ctx)
+static int zstd_compress_one(struct acomp_req *req, struct zstd_ctx *ctx, unsigned int *dlen)
{
- size_t out_len;
- struct zstd_ctx *zctx = ctx;
- const zstd_parameters params = zstd_params();
+ unsigned int out_len;
- out_len = zstd_compress_cctx(zctx->cctx, dst, *dlen, src, slen, ¶ms);
+ ctx->cctx = zstd_init_cctx(ctx->wksp, ctx->wksp_size);
+ if (!ctx->cctx)
+ return -EINVAL;
+
+ out_len = zstd_compress_cctx(ctx->cctx, sg_virt(req->dst),
+ req->dlen, sg_virt(req->src),
+ req->slen, &ctx->params);
if (zstd_is_error(out_len))
return -EINVAL;
+
*dlen = out_len;
+
return 0;
}
-static int zstd_scompress(struct crypto_scomp *tfm, const u8 *src,
- unsigned int slen, u8 *dst, unsigned int *dlen,
- void *ctx)
+static int zstd_compress(struct acomp_req *req)
{
- return __zstd_compress(src, slen, dst, dlen, ctx);
-}
+ struct crypto_acomp_stream *s;
+ unsigned int pos, scur, dcur;
+ unsigned int total_out = 0;
+ bool data_available = true;
+ zstd_out_buffer outbuf;
+ struct acomp_walk walk;
+ zstd_in_buffer inbuf;
+ struct zstd_ctx *ctx;
+ size_t pending_bytes;
+ size_t num_bytes;
+ int ret;
-static int __zstd_decompress(const u8 *src, unsigned int slen,
- u8 *dst, unsigned int *dlen, void *ctx)
-{
- size_t out_len;
- struct zstd_ctx *zctx = ctx;
+ s = crypto_acomp_lock_stream_bh(&zstd_streams);
+ ctx = s->ctx;
- out_len = zstd_decompress_dctx(zctx->dctx, dst, *dlen, src, slen);
- if (zstd_is_error(out_len))
- return -EINVAL;
- *dlen = out_len;
- return 0;
-}
+ ret = acomp_walk_virt(&walk, req, true);
+ if (ret)
+ goto out;
-static int zstd_sdecompress(struct crypto_scomp *tfm, const u8 *src,
- unsigned int slen, u8 *dst, unsigned int *dlen,
- void *ctx)
-{
- return __zstd_decompress(src, slen, dst, dlen, ctx);
-}
-
-static struct scomp_alg scomp = {
- .alloc_ctx = zstd_alloc_ctx,
- .free_ctx = zstd_free_ctx,
- .compress = zstd_scompress,
- .decompress = zstd_sdecompress,
- .base = {
- .cra_name = "zstd",
- .cra_driver_name = "zstd-scomp",
- .cra_module = THIS_MODULE,
+ ctx->cctx = zstd_init_cstream(&ctx->params, 0, ctx->wksp, ctx->wksp_size);
+ if (!ctx->cctx) {
+ ret = -EINVAL;
+ goto out;
}
+
+ do {
+ dcur = acomp_walk_next_dst(&walk);
+ if (!dcur) {
+ ret = -ENOSPC;
+ goto out;
+ }
+
+ outbuf.pos = 0;
+ outbuf.dst = (u8 *)walk.dst.virt.addr;
+ outbuf.size = dcur;
+
+ do {
+ scur = acomp_walk_next_src(&walk);
+ if (dcur == req->dlen && scur == req->slen) {
+ ret = zstd_compress_one(req, ctx, &total_out);
+ acomp_walk_done_src(&walk, scur);
+ acomp_walk_done_dst(&walk, dcur);
+ goto out;
+ }
+
+ if (scur) {
+ inbuf.pos = 0;
+ inbuf.src = walk.src.virt.addr;
+ inbuf.size = scur;
+ } else {
+ data_available = false;
+ break;
+ }
+
+ num_bytes = zstd_compress_stream(ctx->cctx, &outbuf, &inbuf);
+ if (ZSTD_isError(num_bytes)) {
+ ret = -EIO;
+ goto out;
+ }
+
+ pending_bytes = zstd_flush_stream(ctx->cctx, &outbuf);
+ if (ZSTD_isError(pending_bytes)) {
+ ret = -EIO;
+ goto out;
+ }
+ acomp_walk_done_src(&walk, inbuf.pos);
+ } while (dcur != outbuf.pos);
+
+ total_out += outbuf.pos;
+ acomp_walk_done_dst(&walk, dcur);
+ } while (data_available);
+
+ pos = outbuf.pos;
+ num_bytes = zstd_end_stream(ctx->cctx, &outbuf);
+ if (ZSTD_isError(num_bytes))
+ ret = -EIO;
+ else
+ total_out += (outbuf.pos - pos);
+
+out:
+ if (ret)
+ req->dlen = 0;
+ else
+ req->dlen = total_out;
+
+ crypto_acomp_unlock_stream_bh(s);
+
+ return ret;
+}
+
+static int zstd_decompress_one(struct acomp_req *req, struct zstd_ctx *ctx, unsigned int *dlen)
+{
+ size_t out_len;
+
+ ctx->dctx = zstd_init_dctx(ctx->wksp, ctx->wksp_size);
+ if (!ctx->dctx)
+ return -EINVAL;
+
+ out_len = zstd_decompress_dctx(ctx->dctx, sg_virt(req->dst),
+ req->dlen, sg_virt(req->src),
+ req->slen);
+ if (zstd_is_error(out_len))
+ return -EINVAL;
+
+ *dlen = out_len;
+
+ return 0;
+}
+
+static int zstd_decompress(struct acomp_req *req)
+{
+ struct crypto_acomp_stream *s;
+ unsigned int total_out = 0;
+ unsigned int scur, dcur;
+ zstd_out_buffer outbuf;
+ struct acomp_walk walk;
+ zstd_in_buffer inbuf;
+ struct zstd_ctx *ctx;
+ size_t pending_bytes;
+ int ret;
+
+ s = crypto_acomp_lock_stream_bh(&zstd_streams);
+ ctx = s->ctx;
+
+ ret = acomp_walk_virt(&walk, req, true);
+ if (ret)
+ goto out;
+
+ ctx->dctx = zstd_init_dstream(ZSTD_MAX_SIZE, ctx->wksp, ctx->wksp_size);
+ if (!ctx->dctx) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ do {
+ scur = acomp_walk_next_src(&walk);
+ if (scur) {
+ inbuf.pos = 0;
+ inbuf.size = scur;
+ inbuf.src = walk.src.virt.addr;
+ } else {
+ break;
+ }
+
+ do {
+ dcur = acomp_walk_next_dst(&walk);
+ if (dcur == req->dlen && scur == req->slen) {
+ ret = zstd_decompress_one(req, ctx, &total_out);
+ acomp_walk_done_dst(&walk, dcur);
+ acomp_walk_done_src(&walk, scur);
+ goto out;
+ }
+
+ if (!dcur) {
+ ret = -ENOSPC;
+ goto out;
+ }
+
+ outbuf.pos = 0;
+ outbuf.dst = (u8 *)walk.dst.virt.addr;
+ outbuf.size = dcur;
+
+ pending_bytes = zstd_decompress_stream(ctx->dctx, &outbuf, &inbuf);
+ if (ZSTD_isError(pending_bytes)) {
+ ret = -EIO;
+ goto out;
+ }
+
+ total_out += outbuf.pos;
+
+ acomp_walk_done_dst(&walk, outbuf.pos);
+ } while (scur != inbuf.pos);
+
+ if (scur)
+ acomp_walk_done_src(&walk, scur);
+ } while (ret == 0);
+
+out:
+ if (ret)
+ req->dlen = 0;
+ else
+ req->dlen = total_out;
+
+ crypto_acomp_unlock_stream_bh(s);
+
+ return ret;
+}
+
+static struct acomp_alg zstd_acomp = {
+ .base = {
+ .cra_name = "zstd",
+ .cra_driver_name = "zstd-generic",
+ .cra_flags = CRYPTO_ALG_REQ_VIRT,
+ .cra_module = THIS_MODULE,
+ },
+ .init = zstd_init,
+ .exit = zstd_exit,
+ .compress = zstd_compress,
+ .decompress = zstd_decompress,
};
static int __init zstd_mod_init(void)
{
- return crypto_register_scomp(&scomp);
+ return crypto_register_acomp(&zstd_acomp);
}
static void __exit zstd_mod_fini(void)
{
- crypto_unregister_scomp(&scomp);
+ crypto_unregister_acomp(&zstd_acomp);
}
module_init(zstd_mod_init);
base-commit: b939a747dcec83d77fb23660204b82cf64f0b944
--
2.40.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [v5] crypto: zstd - convert to acomp
2025-05-27 12:43 [v5] crypto: zstd - convert to acomp Suman Kumar Chakraborty
@ 2025-05-30 6:30 ` kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2025-05-30 6:30 UTC (permalink / raw)
To: Suman Kumar Chakraborty
Cc: oe-lkp, lkp, Giovanni Cabiddu, linux-crypto, herbert, qat-linux,
dsterba, terrelln, clabbe.montjoie, oliver.sang
Hello,
kernel test robot noticed "WARNING:at_crypto/testmgr.c:#alg_test" on:
commit: 5ff7b07fa1266efb5aced0ad981974c6b0ebbbef ("[v5] crypto: zstd - convert to acomp")
url: https://github.com/intel-lab-lkp/linux/commits/Suman-Kumar-Chakraborty/crypto-zstd-convert-to-acomp/20250527-204451
patch link: https://lore.kernel.org/all/20250527124302.533682-1-suman.kumar.chakraborty@intel.com/
patch subject: [v5] crypto: zstd - convert to acomp
in testcase: boot
config: i386-randconfig-012-20250528
compiler: clang-20
test machine: qemu-system-i386 -enable-kvm -cpu SandyBridge -smp 2 -m 4G
(please refer to attached dmesg/kmsg for entire log/backtrace)
+-------------------------------------------------------+------------+------------+
| | b939a747dc | 5ff7b07fa1 |
+-------------------------------------------------------+------------+------------+
| boot_successes | 6 | 0 |
| boot_failures | 0 | 6 |
| WARNING:at_crypto/testmgr.c:#alg_test | 0 | 6 |
| EIP:alg_test | 0 | 6 |
| WARNING:at_mm/vmalloc.c:#remove_vm_area | 0 | 6 |
| EIP:remove_vm_area | 0 | 6 |
| WARNING:at_mm/vmalloc.c:#vfree | 0 | 6 |
| EIP:vfree | 0 | 6 |
| BUG:kernel_NULL_pointer_dereference,address | 0 | 6 |
| Oops | 0 | 6 |
| EIP:memset | 0 | 6 |
| Kernel_panic-not_syncing:Fatal_exception_in_interrupt | 0 | 6 |
+-------------------------------------------------------+------------+------------+
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202505301305.ee79d8f3-lkp@intel.com
[ 2.703189][ T82] ------------[ cut here ]------------
[ 2.704516][ T82] alg: self-tests for zstd using zstd-generic failed (rc=-22)
[ 2.704572][ T82] WARNING: CPU: 0 PID: 82 at crypto/testmgr.c:5886 alg_test (ld-temp.o:?)
[ 2.706216][ T82] Modules linked in:
[ 2.706621][ T82] CPU: 0 UID: 0 PID: 82 Comm: cryptomgr_test Tainted: G T 6.15.0-rc5-00384-g5ff7b07fa126 #1 PREEMPT(undef)
[ 2.707912][ T82] Tainted: [T]=RANDSTRUCT
[ 2.708361][ T82] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[ 2.709408][ T82] EIP: alg_test (ld-temp.o:?)
[ 2.709886][ T82] Code: 52 68 87 c4 77 82 89 d7 e8 3f ef a4 ff 83 c4 10 b8 fe ff ff ff 83 fe fe 74 9e 56 53 57 68 f7 86 78 82 e8 45 69 ac ff 83 c4 10 <0f> 0b 89 f0 eb 88 8b 45 f0 81 fb dc 00 00 00 0f 83 03 01 00 00 8b
All code
========
0: 52 push %rdx
1: 68 87 c4 77 82 push $0xffffffff8277c487
6: 89 d7 mov %edx,%edi
8: e8 3f ef a4 ff call 0xffffffffffa4ef4c
d: 83 c4 10 add $0x10,%esp
10: b8 fe ff ff ff mov $0xfffffffe,%eax
15: 83 fe fe cmp $0xfffffffe,%esi
18: 74 9e je 0xffffffffffffffb8
1a: 56 push %rsi
1b: 53 push %rbx
1c: 57 push %rdi
1d: 68 f7 86 78 82 push $0xffffffff827886f7
22: e8 45 69 ac ff call 0xffffffffffac696c
27: 83 c4 10 add $0x10,%esp
2a:* 0f 0b ud2 <-- trapping instruction
2c: 89 f0 mov %esi,%eax
2e: eb 88 jmp 0xffffffffffffffb8
30: 8b 45 f0 mov -0x10(%rbp),%eax
33: 81 fb dc 00 00 00 cmp $0xdc,%ebx
39: 0f 83 03 01 00 00 jae 0x142
3f: 8b .byte 0x8b
Code starting with the faulting instruction
===========================================
0: 0f 0b ud2
2: 89 f0 mov %esi,%eax
4: eb 88 jmp 0xffffffffffffff8e
6: 8b 45 f0 mov -0x10(%rbp),%eax
9: 81 fb dc 00 00 00 cmp $0xdc,%ebx
f: 0f 83 03 01 00 00 jae 0x118
15: 8b .byte 0x8b
[ 2.711902][ T82] EAX: 0000003b EBX: 84f9fa00 ECX: 80000002 EDX: 00000000
[ 2.720746][ T82] ESI: ffffffea EDI: 84f9fa80 EBP: 84ebdf08 ESP: 84ebde60
[ 2.721478][ T82] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 EFLAGS: 00010286
[ 2.722299][ T82] CR0: 80050033 CR2: 77d20327 CR3: 03341000 CR4: 00040690
[ 2.723047][ T82] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 2.723759][ T82] DR6: fffe0ff0 DR7: 00000400
[ 2.724246][ T82] Call Trace:
[ 2.724611][ T82] ? kvm_sched_clock_read (ld-temp.o:?)
[ 2.725147][ T82] ? sched_clock_noinstr (ld-temp.o:?)
[ 2.725673][ T82] ? local_clock_noinstr (ld-temp.o:?)
[ 2.726213][ T82] ? __this_cpu_preempt_check (ld-temp.o:?)
[ 2.726782][ T82] ? __this_cpu_preempt_check (ld-temp.o:?)
[ 2.727341][ T82] ? __kthread_parkme (ld-temp.o:?)
[ 2.727843][ T82] ? __kthread_parkme (ld-temp.o:?)
[ 2.728433][ T82] ? __this_cpu_preempt_check (ld-temp.o:?)
[ 2.729006][ T82] ? lockdep_hardirqs_on (ld-temp.o:?)
[ 2.729570][ T82] cryptomgr_test (ld-temp.o:?)
[ 2.730042][ T82] kthread (ld-temp.o:?)
[ 2.730476][ T82] ? schedule_tail (ld-temp.o:?)
[ 2.730950][ T82] ? unregister_key_type (ld-temp.o:?)
[ 2.731474][ T82] ? kthreadd (ld-temp.o:?)
[ 2.731914][ T82] ? kthreadd (ld-temp.o:?)
[ 2.732368][ T82] ? kthreadd (ld-temp.o:?)
[ 2.732796][ T82] ret_from_fork (ld-temp.o:?)
[ 2.733256][ T82] ret_from_fork_asm (kbuild/obj/consumer/i386-randconfig-012-20250528/arch/x86/entry/entry_32.S:737)
[ 2.733764][ T82] entry_INT80_32 (kbuild/obj/consumer/i386-randconfig-012-20250528/arch/x86/entry/entry_32.S:945)
[ 2.734274][ T82] irq event stamp: 389
[ 2.734695][ T82] hardirqs last enabled at (397): console_unlock (ld-temp.o:?)
[ 2.735568][ T82] hardirqs last disabled at (404): console_unlock (ld-temp.o:?)
[ 2.736449][ T82] softirqs last enabled at (200): __do_softirq (ld-temp.o:?)
[ 2.737295][ T82] softirqs last disabled at (189): __do_softirq (ld-temp.o:?)
[ 2.738129][ T82] ---[ end trace 0000000000000000 ]---
[ 2.746180][ T92] alg: No test for 842 (842-scomp)
The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20250530/202505301305.ee79d8f3-lkp@intel.com
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-05-30 6:30 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-27 12:43 [v5] crypto: zstd - convert to acomp Suman Kumar Chakraborty
2025-05-30 6:30 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).