[PATCH 5/7] crypto: acomp - Add ACOMP_REQUEST_CLONE
Herbert Xu
herbert at gondor.apana.org.au
Mon Apr 7 03:03:00 PDT 2025
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 at gondor.apana.org.au>
---
crypto/acompress.c | 23 ++++++++++++++++++++++
include/crypto/acompress.h | 30 +++++++++++++++++++++++++----
include/crypto/internal/acompress.h | 11 +++--------
3 files changed, 52 insertions(+), 12 deletions(-)
diff --git a/crypto/acompress.c b/crypto/acompress.c
index 85cef01bd638..9eed20ad0f24 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);
@@ -599,5 +603,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");
diff --git a/include/crypto/acompress.h b/include/crypto/acompress.h
index f383a4008854..93cee67c27c0 100644
--- a/include/crypto/acompress.h
+++ b/include/crypto/acompress.h
@@ -49,10 +49,19 @@
#define MAX_SYNC_COMP_REQSIZE 0
#define ACOMP_REQUEST_ALLOC(name, tfm, gfp) \
+ char __##name##_req[sizeof(struct acomp_req) + \
+ MAX_SYNC_COMP_REQSIZE] CRYPTO_MINALIGN_ATTR; \
+ struct acomp_req *name = acomp_request_alloc_init( \
+ __##name##_req, (tfm), (gfp))
+
+#define ACOMP_REQUEST_ON_STACK(name, tfm) \
char __##name##_req[sizeof(struct acomp_req) + \
MAX_SYNC_COMP_REQSIZE] CRYPTO_MINALIGN_ATTR; \
struct acomp_req *name = acomp_request_on_stack_init( \
- __##name##_req, (tfm), (gfp), false)
+ __##name##_req, (tfm))
+
+#define ACOMP_REQUEST_CLONE(name, gfp) \
+ acomp_request_clone(name, sizeof(__##name##_req), gfp)
struct acomp_req;
struct folio;
@@ -571,12 +580,12 @@ int crypto_acomp_compress(struct acomp_req *req);
*/
int crypto_acomp_decompress(struct acomp_req *req);
-static inline struct acomp_req *acomp_request_on_stack_init(
- char *buf, struct crypto_acomp *tfm, gfp_t gfp, bool stackonly)
+static inline struct acomp_req *acomp_request_alloc_init(
+ char *buf, struct crypto_acomp *tfm, gfp_t gfp)
{
struct acomp_req *req;
- if (!stackonly && (req = acomp_request_alloc(tfm, gfp)))
+ if ((req = acomp_request_alloc(tfm, gfp)))
return req;
req = (void *)buf;
@@ -586,4 +595,17 @@ static inline struct acomp_req *acomp_request_on_stack_init(
return req;
}
+static inline struct acomp_req *acomp_request_on_stack_init(
+ char *buf, struct crypto_acomp *tfm)
+{
+ struct acomp_req *req = (void *)buf;
+
+ acomp_request_set_tfm(req, tfm);
+ req->base.flags = CRYPTO_TFM_REQ_ON_STACK;
+ return req;
+}
+
+struct acomp_req *acomp_request_clone(struct acomp_req *req,
+ size_t total, gfp_t gfp);
+
#endif
diff --git a/include/crypto/internal/acompress.h b/include/crypto/internal/acompress.h
index 8840fd2c1db5..b51d66633935 100644
--- a/include/crypto/internal/acompress.h
+++ b/include/crypto/internal/acompress.h
@@ -17,12 +17,6 @@
#include <linux/spinlock.h>
#include <linux/workqueue_types.h>
-#define ACOMP_REQUEST_ON_STACK(name, tfm) \
- char __##name##_req[sizeof(struct acomp_req) + \
- MAX_SYNC_COMP_REQSIZE] CRYPTO_MINALIGN_ATTR; \
- struct acomp_req *name = acomp_request_on_stack_init( \
- __##name##_req, (tfm), 0, true)
-
#define ACOMP_FBREQ_ON_STACK(name, req) \
char __##name##_req[sizeof(struct acomp_req) + \
MAX_SYNC_COMP_REQSIZE] CRYPTO_MINALIGN_ATTR; \
@@ -245,9 +239,10 @@ static inline struct acomp_req *acomp_fbreq_on_stack_init(
char *buf, struct acomp_req *old)
{
struct crypto_acomp *tfm = crypto_acomp_reqtfm(old);
- struct acomp_req *req;
+ struct acomp_req *req = (void *)buf;
- req = acomp_request_on_stack_init(buf, tfm, 0, true);
+ acomp_request_set_tfm(req, tfm->fb);
+ req->base.flags = CRYPTO_TFM_REQ_ON_STACK;
acomp_request_set_callback(req, acomp_request_flags(old), NULL, NULL);
req->base.flags &= ~CRYPTO_ACOMP_REQ_PRIVATE;
req->base.flags |= old->base.flags & CRYPTO_ACOMP_REQ_PRIVATE;
--
2.39.5
More information about the linux-mtd
mailing list