* [PATCH] crypto: zstd - convert to acomp
@ 2025-05-16 15:43 Suman Kumar Chakraborty
2025-05-16 17:06 ` Eric Biggers
2025-05-18 21:01 ` Corentin Labbe
0 siblings, 2 replies; 6+ messages in thread
From: Suman Kumar Chakraborty @ 2025-05-16 15:43 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, qat-linux, terrelln, dsterba
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>
---
crypto/zstd.c | 350 +++++++++++++++++++++++++++++---------------------
1 file changed, 205 insertions(+), 145 deletions(-)
diff --git a/crypto/zstd.c b/crypto/zstd.c
index 7570e11b4ee6..d4679075e9f9 100644
--- a/crypto/zstd.c
+++ b/crypto/zstd.c
@@ -12,188 +12,248 @@
#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;
+ u8 wksp[];
};
-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(struct acomp_req *req)
{
- size_t out_len;
- struct zstd_ctx *zctx = ctx;
- const zstd_parameters params = zstd_params();
+ 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;
- out_len = zstd_compress_cctx(zctx->cctx, dst, *dlen, src, slen, ¶ms);
- if (zstd_is_error(out_len))
- return -EINVAL;
- *dlen = out_len;
- return 0;
-}
+ s = crypto_acomp_lock_stream_bh(&zstd_streams);
+ ctx = s->ctx;
-static int zstd_scompress(struct crypto_scomp *tfm, const u8 *src,
- unsigned int slen, u8 *dst, unsigned int *dlen,
- void *ctx)
-{
- return __zstd_compress(src, slen, dst, dlen, ctx);
-}
+ ret = acomp_walk_virt(&walk, req, true);
+ if (ret)
+ goto err;
-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;
-
- out_len = zstd_decompress_dctx(zctx->dctx, dst, *dlen, src, slen);
- if (zstd_is_error(out_len))
- return -EINVAL;
- *dlen = out_len;
- return 0;
-}
-
-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 err;
}
+
+ do {
+ dcur = acomp_walk_next_dst(&walk);
+ if (!dcur) {
+ ret = -ENOSPC;
+ goto err;
+ }
+
+ outbuf.pos = 0;
+ outbuf.dst = (u8 *)walk.dst.virt.addr;
+ outbuf.size = dcur;
+
+ do {
+ scur = acomp_walk_next_src(&walk);
+ 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 err;
+ }
+
+ pending_bytes = zstd_flush_stream(ctx->cctx, &outbuf);
+ if (ZSTD_isError(pending_bytes)) {
+ ret = -EIO;
+ goto err;
+ }
+
+ 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);
+
+err:
+ if (ret)
+ req->dlen = 0;
+ else
+ req->dlen = total_out;
+
+ crypto_acomp_unlock_stream_bh(s);
+
+ return ret;
+}
+
+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 err;
+
+ ctx->dctx = zstd_init_dstream(ZSTD_MAX_SIZE, ctx->wksp, ctx->wksp_size);
+ if (!ctx->dctx) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ 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) {
+ ret = -ENOSPC;
+ goto err;
+ }
+
+ 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 err;
+ }
+
+ 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);
+
+err:
+ 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: 3277a32e6662984c01997bec34d20ab0a98f85ce
--
2.40.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] crypto: zstd - convert to acomp
2025-05-16 15:43 [PATCH] crypto: zstd - convert to acomp Suman Kumar Chakraborty
@ 2025-05-16 17:06 ` Eric Biggers
2025-05-19 14:50 ` Nick Terrell
2025-05-18 21:01 ` Corentin Labbe
1 sibling, 1 reply; 6+ messages in thread
From: Eric Biggers @ 2025-05-16 17:06 UTC (permalink / raw)
To: Suman Kumar Chakraborty
Cc: herbert, linux-crypto, qat-linux, terrelln, dsterba
On Fri, May 16, 2025 at 04:43:31PM +0100, Suman Kumar Chakraborty wrote:
> Convert the implementation to a native acomp interface using zstd
> streaming APIs, eliminating the need for buffer linearization.
How does this affect performance?
- Eric
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] crypto: zstd - convert to acomp
2025-05-16 17:06 ` Eric Biggers
@ 2025-05-19 14:50 ` Nick Terrell
0 siblings, 0 replies; 6+ messages in thread
From: Nick Terrell @ 2025-05-19 14:50 UTC (permalink / raw)
To: Eric Biggers
Cc: Suman Kumar Chakraborty, herbert@gondor.apana.org.au,
linux-crypto@vger.kernel.org, qat-linux@intel.com, Nick Terrell,
dsterba@suse.com
> On May 16, 2025, at 1:06 PM, Eric Biggers <ebiggers@kernel.org> wrote:
>
> >
> On Fri, May 16, 2025 at 04:43:31PM +0100, Suman Kumar Chakraborty wrote:
>> Convert the implementation to a native acomp interface using zstd
>> streaming APIs, eliminating the need for buffer linearization.
>
> How does this affect performance?
Zstd does two extra things when using the streaming API:
1. Allocates a buffer of (Window_Size + 128KB).
2. Both compression and decompression have to copy data into / out of that buffer.
This means there will be an extra memcpy during (de)compression.
I don't know how that will compare against any efficiency gains from
switching to the acomp API. It would be great to see benchmarks here.
When all the data is presented in the first call to the streaming API, and Zstd can
guarantee that there is enough output space, these memcpys can be elided. This
happens, for example, when the data is smaller than the buffer chunk size.
Best,
Nick
> - Eric
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] crypto: zstd - convert to acomp
2025-05-16 15:43 [PATCH] crypto: zstd - convert to acomp Suman Kumar Chakraborty
2025-05-16 17:06 ` Eric Biggers
@ 2025-05-18 21:01 ` Corentin Labbe
2025-05-20 7:57 ` Suman Kumar Chakraborty
1 sibling, 1 reply; 6+ messages in thread
From: Corentin Labbe @ 2025-05-18 21:01 UTC (permalink / raw)
To: Suman Kumar Chakraborty
Cc: herbert, linux-crypto, qat-linux, terrelln, dsterba
Le Fri, May 16, 2025 at 04:43:31PM +0100, Suman Kumar Chakraborty a écrit :
> 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>
> ---
This patch lead to a selftest failure on qemu ARM:
[ 8.966883] alg: self-tests for zstd using zstd-generic failed (rc=-22)
[ 8.967242] ------------[ cut here ]------------
[ 8.968659] WARNING: CPU: 0 PID: 64 at crypto/testmgr.c:5808 alg_test+0x42c/0x654
[ 8.971391] alg: self-tests for zstd using zstd-generic failed (rc=-22)
[ 8.971716] Modules linked in:
[ 8.973531] CPU: 0 UID: 0 PID: 64 Comm: cryptomgr_test Not tainted 6.15.0-rc5-g0f25e6007813-dirty #113 NONE
[ 8.974311] Hardware name: Generic DT based system
[ 8.975088] Call trace:
[ 8.976322] unwind_backtrace from show_stack+0x10/0x14
[ 8.977257] show_stack from dump_stack_lvl+0x54/0x68
[ 8.977910] dump_stack_lvl from __warn+0x80/0x124
[ 8.978418] __warn from warn_slowpath_fmt+0x124/0x18c
[ 8.979081] warn_slowpath_fmt from alg_test+0x42c/0x654
[ 8.979645] alg_test from cryptomgr_test+0x18/0x38
[ 8.980054] cryptomgr_test from kthread+0x108/0x234
[ 8.980603] kthread from ret_from_fork+0x14/0x28
[ 8.981254] Exception stack(0xdfb7dfb0 to 0xdfb7dff8)
[ 8.982194] dfa0: 00000000 00000000 00000000 00000000
[ 8.982734] dfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 8.983394] dfe0: 00000000 00000000 00000000 00000000 00000013 00000000
[ 8.984699] ---[ end trace 0000000000000000 ]---
Regards
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] crypto: zstd - convert to acomp
2025-05-18 21:01 ` Corentin Labbe
@ 2025-05-20 7:57 ` Suman Kumar Chakraborty
2025-05-20 12:13 ` Corentin Labbe
0 siblings, 1 reply; 6+ messages in thread
From: Suman Kumar Chakraborty @ 2025-05-20 7:57 UTC (permalink / raw)
To: Corentin Labbe; +Cc: dsterba, terrelln, linux-crypto, qat-linux, herbert
On Sun, May 18, 2025 at 11:01:54PM +0200, Corentin Labbe wrote:
> Le Fri, May 16, 2025 at 04:43:31PM +0100, Suman Kumar Chakraborty a écrit :
> This patch lead to a selftest failure on qemu ARM:
Hi Coretin,
Can you please share the below
- Configuration for the VM, including size of dram
- Kernel config file
Can you try increasing the DRAM size in the QEMU configuration and
check whether the self-test passes with the updated memory?
Regards
Suman Chakraborty
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] crypto: zstd - convert to acomp
2025-05-20 7:57 ` Suman Kumar Chakraborty
@ 2025-05-20 12:13 ` Corentin Labbe
0 siblings, 0 replies; 6+ messages in thread
From: Corentin Labbe @ 2025-05-20 12:13 UTC (permalink / raw)
To: Suman Kumar Chakraborty
Cc: dsterba, terrelln, linux-crypto, qat-linux, herbert
Le Tue, May 20, 2025 at 08:57:00AM +0100, Suman Kumar Chakraborty a écrit :
> On Sun, May 18, 2025 at 11:01:54PM +0200, Corentin Labbe wrote:
> > Le Fri, May 16, 2025 at 04:43:31PM +0100, Suman Kumar Chakraborty a écrit :
>
> > This patch lead to a selftest failure on qemu ARM:
>
> Hi Coretin,
>
> Can you please share the below
> - Configuration for the VM, including size of dram
> - Kernel config file
>
> Can you try increasing the DRAM size in the QEMU configuration and
> check whether the self-test passes with the updated memory?
It is a qemu-system-arm "-M virt" qemu machine with 4096M so I cannot increase more the memory.
It fails also on qemu-system-x86, qemu-system-mipsel -M malta
You could find all config on my result page: http://kernel.montjoie.ovh/lkml/20250516154331.1651694-1-suman.kumar.chakraborty@intel.com/
Regards
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-05-20 12:13 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-16 15:43 [PATCH] crypto: zstd - convert to acomp Suman Kumar Chakraborty
2025-05-16 17:06 ` Eric Biggers
2025-05-19 14:50 ` Nick Terrell
2025-05-18 21:01 ` Corentin Labbe
2025-05-20 7:57 ` Suman Kumar Chakraborty
2025-05-20 12:13 ` Corentin Labbe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox