* [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list)
@ 2023-01-16 23:07 David Howells
2023-01-16 23:09 ` [PATCH v6 15/34] af_alg: Pin pages rather than ref'ing if appropriate David Howells
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: David Howells @ 2023-01-16 23:07 UTC (permalink / raw)
To: Al Viro
Cc: James E.J. Bottomley, Paolo Abeni, John Hubbard,
Christoph Hellwig, Paulo Alcantara, linux-scsi, Steve French,
Stefan Metzmacher, Miklos Szeredi, Martin K. Petersen,
Logan Gunthorpe, Jeff Layton, Jakub Kicinski, netdev,
Rohith Surabattula, Eric Dumazet, Matthew Wilcox, Anna Schumaker,
Jens Axboe, Shyam Prasad N, Tom Talpey, linux-rdma,
Trond Myklebust, Christian Schoenebeck, linux-mm, linux-crypto,
linux-nfs, v9fs-developer, Latchesar Ionkov, linux-fsdevel,
Eric Van Hensbergen, Long Li, Jan Kara, linux-cachefs,
linux-block, Dominique Martinet, Namjae Jeon, David S. Miller,
linux-cifs, Steve French, Herbert Xu, dhowells, Christoph Hellwig,
Matthew Wilcox, Jens Axboe, Jan Kara, Jeff Layton,
Logan Gunthorpe, linux-fsdevel, linux-block, linux-kernel
Hi Al, Christoph,
Here are patches clean up some use of READ/WRITE and ITER_SOURCE/DEST,
patches to provide support for extracting pages from an iov_iter and a
patch to use the primary extraction function in the block layer bio code.
I've also added a bunch of other conversions and had a tentative stab at
the networking code.
The patches make the following changes:
(1) Deal with switching from using the iterator data_source to indicate
the I/O direction to deriving this from other information, eg.:
IOCB_WRITE, IOMAP_WRITE and the REQ_OP_* number. This allows
iov_iter_rw() to be removed eventually.
(2) Define FOLL_SOURCE_BUF and FOLL_DEST_BUF and pass these into
iov_iter_get_pages*() to indicate the I/O direction with regards to
how the buffer described by the iterator is to be used. This is
included in the gup_flags passed in with Logan's patches.
Calls to iov_iter_get_pages*2() are replaced with calls to
iov_iter_get_pages*() and the former is removed.
(3) Add a function, iov_iter_extract_pages() to replace
iov_iter_get_pages*() that gets refs, pins or just lists the pages as
appropriate to the iterator type and the I/O direction.
Add a function, iov_iter_extract_mode() that will indicate from the
iterator type and the I/O direction how the cleanup is to be
performed, returning FOLL_GET, FOLL_PIN or 0.
Add a function, folio_put_unpin(), and a wrapper, page_put_unpin(),
that take a page and the return from iov_iter_extract_mode() and do
the right thing to clean up the page.
(4) Make the bio struct carry a pair of flags to indicate the cleanup
mode. BIO_NO_PAGE_REF is replaced with BIO_PAGE_REFFED (equivalent to
FOLL_GET) and BIO_PAGE_PINNED (equivalent to BIO_PAGE_PINNED) is
added. These are forced to have the same value as the FOLL_* flags so
they can be passed to the previously mentioned cleanup function.
(5) Make the iter-to-bio code use iov_iter_extract_pages() to
appropriately retain the pages and clean them up later.
(6) Fix bio_flagged() so that it doesn't prevent a gcc optimisation.
(7) Add a function in netfslib, netfs_extract_user_iter(), to extract a
UBUF- or IOVEC-type iterator to a page list in a BVEC-type iterator,
with all the pages suitably ref'd or pinned.
(8) Add a function in netfslib, netfs_extract_iter_to_sg(), to extract a
UBUF-, IOVEC-, BVEC-, XARRAY- or KVEC-type iterator to a scatterlist.
The first two types appropriately ref or pin pages; the latter three
don't perform any retention, leaving that to the caller.
Note that I can make use of this in the SCSI and AF_ALG code and
possibly the networking code, so this might merit being moved to core
code.
(9) Make AF_ALG use iov_iter_extract_pages() and possibly go further and
make it use netfs_extract_iter_to_sg() instead.
(10) Make SCSI vhost use netfs_extract_iter_to_sg().
(11) Make fs/direct-io.c use iov_iter_extract_pages().
(13) Make splice-to-pipe use iov_iter_extract_pages(), but limit the usage
to a cleanup mode of FOLL_GET.
(13) Make the 9P, FUSE and NFS filesystems use iov_iter_extract_pages().
(14) Make the CIFS filesystem use iterators from the top all the way down
to the socket on the simple path. Make it use
netfs_extract_user_iter() to use an XARRAY-type iterator or to build a
BVEC-type iterator in the top layers from a UBUF- or IOVEC-type
iterator and attach the iterator to the operation descriptors.
netfs_extract_iter_to_sg() is used to build scatterlists for doing
transport crypto and a function, smb_extract_iter_to_rdma(), is
provided to build an RDMA SGE list directly from an iterator without
going via a page list and then a scatter list.
(15) A couple of work-in-progress patches to try and make sk_buff fragments
record the information needed to clean them up in the lowest two bits
of the page pointer in the fragment struct.
This leaves:
(*) Four calls to iov_iter_get_pages() in CEPH. That will be helped by
patches to pass an iterator down to the transport layer instead of
converting to a page list high up and passing that down, but the
transport layer could do with some massaging so that it doesn't covert
the iterator to a page list and then the pages individually back to
iterators to pass to the socket.
(*) One call to iov_iter_get_pages() each in the networking core, RDS and
TLS, all related to zero-copy. TLS seems to do zerocopy-read (or
maybe decrypt-offload) and should be doing FOLL_PIN, not FOLL_GET for
user-provided buffers.
Changes:
========
ver #6)
- Fix write() syscall and co. not setting IOCB_WRITE.
- Added iocb_is_read() and iocb_is_write() to check IOCB_WRITE.
- Use op_is_write() in bio_copy_user_iov().
- Drop the iterator direction checks from smbd_recv().
- Define FOLL_SOURCE_BUF and FOLL_DEST_BUF and pass them in as part of
gup_flags to iov_iter_get/extract_pages*().
- Replace iov_iter_get_pages*2() with iov_iter_get_pages*() and remove.
- Add back the function to indicate the cleanup mode.
- Drop the cleanup_mode return arg to iov_iter_extract_pages().
- Provide a helper to clean up a page.
- Renumbered FOLL_GET and FOLL_PIN and made BIO_PAGE_REFFED/PINNED have
the same numerical values, enforced with an assertion.
- Converted AF_ALG, SCSI vhost, generic DIO, FUSE, splice to pipe, 9P and
NFS.
- Added in the patches to make CIFS do top-to-bottom iterators and use
various of the added extraction functions.
- Added a pair of work-in-progess patches to make sk_buff fragments store
FOLL_GET and FOLL_PIN.
ver #5)
- Replace BIO_NO_PAGE_REF with BIO_PAGE_REFFED and split into own patch.
- Transcribe FOLL_GET/PIN into BIO_PAGE_REFFED/PINNED flags.
- Add patch to allow bio_flagged() to be combined by gcc.
ver #4)
- Drop the patch to move the FOLL_* flags to linux/mm_types.h as they're
no longer referenced by linux/uio.h.
- Add ITER_SOURCE/DEST cleanup patches.
- Make iov_iter/netfslib iter extraction patches use ITER_SOURCE/DEST.
- Allow additional gup_flags to be passed into iov_iter_extract_pages().
- Add struct bio patch.
ver #3)
- Switch to using EXPORT_SYMBOL_GPL to prevent indirect 3rd-party access
to get/pin_user_pages_fast()[1].
ver #2)
- Rolled the extraction cleanup mode query function into the extraction
function, returning the indication through the argument list.
- Fixed patch 4 (extract to scatterlist) to actually use the new
extraction API.
I've pushed the patches (excluding the two WIP networking patches) here
also:
https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=iov-extract
David
Link: https://lore.kernel.org/r/Y3zFzdWnWlEJ8X8/@infradead.org/ [1]
Link: https://lore.kernel.org/r/166697254399.61150.1256557652599252121.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/166722777223.2555743.162508599131141451.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/166732024173.3186319.18204305072070871546.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/166869687556.3723671.10061142538708346995.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/166920902005.1461876.2786264600108839814.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/166997419665.9475.15014699817597102032.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/167305160937.1521586.133299343565358971.stgit@warthog.procyon.org.uk/ # v4
Link: https://lore.kernel.org/r/167344725490.2425628.13771289553670112965.stgit@warthog.procyon.org.uk/ # v5
Previous versions of the CIFS patch sets can be found here:
Link: https://lore.kernel.org/r/164311902471.2806745.10187041199819525677.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/164928615045.457102.10607899252434268982.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/165211416682.3154751.17287804906832979514.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/165348876794.2106726.9240233279581920208.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/165364823513.3334034.11209090728654641458.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/166126392703.708021.14465850073772688008.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/166697254399.61150.1256557652599252121.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/166732024173.3186319.18204305072070871546.stgit@warthog.procyon.org.uk/ # rfc
---
David Howells (34):
vfs: Unconditionally set IOCB_WRITE in call_write_iter()
iov_iter: Use IOCB/IOMAP_WRITE/op_is_write rather than iterator direction
iov_iter: Pass I/O direction into iov_iter_get_pages*()
iov_iter: Remove iov_iter_get_pages2/pages_alloc2()
iov_iter: Change the direction macros into an enum
iov_iter: Use the direction in the iterator functions
iov_iter: Add a function to extract a page list from an iterator
mm: Provide a helper to drop a pin/ref on a page
bio: Rename BIO_NO_PAGE_REF to BIO_PAGE_REFFED and invert the meaning
mm, block: Make BIO_PAGE_REFFED/PINNED the same as FOLL_GET/PIN numerically
iov_iter, block: Make bio structs pin pages rather than ref'ing if appropriate
bio: Fix bio_flagged() so that gcc can better optimise it
netfs: Add a function to extract a UBUF or IOVEC into a BVEC iterator
netfs: Add a function to extract an iterator into a scatterlist
af_alg: Pin pages rather than ref'ing if appropriate
af_alg: [RFC] Use netfs_extract_iter_to_sg() to create scatterlists
scsi: [RFC] Use netfs_extract_iter_to_sg()
dio: Pin pages rather than ref'ing if appropriate
fuse: Pin pages rather than ref'ing if appropriate
vfs: Make splice use iov_iter_extract_pages()
9p: Pin pages rather than ref'ing if appropriate
nfs: Pin pages rather than ref'ing if appropriate
cifs: Implement splice_read to pass down ITER_BVEC not ITER_PIPE
cifs: Add a function to build an RDMA SGE list from an iterator
cifs: Add a function to Hash the contents of an iterator
cifs: Add some helper functions
cifs: Add a function to read into an iter from a socket
cifs: Change the I/O paths to use an iterator rather than a page list
cifs: Build the RDMA SGE list directly from an iterator
cifs: Remove unused code
cifs: Fix problem with encrypted RDMA data read
cifs: DIO to/from KVEC-type iterators should now work
net: [RFC][WIP] Mark each skb_frags as to how they should be cleaned up
net: [RFC][WIP] Make __zerocopy_sg_from_iter() correctly pin or leave pages unref'd
block/bio.c | 48 +-
block/blk-map.c | 26 +-
block/blk.h | 25 +
block/fops.c | 8 +-
crypto/af_alg.c | 57 +-
crypto/algif_hash.c | 20 +-
drivers/net/tun.c | 2 +-
drivers/vhost/scsi.c | 75 +-
fs/9p/vfs_addr.c | 2 +-
fs/affs/file.c | 4 +-
fs/ceph/addr.c | 2 +-
fs/ceph/file.c | 16 +-
fs/cifs/Kconfig | 1 +
fs/cifs/cifsencrypt.c | 172 +++-
fs/cifs/cifsfs.c | 12 +-
fs/cifs/cifsfs.h | 6 +
fs/cifs/cifsglob.h | 66 +-
fs/cifs/cifsproto.h | 11 +-
fs/cifs/cifssmb.c | 13 +-
fs/cifs/connect.c | 16 +
fs/cifs/file.c | 1851 +++++++++++++++++--------------------
fs/cifs/fscache.c | 22 +-
fs/cifs/fscache.h | 10 +-
fs/cifs/misc.c | 132 +--
fs/cifs/smb2ops.c | 374 ++++----
fs/cifs/smb2pdu.c | 45 +-
fs/cifs/smbdirect.c | 511 ++++++----
fs/cifs/smbdirect.h | 4 +-
fs/cifs/transport.c | 57 +-
fs/dax.c | 6 +-
fs/direct-io.c | 77 +-
fs/exfat/inode.c | 6 +-
fs/ext2/inode.c | 2 +-
fs/f2fs/file.c | 10 +-
fs/fat/inode.c | 4 +-
fs/fuse/dax.c | 2 +-
fs/fuse/dev.c | 24 +-
fs/fuse/file.c | 34 +-
fs/fuse/fuse_i.h | 1 +
fs/hfs/inode.c | 2 +-
fs/hfsplus/inode.c | 2 +-
fs/iomap/direct-io.c | 6 +-
fs/jfs/inode.c | 2 +-
fs/netfs/Makefile | 1 +
fs/netfs/iterator.c | 371 ++++++++
fs/nfs/direct.c | 32 +-
fs/nilfs2/inode.c | 2 +-
fs/ntfs3/inode.c | 2 +-
fs/ocfs2/aops.c | 2 +-
fs/orangefs/inode.c | 2 +-
fs/reiserfs/inode.c | 2 +-
fs/splice.c | 10 +-
fs/udf/inode.c | 2 +-
include/crypto/if_alg.h | 7 +-
include/linux/bio.h | 23 +-
include/linux/blk_types.h | 3 +-
include/linux/fs.h | 11 +
include/linux/mm.h | 32 +-
include/linux/netfs.h | 6 +
include/linux/skbuff.h | 124 ++-
include/linux/uio.h | 83 +-
io_uring/net.c | 2 +-
lib/iov_iter.c | 428 ++++++++-
mm/gup.c | 47 +
mm/vmalloc.c | 1 +
net/9p/trans_common.c | 6 +-
net/9p/trans_common.h | 3 +-
net/9p/trans_virtio.c | 91 +-
net/bpf/test_run.c | 2 +-
net/core/datagram.c | 23 +-
net/core/gro.c | 2 +-
net/core/skbuff.c | 16 +-
net/core/skmsg.c | 4 +-
net/ipv4/ip_output.c | 2 +-
net/ipv4/tcp.c | 4 +-
net/ipv6/esp6.c | 5 +-
net/ipv6/ip6_output.c | 2 +-
net/packet/af_packet.c | 2 +-
net/rds/message.c | 4 +-
net/tls/tls_sw.c | 5 +-
net/xfrm/xfrm_ipcomp.c | 2 +-
81 files changed, 3006 insertions(+), 2126 deletions(-)
create mode 100644 fs/netfs/iterator.c
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v6 15/34] af_alg: Pin pages rather than ref'ing if appropriate
2023-01-16 23:07 [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list) David Howells
@ 2023-01-16 23:09 ` David Howells
2023-01-16 23:09 ` [PATCH v6 16/34] af_alg: [RFC] Use netfs_extract_iter_to_sg() to create scatterlists David Howells
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: David Howells @ 2023-01-16 23:09 UTC (permalink / raw)
To: Al Viro
Cc: Herbert Xu, linux-crypto, dhowells, Christoph Hellwig,
Matthew Wilcox, Jens Axboe, Jan Kara, Jeff Layton,
Logan Gunthorpe, linux-fsdevel, linux-block, linux-kernel
Convert AF_ALG to use iov_iter_extract_pages() instead of
iov_iter_get_pages(). This will pin pages or leave them unaltered rather
than getting a ref on them as appropriate to the iterator.
The pages need to be pinned for DIO-read rather than having refs taken on
them to prevent VM copy-on-write from malfunctioning during a concurrent
fork() (the result of the I/O would otherwise end up only visible to the
child process and not the parent).
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Herbert Xu <herbert@gondor.apana.org.au>
cc: linux-crypto@vger.kernel.org
---
crypto/af_alg.c | 9 ++++++---
include/crypto/if_alg.h | 1 +
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 7a68db157fae..c99e09fce71f 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -534,15 +534,18 @@ static const struct net_proto_family alg_family = {
int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len,
unsigned int gup_flags)
{
+ struct page **pages = sgl->pages;
size_t off;
ssize_t n;
int npages, i;
- n = iov_iter_get_pages(iter, sgl->pages, len, ALG_MAX_PAGES, &off,
- gup_flags);
+ n = iov_iter_extract_pages(iter, &pages, len, ALG_MAX_PAGES,
+ gup_flags, &off);
if (n < 0)
return n;
+ sgl->cleanup_mode = iov_iter_extract_mode(iter, gup_flags);
+
npages = DIV_ROUND_UP(off + n, PAGE_SIZE);
if (WARN_ON(npages == 0))
return -EINVAL;
@@ -576,7 +579,7 @@ void af_alg_free_sg(struct af_alg_sgl *sgl)
int i;
for (i = 0; i < sgl->npages; i++)
- put_page(sgl->pages[i]);
+ page_put_unpin(sgl->pages[i], sgl->cleanup_mode);
}
EXPORT_SYMBOL_GPL(af_alg_free_sg);
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 12058ab6cad9..95b3b7517d3f 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -61,6 +61,7 @@ struct af_alg_sgl {
struct scatterlist sg[ALG_MAX_PAGES + 1];
struct page *pages[ALG_MAX_PAGES];
unsigned int npages;
+ unsigned int cleanup_mode;
};
/* TX SGL entry */
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v6 16/34] af_alg: [RFC] Use netfs_extract_iter_to_sg() to create scatterlists
2023-01-16 23:07 [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list) David Howells
2023-01-16 23:09 ` [PATCH v6 15/34] af_alg: Pin pages rather than ref'ing if appropriate David Howells
@ 2023-01-16 23:09 ` David Howells
2023-01-16 23:11 ` [PATCH v6 25/34] cifs: Add a function to Hash the contents of an iterator David Howells
2023-01-17 7:46 ` [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list) Christoph Hellwig
3 siblings, 0 replies; 5+ messages in thread
From: David Howells @ 2023-01-16 23:09 UTC (permalink / raw)
To: Al Viro
Cc: Herbert Xu, linux-crypto, dhowells, Christoph Hellwig,
Matthew Wilcox, Jens Axboe, Jan Kara, Jeff Layton,
Logan Gunthorpe, linux-fsdevel, linux-block, linux-kernel
Use netfs_extract_iter_to_sg() to decant the destination iterator into a
scatterlist in af_alg_get_rsgl(). af_alg_make_sg() can then be removed.
Note that if this fits, netfs_extract_iter_to_sg() should move to core
code.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Herbert Xu <herbert@gondor.apana.org.au>
cc: linux-crypto@vger.kernel.org
---
crypto/af_alg.c | 63 +++++++++++++----------------------------------
crypto/algif_hash.c | 21 +++++++++++-----
include/crypto/if_alg.h | 7 +----
3 files changed, 35 insertions(+), 56 deletions(-)
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index c99e09fce71f..c5fbe39366ff 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -22,6 +22,7 @@
#include <linux/sched/signal.h>
#include <linux/security.h>
#include <linux/string.h>
+#include <linux/netfs.h>
#include <keys/user-type.h>
#include <keys/trusted-type.h>
#include <keys/encrypted-type.h>
@@ -531,55 +532,22 @@ static const struct net_proto_family alg_family = {
.owner = THIS_MODULE,
};
-int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len,
- unsigned int gup_flags)
-{
- struct page **pages = sgl->pages;
- size_t off;
- ssize_t n;
- int npages, i;
-
- n = iov_iter_extract_pages(iter, &pages, len, ALG_MAX_PAGES,
- gup_flags, &off);
- if (n < 0)
- return n;
-
- sgl->cleanup_mode = iov_iter_extract_mode(iter, gup_flags);
-
- npages = DIV_ROUND_UP(off + n, PAGE_SIZE);
- if (WARN_ON(npages == 0))
- return -EINVAL;
- /* Add one extra for linking */
- sg_init_table(sgl->sg, npages + 1);
-
- for (i = 0, len = n; i < npages; i++) {
- int plen = min_t(int, len, PAGE_SIZE - off);
-
- sg_set_page(sgl->sg + i, sgl->pages[i], plen, off);
-
- off = 0;
- len -= plen;
- }
- sg_mark_end(sgl->sg + npages - 1);
- sgl->npages = npages;
-
- return n;
-}
-EXPORT_SYMBOL_GPL(af_alg_make_sg);
-
static void af_alg_link_sg(struct af_alg_sgl *sgl_prev,
struct af_alg_sgl *sgl_new)
{
- sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1);
- sg_chain(sgl_prev->sg, sgl_prev->npages + 1, sgl_new->sg);
+ sg_unmark_end(sgl_prev->sgt.sgl + sgl_prev->sgt.nents - 1);
+ sg_chain(sgl_prev->sgt.sgl, sgl_prev->sgt.nents + 1, sgl_new->sgt.sgl);
}
void af_alg_free_sg(struct af_alg_sgl *sgl)
{
int i;
- for (i = 0; i < sgl->npages; i++)
- page_put_unpin(sgl->pages[i], sgl->cleanup_mode);
+ if (!(sgl->cleanup_mode & (FOLL_PIN | FOLL_GET)))
+ return;
+
+ for (i = 0; i < sgl->sgt.nents; i++)
+ page_put_unpin(sg_page(&sgl->sgt.sgl[i]), sgl->cleanup_mode);
}
EXPORT_SYMBOL_GPL(af_alg_free_sg);
@@ -1293,8 +1261,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
while (maxsize > len && msg_data_left(msg)) {
struct af_alg_rsgl *rsgl;
+ ssize_t err;
size_t seglen;
- int err;
/* limit the amount of readable buffers */
if (!af_alg_readable(sk))
@@ -1311,17 +1279,22 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
return -ENOMEM;
}
- rsgl->sgl.npages = 0;
+ rsgl->sgl.sgt.sgl = rsgl->sgl.sgl;
+ rsgl->sgl.sgt.nents = 0;
+ rsgl->sgl.sgt.orig_nents = 0;
list_add_tail(&rsgl->list, &areq->rsgl_list);
- /* make one iovec available as scatterlist */
- err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen,
- FOLL_DEST_BUF);
+ err = netfs_extract_iter_to_sg(&msg->msg_iter, seglen,
+ &rsgl->sgl.sgt, ALG_MAX_PAGES,
+ FOLL_DEST_BUF);
if (err < 0) {
rsgl->sg_num_bytes = 0;
return err;
}
+ rsgl->sgl.cleanup_mode = iov_iter_extract_mode(&msg->msg_iter,
+ FOLL_DEST_BUF);
+
/* chain the new scatterlist with previous one */
if (areq->last_rsgl)
af_alg_link_sg(&areq->last_rsgl->sgl, &rsgl->sgl);
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index fe3d2258145f..5aef6818a9ff 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/net.h>
+#include <linux/netfs.h>
#include <net/sock.h>
struct hash_ctx {
@@ -91,14 +92,22 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
if (len > limit)
len = limit;
- len = af_alg_make_sg(&ctx->sgl, &msg->msg_iter, len,
- FOLL_SOURCE_BUF);
+ ctx->sgl.sgt.sgl = ctx->sgl.sgl;
+ ctx->sgl.sgt.nents = 0;
+ ctx->sgl.sgt.orig_nents = 0;
+
+ len = netfs_extract_iter_to_sg(&msg->msg_iter, len,
+ &ctx->sgl.sgt, ALG_MAX_PAGES,
+ FOLL_SOURCE_BUF);
if (len < 0) {
err = copied ? 0 : len;
goto unlock;
}
- ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL, len);
+ ctx->sgl.cleanup_mode = iov_iter_extract_mode(&msg->msg_iter,
+ FOLL_SOURCE_BUF);
+
+ ahash_request_set_crypt(&ctx->req, ctx->sgl.sgt.sgl, NULL, len);
err = crypto_wait_req(crypto_ahash_update(&ctx->req),
&ctx->wait);
@@ -142,8 +151,8 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
flags |= MSG_MORE;
lock_sock(sk);
- sg_init_table(ctx->sgl.sg, 1);
- sg_set_page(ctx->sgl.sg, page, size, offset);
+ sg_init_table(ctx->sgl.sgl, 1);
+ sg_set_page(ctx->sgl.sgl, page, size, offset);
if (!(flags & MSG_MORE)) {
err = hash_alloc_result(sk, ctx);
@@ -152,7 +161,7 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
} else if (!ctx->more)
hash_free_result(sk, ctx);
- ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size);
+ ahash_request_set_crypt(&ctx->req, ctx->sgl.sgl, ctx->result, size);
if (!(flags & MSG_MORE)) {
if (ctx->more)
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 95b3b7517d3f..424a2071705d 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -58,9 +58,8 @@ struct af_alg_type {
};
struct af_alg_sgl {
- struct scatterlist sg[ALG_MAX_PAGES + 1];
- struct page *pages[ALG_MAX_PAGES];
- unsigned int npages;
+ struct sg_table sgt;
+ struct scatterlist sgl[ALG_MAX_PAGES + 1];
unsigned int cleanup_mode;
};
@@ -166,8 +165,6 @@ int af_alg_release(struct socket *sock);
void af_alg_release_parent(struct sock *sk);
int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern);
-int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len,
- unsigned int gup_flags);
void af_alg_free_sg(struct af_alg_sgl *sgl);
static inline struct alg_sock *alg_sk(struct sock *sk)
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v6 25/34] cifs: Add a function to Hash the contents of an iterator
2023-01-16 23:07 [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list) David Howells
2023-01-16 23:09 ` [PATCH v6 15/34] af_alg: Pin pages rather than ref'ing if appropriate David Howells
2023-01-16 23:09 ` [PATCH v6 16/34] af_alg: [RFC] Use netfs_extract_iter_to_sg() to create scatterlists David Howells
@ 2023-01-16 23:11 ` David Howells
2023-01-17 7:46 ` [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list) Christoph Hellwig
3 siblings, 0 replies; 5+ messages in thread
From: David Howells @ 2023-01-16 23:11 UTC (permalink / raw)
To: Al Viro
Cc: Steve French, Shyam Prasad N, Rohith Surabattula, Jeff Layton,
linux-cifs, linux-fsdevel, linux-crypto, dhowells,
Christoph Hellwig, Matthew Wilcox, Jens Axboe, Jan Kara,
Jeff Layton, Logan Gunthorpe, linux-fsdevel, linux-block,
linux-kernel
Add a function to push the contents of a BVEC-, KVEC- or XARRAY-type
iterator into a symmetric hash algorithm.
UBUF- and IOBUF-type iterators are not supported on the assumption that
either we're doing buffered I/O, in which case we won't see them, or we're
doing direct I/O, in which case the iterator will have been extracted into
a BVEC-type iterator higher up.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Shyam Prasad N <nspmangalore@gmail.com>
cc: Rohith Surabattula <rohiths.msft@gmail.com>
cc: Jeff Layton <jlayton@kernel.org>
cc: linux-cifs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
cc: linux-crypto@vger.kernel.org
Link: https://lore.kernel.org/r/166697257423.61150.12070648579830206483.stgit@warthog.procyon.org.uk/ # rfc
Link: https://lore.kernel.org/r/166732029577.3186319.17162612653237909961.stgit@warthog.procyon.org.uk/ # rfc
---
fs/cifs/cifsencrypt.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 144 insertions(+)
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 5db73c0f792a..e13f26371540 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -24,6 +24,150 @@
#include "../smbfs_common/arc4.h"
#include <crypto/aead.h>
+/*
+ * Hash data from a BVEC-type iterator.
+ */
+static int cifs_shash_bvec(const struct iov_iter *iter, ssize_t maxsize,
+ struct shash_desc *shash)
+{
+ const struct bio_vec *bv = iter->bvec;
+ unsigned long start = iter->iov_offset;
+ unsigned int i;
+ void *p;
+ int ret;
+
+ for (i = 0; i < iter->nr_segs; i++) {
+ size_t off, len;
+
+ len = bv[i].bv_len;
+ if (start >= len) {
+ start -= len;
+ continue;
+ }
+
+ len = min_t(size_t, maxsize, len - start);
+ off = bv[i].bv_offset + start;
+
+ p = kmap_local_page(bv[i].bv_page);
+ ret = crypto_shash_update(shash, p + off, len);
+ kunmap_local(p);
+ if (ret < 0)
+ return ret;
+
+ maxsize -= len;
+ if (maxsize <= 0)
+ break;
+ start = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * Hash data from a KVEC-type iterator.
+ */
+static int cifs_shash_kvec(const struct iov_iter *iter, ssize_t maxsize,
+ struct shash_desc *shash)
+{
+ const struct kvec *kv = iter->kvec;
+ unsigned long start = iter->iov_offset;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < iter->nr_segs; i++) {
+ size_t len;
+
+ len = kv[i].iov_len;
+ if (start >= len) {
+ start -= len;
+ continue;
+ }
+
+ len = min_t(size_t, maxsize, len - start);
+ ret = crypto_shash_update(shash, kv[i].iov_base + start, len);
+ if (ret < 0)
+ return ret;
+ maxsize -= len;
+
+ if (maxsize <= 0)
+ break;
+ start = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * Hash data from an XARRAY-type iterator.
+ */
+static ssize_t cifs_shash_xarray(const struct iov_iter *iter, ssize_t maxsize,
+ struct shash_desc *shash)
+{
+ struct folio *folios[16], *folio;
+ unsigned int nr, i, j, npages;
+ loff_t start = iter->xarray_start + iter->iov_offset;
+ pgoff_t last, index = start / PAGE_SIZE;
+ ssize_t ret = 0;
+ size_t len, offset, foffset;
+ void *p;
+
+ if (maxsize == 0)
+ return 0;
+
+ last = (start + maxsize - 1) / PAGE_SIZE;
+ do {
+ nr = xa_extract(iter->xarray, (void **)folios, index, last,
+ ARRAY_SIZE(folios), XA_PRESENT);
+ if (nr == 0)
+ return -EIO;
+
+ for (i = 0; i < nr; i++) {
+ folio = folios[i];
+ npages = folio_nr_pages(folio);
+ foffset = start - folio_pos(folio);
+ offset = foffset % PAGE_SIZE;
+ for (j = foffset / PAGE_SIZE; j < npages; j++) {
+ len = min_t(size_t, maxsize, PAGE_SIZE - offset);
+ p = kmap_local_page(folio_page(folio, j));
+ ret = crypto_shash_update(shash, p, len);
+ kunmap_local(p);
+ if (ret < 0)
+ return ret;
+ maxsize -= len;
+ if (maxsize <= 0)
+ return 0;
+ start += len;
+ offset = 0;
+ index++;
+ }
+ }
+ } while (nr == ARRAY_SIZE(folios));
+ return 0;
+}
+
+/*
+ * Pass the data from an iterator into a hash.
+ */
+static int cifs_shash_iter(const struct iov_iter *iter, size_t maxsize,
+ struct shash_desc *shash)
+{
+ if (maxsize == 0)
+ return 0;
+
+ switch (iov_iter_type(iter)) {
+ case ITER_BVEC:
+ return cifs_shash_bvec(iter, maxsize, shash);
+ case ITER_KVEC:
+ return cifs_shash_kvec(iter, maxsize, shash);
+ case ITER_XARRAY:
+ return cifs_shash_xarray(iter, maxsize, shash);
+ default:
+ pr_err("cifs_shash_iter(%u) unsupported\n", iov_iter_type(iter));
+ WARN_ON_ONCE(1);
+ return -EIO;
+ }
+}
+
int __cifs_calc_signature(struct smb_rqst *rqst,
struct TCP_Server_Info *server, char *signature,
struct shash_desc *shash)
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list)
2023-01-16 23:07 [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list) David Howells
` (2 preceding siblings ...)
2023-01-16 23:11 ` [PATCH v6 25/34] cifs: Add a function to Hash the contents of an iterator David Howells
@ 2023-01-17 7:46 ` Christoph Hellwig
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2023-01-17 7:46 UTC (permalink / raw)
To: David Howells
Cc: Al Viro, James E.J. Bottomley, Paolo Abeni, John Hubbard,
Christoph Hellwig, Paulo Alcantara, linux-scsi, Steve French,
Stefan Metzmacher, Miklos Szeredi, Martin K. Petersen,
Logan Gunthorpe, Jeff Layton, Jakub Kicinski, netdev,
Rohith Surabattula, Eric Dumazet, Matthew Wilcox, Anna Schumaker,
Jens Axboe, Shyam Prasad N, Tom Talpey, linux-rdma,
Trond Myklebust, Christian Schoenebeck, linux-mm, linux-crypto,
linux-nfs, v9fs-developer, Latchesar Ionkov, linux-fsdevel,
Eric Van Hensbergen, Long Li, Jan Kara, linux-cachefs,
linux-block, Dominique Martinet, Namjae Jeon, David S. Miller,
linux-cifs, Steve French, Herbert Xu, Christoph Hellwig,
linux-kernel
First off the liver comment: can we cut down things for a first
round? Maybe just convert everything using the bio based helpers
and then chunk it up? Reviewing 34 patches across a dozen subsystems
isn't going to be easy and it will be hard to come up with a final
positive conclusion.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-01-17 7:47 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-01-16 23:07 [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list) David Howells
2023-01-16 23:09 ` [PATCH v6 15/34] af_alg: Pin pages rather than ref'ing if appropriate David Howells
2023-01-16 23:09 ` [PATCH v6 16/34] af_alg: [RFC] Use netfs_extract_iter_to_sg() to create scatterlists David Howells
2023-01-16 23:11 ` [PATCH v6 25/34] cifs: Add a function to Hash the contents of an iterator David Howells
2023-01-17 7:46 ` [PATCH v6 00/34] iov_iter: Improve page extraction (ref, pin or just list) Christoph Hellwig
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).