aboutsummaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2025-04-07 18:03:00 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2025-04-16 15:16:20 +0800
commit097c432caaa6d91f87732fe991cb08139e31101a (patch)
treecbf90c936c17accd824b0f16e4bc7210f6eb02ef /crypto
parentd0a5c9d079decad95a77638c19bc5b3a6a0ffe21 (diff)
crypto: acomp - Add ACOMP_REQUEST_CLONE
Add a new helper ACOMP_REQUEST_CLONE that will transform a stack request into a dynamically allocated one if possible, and otherwise switch it over to the sycnrhonous fallback transform. The intended usage is: ACOMP_STACK_ON_REQUEST(req, tfm); ... err = crypto_acomp_compress(req); /* The request cannot complete synchronously. */ if (err == -EAGAIN) { /* This will not fail. */ req = ACOMP_REQUEST_CLONE(req, gfp); /* Redo operation. */ err = crypto_acomp_compress(req); } Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/acompress.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/crypto/acompress.c b/crypto/acompress.c
index f343b1a4b1d1..530b9bfd03a5 100644
--- a/crypto/acompress.c
+++ b/crypto/acompress.c
@@ -316,6 +316,8 @@ int crypto_acomp_compress(struct acomp_req *req)
{
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+ if (acomp_req_on_stack(req) && acomp_is_async(tfm))
+ return -EAGAIN;
if (crypto_acomp_req_chain(tfm) || acomp_request_issg(req))
crypto_acomp_reqtfm(req)->compress(req);
return acomp_do_req_chain(req, true);
@@ -326,6 +328,8 @@ int crypto_acomp_decompress(struct acomp_req *req)
{
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+ if (acomp_req_on_stack(req) && acomp_is_async(tfm))
+ return -EAGAIN;
if (crypto_acomp_req_chain(tfm) || acomp_request_issg(req))
crypto_acomp_reqtfm(req)->decompress(req);
return acomp_do_req_chain(req, false);
@@ -603,5 +607,24 @@ int acomp_walk_virt(struct acomp_walk *__restrict walk,
}
EXPORT_SYMBOL_GPL(acomp_walk_virt);
+struct acomp_req *acomp_request_clone(struct acomp_req *req,
+ size_t total, gfp_t gfp)
+{
+ struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+ struct acomp_req *nreq;
+
+ nreq = kmalloc(total, gfp);
+ if (!nreq) {
+ acomp_request_set_tfm(req, tfm->fb);
+ req->base.flags = CRYPTO_TFM_REQ_ON_STACK;
+ return req;
+ }
+
+ memcpy(nreq, req, total);
+ acomp_request_set_tfm(req, tfm);
+ return req;
+}
+EXPORT_SYMBOL_GPL(acomp_request_clone);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Asynchronous compression type");