netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: Ard Biesheuvel <ardb@kernel.org>,
	Herbert Xu <herbert@gondor.apana.org.au>,
	Eric Biggers <ebiggers@kernel.org>,
	Kees Cook <keescook@chromium.org>,
	Haren Myneni <haren@us.ibm.com>, Nick Terrell <terrelln@fb.com>,
	Minchan Kim <minchan@kernel.org>,
	Sergey Senozhatsky <senozhatsky@chromium.org>,
	Jens Axboe <axboe@kernel.dk>,
	Giovanni Cabiddu <giovanni.cabiddu@intel.com>,
	Richard Weinberger <richard@nod.at>,
	David Ahern <dsahern@kernel.org>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Steffen Klassert <steffen.klassert@secunet.com>,
	linux-kernel@vger.kernel.org, linux-block@vger.kernel.org,
	qat-linux@intel.com, linuxppc-dev@lists.ozlabs.org,
	linux-mtd@lists.infradead.org, netdev@vger.kernel.org
Subject: [RFC PATCH 20/21] crypto: deflate - implement acomp API directly
Date: Tue, 18 Jul 2023 14:58:46 +0200	[thread overview]
Message-ID: <20230718125847.3869700-21-ardb@kernel.org> (raw)
In-Reply-To: <20230718125847.3869700-1-ardb@kernel.org>

Drop the scomp implementation of deflate, which can only operate on
contiguous in- and output buffer, and replace it with an implementation
of acomp directly. This implementation walks the scatterlists, removing
the need for the caller to use scratch buffers to present the input and
output in a contiguous manner.

This is intended for use by the IPcomp code, which currently needs to
'linearize' SKBs in order for the compression to be able to consume the
input in a single chunk.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 crypto/deflate.c             | 315 +++++++-------------
 include/crypto/scatterwalk.h |   2 +-
 2 files changed, 113 insertions(+), 204 deletions(-)

diff --git a/crypto/deflate.c b/crypto/deflate.c
index 0955040ca9e64146..112683473df2b588 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -6,246 +6,154 @@
  * by IPCOMP (RFC 3173 & RFC 2394).
  *
  * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
- *
- * FIXME: deflate transforms will require up to a total of about 436k of kernel
- * memory on i386 (390k for compression, the rest for decompression), as the
- * current zlib kernel code uses a worst case pre-allocation system by default.
- * This needs to be fixed so that the amount of memory required is properly
- * related to the  winbits and memlevel parameters.
- *
- * The default winbits of 11 should suit most packets, and it may be something
- * to configure on a per-tfm basis in the future.
- *
- * Currently, compression history is not maintained between tfm calls, as
- * it is not needed for IPCOMP and keeps the code simpler.  It can be
- * implemented if someone wants it.
+ * Copyright (c) 2023 Google, LLC. <ardb@kernel.org>
  */
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/crypto.h>
 #include <linux/zlib.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
 #include <linux/net.h>
-#include <crypto/internal/scompress.h>
+#include <linux/scatterlist.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/internal/acompress.h>
 
 #define DEFLATE_DEF_LEVEL		Z_DEFAULT_COMPRESSION
 #define DEFLATE_DEF_WINBITS		11
 #define DEFLATE_DEF_MEMLEVEL		MAX_MEM_LEVEL
 
-struct deflate_ctx {
-	struct z_stream_s comp_stream;
-	struct z_stream_s decomp_stream;
+struct deflate_req_ctx {
+	struct z_stream_s stream;
+	u8 workspace[];
 };
 
-static int deflate_comp_init(struct deflate_ctx *ctx)
+static int deflate_process(struct acomp_req *req, struct z_stream_s *stream,
+			   int (*process)(struct z_stream_s *, int))
 {
-	int ret = 0;
-	struct z_stream_s *stream = &ctx->comp_stream;
+	unsigned int slen = req->slen;
+	unsigned int dlen = req->dlen;
+	struct scatter_walk src, dst;
+	unsigned int scur, dcur;
+	int ret;
 
-	stream->workspace = vzalloc(zlib_deflate_workspacesize(
-				-DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL));
-	if (!stream->workspace) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	stream->avail_in = stream->avail_out = 0;
+
+	scatterwalk_start(&src, req->src);
+	scatterwalk_start(&dst, req->dst);
+
+	scur = dcur = 0;
+
+	do {
+		if (stream->avail_in == 0) {
+			if (scur) {
+				slen -= scur;
+
+				scatterwalk_unmap(stream->next_in - scur);
+				scatterwalk_advance(&src, scur);
+				scatterwalk_done(&src, 0, slen);
+			}
+
+			scur = scatterwalk_clamp(&src, slen);
+			if (scur) {
+				stream->next_in = scatterwalk_map(&src);
+				stream->avail_in = scur;
+			}
+		}
+
+		if (stream->avail_out == 0) {
+			if (dcur) {
+				dlen -= dcur;
+
+				scatterwalk_unmap(stream->next_out - dcur);
+				scatterwalk_advance(&dst, dcur);
+				scatterwalk_done(&dst, 1, dlen);
+			}
+
+			dcur = scatterwalk_clamp(&dst, dlen);
+			if (!dcur)
+				break;
+
+			stream->next_out = scatterwalk_map(&dst);
+			stream->avail_out = dcur;
+		}
+
+		ret = process(stream, (slen == scur) ? Z_FINISH : Z_SYNC_FLUSH);
+	} while (ret == Z_OK);
+
+	if (scur)
+		scatterwalk_unmap(stream->next_in - scur);
+	if (dcur)
+		scatterwalk_unmap(stream->next_out - dcur);
+
+	if (ret != Z_STREAM_END)
+		return -EINVAL;
+
+	req->dlen = stream->total_out;
+	return 0;
+}
+
+static int deflate_compress(struct acomp_req *req)
+{
+	struct deflate_req_ctx *ctx = acomp_request_ctx(req);
+	struct z_stream_s *stream = &ctx->stream;
+	int ret;
+
+        if (!req->src || !req->slen || !req->dst || !req->dlen)
+                return -EINVAL;
+
+	stream->workspace = ctx->workspace;
 	ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
 	                        -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
 	                        Z_DEFAULT_STRATEGY);
-	if (ret != Z_OK) {
-		ret = -EINVAL;
-		goto out_free;
-	}
-out:
+	if (ret != Z_OK)
+		return -EINVAL;
+
+	ret = deflate_process(req, stream, zlib_deflate);
+	zlib_deflateEnd(stream);
 	return ret;
-out_free:
-	vfree(stream->workspace);
-	goto out;
 }
 
-static int deflate_decomp_init(struct deflate_ctx *ctx)
+static int deflate_decompress(struct acomp_req *req)
 {
-	int ret = 0;
-	struct z_stream_s *stream = &ctx->decomp_stream;
+	struct deflate_req_ctx *ctx = acomp_request_ctx(req);
+	struct z_stream_s *stream = &ctx->stream;
+	int ret;
 
-	stream->workspace = vzalloc(zlib_inflate_workspacesize());
-	if (!stream->workspace) {
-		ret = -ENOMEM;
-		goto out;
-	}
+        if (!req->src || !req->slen || !req->dst || !req->dlen)
+                return -EINVAL;
+
+	stream->workspace = ctx->workspace;
 	ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
-	if (ret != Z_OK) {
-		ret = -EINVAL;
-		goto out_free;
-	}
-out:
-	return ret;
-out_free:
-	vfree(stream->workspace);
-	goto out;
-}
+	if (ret != Z_OK)
+		return -EINVAL;
 
-static void deflate_comp_exit(struct deflate_ctx *ctx)
-{
-	zlib_deflateEnd(&ctx->comp_stream);
-	vfree(ctx->comp_stream.workspace);
-}
-
-static void deflate_decomp_exit(struct deflate_ctx *ctx)
-{
-	zlib_inflateEnd(&ctx->decomp_stream);
-	vfree(ctx->decomp_stream.workspace);
-}
-
-static int __deflate_init(void *ctx)
-{
-	int ret;
-
-	ret = deflate_comp_init(ctx);
-	if (ret)
-		goto out;
-	ret = deflate_decomp_init(ctx);
-	if (ret)
-		deflate_comp_exit(ctx);
-out:
+	ret = deflate_process(req, stream, zlib_inflate);
+	req->dlen = stream->total_out;
+	zlib_inflateEnd(stream);
 	return ret;
 }
 
-static void *deflate_alloc_ctx(struct crypto_scomp *tfm)
-{
-	struct deflate_ctx *ctx;
-	int ret;
+static struct acomp_alg alg = {
+	.compress		= deflate_compress,
+	.decompress		= deflate_decompress,
 
-	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-	if (!ctx)
-		return ERR_PTR(-ENOMEM);
-
-	ret = __deflate_init(ctx);
-	if (ret) {
-		kfree(ctx);
-		return ERR_PTR(ret);
-	}
-
-	return ctx;
-}
-
-static void __deflate_exit(void *ctx)
-{
-	deflate_comp_exit(ctx);
-	deflate_decomp_exit(ctx);
-}
-
-static void deflate_free_ctx(struct crypto_scomp *tfm, void *ctx)
-{
-	__deflate_exit(ctx);
-	kfree_sensitive(ctx);
-}
-
-static int __deflate_compress(const u8 *src, unsigned int slen,
-			      u8 *dst, unsigned int *dlen, void *ctx)
-{
-	int ret = 0;
-	struct deflate_ctx *dctx = ctx;
-	struct z_stream_s *stream = &dctx->comp_stream;
-
-	ret = zlib_deflateReset(stream);
-	if (ret != Z_OK) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	stream->next_in = (u8 *)src;
-	stream->avail_in = slen;
-	stream->next_out = (u8 *)dst;
-	stream->avail_out = *dlen;
-
-	ret = zlib_deflate(stream, Z_FINISH);
-	if (ret != Z_STREAM_END) {
-		ret = -EINVAL;
-		goto out;
-	}
-	ret = 0;
-	*dlen = stream->total_out;
-out:
-	return ret;
-}
-
-static int deflate_scompress(struct crypto_scomp *tfm, const u8 *src,
-			     unsigned int slen, u8 *dst, unsigned int *dlen,
-			     void *ctx)
-{
-	return __deflate_compress(src, slen, dst, dlen, ctx);
-}
-
-static int __deflate_decompress(const u8 *src, unsigned int slen,
-				u8 *dst, unsigned int *dlen, void *ctx)
-{
-
-	int ret = 0;
-	struct deflate_ctx *dctx = ctx;
-	struct z_stream_s *stream = &dctx->decomp_stream;
-
-	ret = zlib_inflateReset(stream);
-	if (ret != Z_OK) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	stream->next_in = (u8 *)src;
-	stream->avail_in = slen;
-	stream->next_out = (u8 *)dst;
-	stream->avail_out = *dlen;
-
-	ret = zlib_inflate(stream, Z_SYNC_FLUSH);
-	/*
-	 * Work around a bug in zlib, which sometimes wants to taste an extra
-	 * byte when being used in the (undocumented) raw deflate mode.
-	 * (From USAGI).
-	 */
-	if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
-		u8 zerostuff = 0;
-		stream->next_in = &zerostuff;
-		stream->avail_in = 1;
-		ret = zlib_inflate(stream, Z_FINISH);
-	}
-	if (ret != Z_STREAM_END) {
-		ret = -EINVAL;
-		goto out;
-	}
-	ret = 0;
-	*dlen = stream->total_out;
-out:
-	return ret;
-}
-
-static int deflate_sdecompress(struct crypto_scomp *tfm, const u8 *src,
-			       unsigned int slen, u8 *dst, unsigned int *dlen,
-			       void *ctx)
-{
-	return __deflate_decompress(src, slen, dst, dlen, ctx);
-}
-
-static struct scomp_alg scomp = {
-	.alloc_ctx		= deflate_alloc_ctx,
-	.free_ctx		= deflate_free_ctx,
-	.compress		= deflate_scompress,
-	.decompress		= deflate_sdecompress,
-	.base			= {
-		.cra_name	= "deflate",
-		.cra_driver_name = "deflate-scomp",
-		.cra_module	 = THIS_MODULE,
-	}
+	.base.cra_name		= "deflate",
+	.base.cra_driver_name	= "deflate-generic",
+	.base.cra_module	= THIS_MODULE,
 };
 
 static int __init deflate_mod_init(void)
 {
-	return crypto_register_scomp(&scomp);
+	size_t size = max(zlib_inflate_workspacesize(),
+			  zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS,
+						     DEFLATE_DEF_MEMLEVEL));
+
+	alg.reqsize = struct_size_t(struct deflate_req_ctx, workspace, size);
+	return crypto_register_acomp(&alg);
 }
 
 static void __exit deflate_mod_fini(void)
 {
-	crypto_unregister_scomp(&scomp);
+	crypto_unregister_acomp(&alg);
 }
 
 subsys_initcall(deflate_mod_init);
@@ -254,4 +162,5 @@ module_exit(deflate_mod_fini);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
+MODULE_AUTHOR("Ard Biesheuvel <ardb@kernel.org>");
 MODULE_ALIAS_CRYPTO("deflate");
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 32fc4473175b1d81..46dc7b21bf9ecbd0 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -51,7 +51,7 @@ static inline struct page *scatterwalk_page(struct scatter_walk *walk)
 	return sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
 }
 
-static inline void scatterwalk_unmap(void *vaddr)
+static inline void scatterwalk_unmap(const void *vaddr)
 {
 	kunmap_local(vaddr);
 }
-- 
2.39.2


  parent reply	other threads:[~2023-07-18 13:01 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-18 12:58 [RFC PATCH 00/21] crypto: consolidate and clean up compression APIs Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 01/21] crypto: scomp - Revert "add support for deflate rfc1950 (zlib)" Ard Biesheuvel
2023-07-18 22:32   ` Eric Biggers
2023-07-18 22:54     ` Eric Biggers
2023-07-18 23:06       ` Ard Biesheuvel
2023-07-21  9:10   ` Simon Horman
2023-08-03  9:51   ` Giovanni Cabiddu
2023-08-03  9:59     ` Ard Biesheuvel
2023-08-03 10:29       ` Giovanni Cabiddu
2023-07-18 12:58 ` [RFC PATCH 02/21] crypto: qat - Drop support for allocating destination buffers Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 03/21] crypto: acompress - Drop destination scatterlist allocation feature Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 04/21] net: ipcomp: Migrate to acomp API from deprecated comp API Ard Biesheuvel
2023-07-21  9:11   ` Simon Horman
2023-07-18 12:58 ` [RFC PATCH 05/21] ubifs: Pass worst-case buffer size to compression routines Ard Biesheuvel
2023-07-18 22:38   ` Eric Biggers
2023-07-19  8:33     ` Ard Biesheuvel
2023-07-19 14:23       ` Zhihao Cheng
2023-07-19 14:38         ` Ard Biesheuvel
2023-07-20  1:23           ` Zhihao Cheng
2023-07-18 12:58 ` [RFC PATCH 06/21] ubifs: Avoid allocating buffer space unnecessarily Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 07/21] ubifs: Migrate to acomp compression API Ard Biesheuvel
2023-07-21  9:19   ` Simon Horman
2023-07-18 12:58 ` [RFC PATCH 08/21] zram: " Ard Biesheuvel
2023-07-21  9:22   ` Simon Horman
2023-07-18 12:58 ` [RFC PATCH 09/21] crypto: nx - Migrate to scomp API Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 10/21] crypto: 842 - drop obsolete 'comp' implementation Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 11/21] crypto: deflate " Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 12/21] crypto: lz4 " Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 13/21] crypto: lz4hc " Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 14/21] crypto: lzo-rle " Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 15/21] crypto: lzo " Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 16/21] crypto: zstd " Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 17/21] crypto: cavium/zip " Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 18/21] crypto: compress_null " Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 19/21] crypto: remove obsolete 'comp' compression API Ard Biesheuvel
2023-07-21 11:07   ` Simon Horman
2023-07-18 12:58 ` Ard Biesheuvel [this message]
2023-07-21 11:12   ` [RFC PATCH 20/21] crypto: deflate - implement acomp API directly Simon Horman
2023-07-21 11:17     ` Ard Biesheuvel
2023-07-18 12:58 ` [RFC PATCH 21/21] crypto: scompress - Drop the use of per-cpu scratch buffers Ard Biesheuvel
2023-07-28  9:55 ` [RFC PATCH 00/21] crypto: consolidate and clean up compression APIs Herbert Xu
2023-07-28  9:57   ` Ard Biesheuvel
2023-07-28  9:59     ` Herbert Xu
2023-07-28 10:03       ` Ard Biesheuvel
2023-07-28 10:05         ` Herbert Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230718125847.3869700-21-ardb@kernel.org \
    --to=ardb@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=dsahern@kernel.org \
    --cc=ebiggers@kernel.org \
    --cc=edumazet@google.com \
    --cc=giovanni.cabiddu@intel.com \
    --cc=haren@us.ibm.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=keescook@chromium.org \
    --cc=kuba@kernel.org \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=minchan@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=qat-linux@intel.com \
    --cc=richard@nod.at \
    --cc=senozhatsky@chromium.org \
    --cc=steffen.klassert@secunet.com \
    --cc=terrelln@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).