From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 13/29] crypto: scatterwalk - add new functions for iterating through data
Date: Sun, 29 Dec 2024 16:14:02 -0800 [thread overview]
Message-ID: <20241230001418.74739-14-ebiggers@kernel.org> (raw)
In-Reply-To: <20241230001418.74739-1-ebiggers@kernel.org>
From: Eric Biggers <ebiggers@google.com>
Add scatterwalk_next() which consolidates scatterwalk_clamp() and
scatterwalk_map(). Also add scatterwalk_done_src() and
scatterwalk_done_dst() which consolidate scatterwalk_unmap(),
scatterwalk_advance(), and scatterwalk_done() or scatterwalk_pagedone().
A later patch will remove scatterwalk_done() and scatterwalk_pagedone().
The new code eliminates the error-prone 'more' parameter. Advancing to
the next sg entry now only happens just-in-time in scatterwalk_next().
The new code also pairs the dcache flush more closely with the actual
write, similar to memcpy_to_page(). Previously it was paired with
advancing to the next page. This is currently causing bugs where the
dcache flush is incorrectly being skipped, usually due to
scatterwalk_copychunks() being called without a following
scatterwalk_done(). The dcache flush may have been placed where it was
in order to not call flush_dcache_page() redundantly when visiting a
page more than once. However, that case is rare in practice, and most
architectures either do not implement flush_dcache_page() anyway or
implement it lazily where it just clears a page flag.
Another limitation of the old code was that by the time the flush
happened, there was no way to tell if more than one page needed to be
flushed. That has been sufficient because the code goes page by page,
but I would like to optimize that on !HIGHMEM platforms. The new code
makes this possible, and a later patch will implement this optimization.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
include/crypto/scatterwalk.h | 69 ++++++++++++++++++++++++++++++++----
1 file changed, 63 insertions(+), 6 deletions(-)
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 5c7765f601e0..8e83c43016c9 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -62,16 +62,10 @@ static inline unsigned int scatterwalk_clamp(struct scatter_walk *walk,
if (walk->offset >= walk->sg->offset + walk->sg->length)
scatterwalk_start(walk, sg_next(walk->sg));
return min(nbytes, scatterwalk_pagelen(walk));
}
-static inline void scatterwalk_advance(struct scatter_walk *walk,
- unsigned int nbytes)
-{
- walk->offset += nbytes;
-}
-
static inline struct page *scatterwalk_page(struct scatter_walk *walk)
{
return sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
}
@@ -84,10 +78,28 @@ static inline void *scatterwalk_map(struct scatter_walk *walk)
{
return kmap_local_page(scatterwalk_page(walk)) +
offset_in_page(walk->offset);
}
+/**
+ * scatterwalk_next() - Get the next data buffer in a scatterlist walk
+ * @walk: the scatter_walk
+ * @total: the total number of bytes remaining, > 0
+ * @nbytes_ret: (out) the next number of bytes available, <= @total
+ *
+ * Return: A virtual address for the next segment of data from the scatterlist.
+ * The caller must call scatterwalk_done_src() or scatterwalk_done_dst()
+ * when it is done using this virtual address.
+ */
+static inline void *scatterwalk_next(struct scatter_walk *walk,
+ unsigned int total,
+ unsigned int *nbytes_ret)
+{
+ *nbytes_ret = scatterwalk_clamp(walk, total);
+ return scatterwalk_map(walk);
+}
+
static inline void scatterwalk_pagedone(struct scatter_walk *walk, int out,
unsigned int more)
{
if (out) {
struct page *page;
@@ -106,10 +118,55 @@ static inline void scatterwalk_done(struct scatter_walk *walk, int out,
if (!more || walk->offset >= walk->sg->offset + walk->sg->length ||
!(walk->offset & (PAGE_SIZE - 1)))
scatterwalk_pagedone(walk, out, more);
}
+static inline void scatterwalk_advance(struct scatter_walk *walk,
+ unsigned int nbytes)
+{
+ walk->offset += nbytes;
+}
+
+/**
+ * scatterwalk_done_src() - Finish one step of a walk of source scatterlist
+ * @walk: the scatter_walk
+ * @vaddr: the address returned by scatterwalk_next()
+ * @nbytes: the number of bytes processed this step, less than or equal to the
+ * number of bytes that scatterwalk_next() returned.
+ *
+ * Use this if the @vaddr was not written to, i.e. it is source data.
+ */
+static inline void scatterwalk_done_src(struct scatter_walk *walk,
+ const void *vaddr, unsigned int nbytes)
+{
+ scatterwalk_unmap((void *)vaddr);
+ scatterwalk_advance(walk, nbytes);
+}
+
+/**
+ * scatterwalk_done_dst() - Finish one step of a walk of destination scatterlist
+ * @walk: the scatter_walk
+ * @vaddr: the address returned by scatterwalk_next()
+ * @nbytes: the number of bytes processed this step, less than or equal to the
+ * number of bytes that scatterwalk_next() returned.
+ *
+ * Use this if the @vaddr may have been written to, i.e. it is destination data.
+ */
+static inline void scatterwalk_done_dst(struct scatter_walk *walk,
+ void *vaddr, unsigned int nbytes)
+{
+ scatterwalk_unmap(vaddr);
+ /*
+ * Explicitly check ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE instead of just
+ * relying on flush_dcache_page() being a no-op when not implemented,
+ * since otherwise the BUG_ON in sg_page() does not get optimized out.
+ */
+ if (ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE)
+ flush_dcache_page(scatterwalk_page(walk));
+ scatterwalk_advance(walk, nbytes);
+}
+
void scatterwalk_skip(struct scatter_walk *walk, unsigned int nbytes);
void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
size_t nbytes, int out);
--
2.47.1
next prev parent reply other threads:[~2024-12-30 0:16 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-30 0:13 [PATCH v2 00/29] crypto: scatterlist handling improvements Eric Biggers
2024-12-30 0:13 ` [PATCH v2 01/29] crypto: skcipher - document skcipher_walk_done() and rename some vars Eric Biggers
2024-12-30 0:13 ` [PATCH v2 02/29] crypto: skcipher - remove unnecessary page alignment of bounce buffer Eric Biggers
2024-12-30 0:13 ` [PATCH v2 03/29] crypto: skcipher - remove redundant clamping to page size Eric Biggers
2024-12-30 0:13 ` [PATCH v2 04/29] crypto: skcipher - remove redundant check for SKCIPHER_WALK_SLOW Eric Biggers
2024-12-30 0:13 ` [PATCH v2 05/29] crypto: skcipher - fold skcipher_walk_skcipher() into skcipher_walk_virt() Eric Biggers
2024-12-30 0:13 ` [PATCH v2 06/29] crypto: skcipher - clean up initialization of skcipher_walk::flags Eric Biggers
2024-12-30 0:13 ` [PATCH v2 07/29] crypto: skcipher - optimize initializing skcipher_walk fields Eric Biggers
2024-12-30 0:13 ` [PATCH v2 08/29] crypto: skcipher - call cond_resched() directly Eric Biggers
2024-12-30 0:13 ` [PATCH v2 09/29] crypto: omap - switch from scatter_walk to plain offset Eric Biggers
2024-12-30 0:13 ` [PATCH v2 10/29] crypto: powerpc/p10-aes-gcm - simplify handling of linear associated data Eric Biggers
2025-01-02 11:50 ` Christophe Leroy
2025-01-02 17:24 ` Eric Biggers
2024-12-30 0:14 ` [PATCH v2 11/29] crypto: scatterwalk - move to next sg entry just in time Eric Biggers
2024-12-30 0:14 ` [PATCH v2 12/29] crypto: scatterwalk - add new functions for skipping data Eric Biggers
2024-12-30 0:14 ` Eric Biggers [this message]
2024-12-30 0:14 ` [PATCH v2 14/29] crypto: scatterwalk - add new functions for copying data Eric Biggers
2024-12-30 0:14 ` [PATCH v2 15/29] crypto: scatterwalk - add scatterwalk_get_sglist() Eric Biggers
2024-12-30 0:14 ` [PATCH v2 16/29] crypto: skcipher - use scatterwalk_start_at_pos() Eric Biggers
2024-12-30 0:14 ` [PATCH v2 17/29] crypto: aegis - use the new scatterwalk functions Eric Biggers
2024-12-30 0:14 ` [PATCH v2 18/29] crypto: arm/ghash " Eric Biggers
2024-12-30 0:14 ` [PATCH v2 19/29] crypto: arm64 " Eric Biggers
2024-12-30 0:14 ` [PATCH v2 20/29] crypto: nx " Eric Biggers
2024-12-30 0:14 ` [PATCH v2 21/29] crypto: s390/aes-gcm " Eric Biggers
2025-01-08 15:06 ` Harald Freudenberger
2024-12-30 0:14 ` [PATCH v2 22/29] crypto: s5p-sss " Eric Biggers
2024-12-30 0:14 ` [PATCH v2 23/29] crypto: stm32 " Eric Biggers
2024-12-30 0:14 ` [PATCH v2 24/29] crypto: x86/aes-gcm " Eric Biggers
2024-12-30 0:14 ` [PATCH v2 25/29] crypto: x86/aegis " Eric Biggers
2024-12-30 0:14 ` [PATCH v2 26/29] net/tls: " Eric Biggers
2024-12-30 0:14 ` [PATCH v2 27/29] crypto: skcipher - " Eric Biggers
2024-12-30 0:14 ` [PATCH v2 28/29] crypto: scatterwalk - remove obsolete functions Eric Biggers
2024-12-30 0:14 ` [PATCH v2 29/29] crypto: scatterwalk - don't split at page boundaries when !HIGHMEM Eric Biggers
2024-12-30 1:31 ` [PATCH v2 00/29] crypto: scatterlist handling improvements Eric Biggers
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=20241230001418.74739-14-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
/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).