Commit 097c432c authored by Herbert Xu's avatar Herbert Xu
Browse files

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: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent d0a5c9d0
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -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");
+26 −4
Original line number Diff line number Diff line
@@ -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
+3 −8
Original line number Diff line number Diff line
@@ -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;