diff mbox series

[v2,2/3] crypto: scatterwalk - Add memcpy_sglist

Message ID 18a6df64615a10be64c3c902f8b1f36e472548d7.1741318360.git.herbert@gondor.apana.org.au
State New
Headers show
Series crypto: scatterwalk - scatterwalk_next and memcpy_sglist | expand

Commit Message

Herbert Xu March 7, 2025, 3:36 a.m. UTC
Add memcpy_sglist which copies one SG list to another.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 crypto/scatterwalk.c         | 27 +++++++++++++++++++++++++++
 include/crypto/scatterwalk.h |  3 +++
 2 files changed, 30 insertions(+)

Comments

Eric Biggers March 7, 2025, 9:37 p.m. UTC | #1
On Fri, Mar 07, 2025 at 11:36:19AM +0800, Herbert Xu wrote:
> Add memcpy_sglist which copies one SG list to another.
> 
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

There's no user of this yet, but presumably this is going to be used to replace
some of the bizarre code that is using the "null skcipher" to copy between two
scatterlists?  For example the code in crypto/seqiv.c.

- Eric
Herbert Xu March 8, 2025, 10:52 a.m. UTC | #2
On Fri, Mar 07, 2025 at 01:37:49PM -0800, Eric Biggers wrote:
>
> There's no user of this yet, but presumably this is going to be used to replace
> some of the bizarre code that is using the "null skcipher" to copy between two
> scatterlists?  For example the code in crypto/seqiv.c.

It was actually for zram:

https://lore.kernel.org/all/Z8kiRym1hS9fB2mE@gondor.apana.org.au/

But yes we could definitely replace the null skcipher with this.
Do you want to have a go at that?

Thanks,
diff mbox series

Patch

diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index 20a28c6d94da..8225801488d5 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -86,6 +86,33 @@  void memcpy_to_sglist(struct scatterlist *sg, unsigned int start,
 }
 EXPORT_SYMBOL_GPL(memcpy_to_sglist);
 
+void memcpy_sglist(struct scatterlist *dst, struct scatterlist *src,
+		   unsigned int nbytes)
+{
+	struct scatter_walk swalk;
+	struct scatter_walk dwalk;
+
+	if (unlikely(nbytes == 0)) /* in case sg == NULL */
+		return;
+
+	scatterwalk_start(&swalk, src);
+	scatterwalk_start(&dwalk, dst);
+
+	do {
+		unsigned int slen, dlen;
+		unsigned int len;
+
+		slen = scatterwalk_next(&swalk, nbytes);
+		dlen = scatterwalk_next(&dwalk, nbytes);
+		len = min(slen, dlen);
+		memcpy(dwalk.addr, swalk.addr, len);
+		scatterwalk_done_dst(&dwalk, len);
+		scatterwalk_done_src(&swalk, len);
+		nbytes -= len;
+	} while (nbytes);
+}
+EXPORT_SYMBOL_GPL(memcpy_sglist);
+
 struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2],
 				     struct scatterlist *src,
 				     unsigned int len)
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 791100054f7c..533e52dd7e0f 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -210,6 +210,9 @@  void memcpy_from_sglist(void *buf, struct scatterlist *sg,
 void memcpy_to_sglist(struct scatterlist *sg, unsigned int start,
 		      const void *buf, unsigned int nbytes);
 
+void memcpy_sglist(struct scatterlist *dst, struct scatterlist *src,
+		   unsigned int nbytes);
+
 /* In new code, please use memcpy_{from,to}_sglist() directly instead. */
 static inline void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
 					    unsigned int start,