summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2025-03-09 10:43:17 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2025-03-15 16:21:22 +0800
commit3d72ad46a23ae42450d1f475bb472151dede5b93 (patch)
tree1dc4fa21ca6c6db00464630400e165885ecf4f86 /crypto
parent0af7304c0696ec5b3589af6973b7f27e014c2903 (diff)
crypto: acomp - Move stream management into scomp layer
Rather than allocating the stream memory in the request object, move it into a per-cpu buffer managed by scomp. This takes the stress off the user from having to manage large request objects and setting up their own per-cpu buffers in order to do so. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/acompress.c30
-rw-r--r--crypto/compress.h2
-rw-r--r--crypto/scompress.c90
3 files changed, 58 insertions, 64 deletions
diff --git a/crypto/acompress.c b/crypto/acompress.c
index 30176316140a..ef36ec31d73d 100644
--- a/crypto/acompress.c
+++ b/crypto/acompress.c
@@ -123,36 +123,6 @@ struct crypto_acomp *crypto_alloc_acomp_node(const char *alg_name, u32 type,
}
EXPORT_SYMBOL_GPL(crypto_alloc_acomp_node);
-struct acomp_req *acomp_request_alloc(struct crypto_acomp *acomp)
-{
- struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
- struct acomp_req *req;
-
- req = __acomp_request_alloc(acomp);
- if (req && (tfm->__crt_alg->cra_type != &crypto_acomp_type))
- return crypto_acomp_scomp_alloc_ctx(req);
-
- return req;
-}
-EXPORT_SYMBOL_GPL(acomp_request_alloc);
-
-void acomp_request_free(struct acomp_req *req)
-{
- struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
- struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
-
- if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
- crypto_acomp_scomp_free_ctx(req);
-
- if (req->base.flags & CRYPTO_ACOMP_ALLOC_OUTPUT) {
- acomp->dst_free(req->dst);
- req->dst = NULL;
- }
-
- __acomp_request_free(req);
-}
-EXPORT_SYMBOL_GPL(acomp_request_free);
-
void comp_prepare_alg(struct comp_alg_common *alg)
{
struct crypto_alg *base = &alg->base;
diff --git a/crypto/compress.h b/crypto/compress.h
index c3cedfb5e606..f7737a1fcbbd 100644
--- a/crypto/compress.h
+++ b/crypto/compress.h
@@ -15,8 +15,6 @@ struct acomp_req;
struct comp_alg_common;
int crypto_init_scomp_ops_async(struct crypto_tfm *tfm);
-struct acomp_req *crypto_acomp_scomp_alloc_ctx(struct acomp_req *req);
-void crypto_acomp_scomp_free_ctx(struct acomp_req *req);
void comp_prepare_alg(struct comp_alg_common *alg);
diff --git a/crypto/scompress.c b/crypto/scompress.c
index 1cef6bb06a81..9b6d9bbbc73a 100644
--- a/crypto/scompress.c
+++ b/crypto/scompress.c
@@ -98,13 +98,62 @@ error:
return -ENOMEM;
}
+static void scomp_free_streams(struct scomp_alg *alg)
+{
+ struct crypto_acomp_stream __percpu *stream = alg->stream;
+ int i;
+
+ for_each_possible_cpu(i) {
+ struct crypto_acomp_stream *ps = per_cpu_ptr(stream, i);
+
+ if (!ps->ctx)
+ break;
+
+ alg->free_ctx(ps);
+ }
+
+ free_percpu(stream);
+}
+
+static int scomp_alloc_streams(struct scomp_alg *alg)
+{
+ struct crypto_acomp_stream __percpu *stream;
+ int i;
+
+ stream = alloc_percpu(struct crypto_acomp_stream);
+ if (!stream)
+ return -ENOMEM;
+
+ for_each_possible_cpu(i) {
+ struct crypto_acomp_stream *ps = per_cpu_ptr(stream, i);
+
+ ps->ctx = alg->alloc_ctx();
+ if (IS_ERR(ps->ctx)) {
+ scomp_free_streams(alg);
+ return PTR_ERR(ps->ctx);
+ }
+
+ spin_lock_init(&ps->lock);
+ }
+
+ alg->stream = stream;
+ return 0;
+}
+
static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
{
+ struct scomp_alg *alg = crypto_scomp_alg(__crypto_scomp_tfm(tfm));
int ret = 0;
mutex_lock(&scomp_lock);
+ if (!alg->stream) {
+ ret = scomp_alloc_streams(alg);
+ if (ret)
+ goto unlock;
+ }
if (!scomp_scratch_users++)
ret = crypto_scomp_alloc_scratches();
+unlock:
mutex_unlock(&scomp_lock);
return ret;
@@ -115,7 +164,7 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
void **tfm_ctx = acomp_tfm_ctx(tfm);
struct crypto_scomp *scomp = *tfm_ctx;
- void **ctx = acomp_request_ctx(req);
+ struct crypto_acomp_stream *stream;
struct scomp_scratch *scratch;
void *src, *dst;
unsigned int dlen;
@@ -148,12 +197,15 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
else
dst = scratch->dst;
+ stream = raw_cpu_ptr(crypto_scomp_alg(scomp)->stream);
+ spin_lock(&stream->lock);
if (dir)
ret = crypto_scomp_compress(scomp, src, req->slen,
- dst, &req->dlen, *ctx);
+ dst, &req->dlen, stream->ctx);
else
ret = crypto_scomp_decompress(scomp, src, req->slen,
- dst, &req->dlen, *ctx);
+ dst, &req->dlen, stream->ctx);
+ spin_unlock(&stream->lock);
if (!ret) {
if (!req->dst) {
req->dst = sgl_alloc(req->dlen, GFP_ATOMIC, NULL);
@@ -226,45 +278,19 @@ int crypto_init_scomp_ops_async(struct crypto_tfm *tfm)
crt->compress = scomp_acomp_compress;
crt->decompress = scomp_acomp_decompress;
crt->dst_free = sgl_free;
- crt->reqsize = sizeof(void *);
return 0;
}
-struct acomp_req *crypto_acomp_scomp_alloc_ctx(struct acomp_req *req)
+static void crypto_scomp_destroy(struct crypto_alg *alg)
{
- struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
- struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
- struct crypto_scomp **tfm_ctx = crypto_tfm_ctx(tfm);
- struct crypto_scomp *scomp = *tfm_ctx;
- void *ctx;
-
- ctx = crypto_scomp_alloc_ctx(scomp);
- if (IS_ERR(ctx)) {
- kfree(req);
- return NULL;
- }
-
- *req->__ctx = ctx;
-
- return req;
-}
-
-void crypto_acomp_scomp_free_ctx(struct acomp_req *req)
-{
- struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
- struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
- struct crypto_scomp **tfm_ctx = crypto_tfm_ctx(tfm);
- struct crypto_scomp *scomp = *tfm_ctx;
- void *ctx = *req->__ctx;
-
- if (ctx)
- crypto_scomp_free_ctx(scomp, ctx);
+ scomp_free_streams(__crypto_scomp_alg(alg));
}
static const struct crypto_type crypto_scomp_type = {
.extsize = crypto_alg_extsize,
.init_tfm = crypto_scomp_init_tfm,
+ .destroy = crypto_scomp_destroy,
#ifdef CONFIG_PROC_FS
.show = crypto_scomp_show,
#endif