From: J Louis Kaplan <Louis.Kaplan@arm.com>
To: cel@kernel.org, dai.ngo@oracle.com, jlayton@kernel.org,
neil@brown.name, okorniev@redhat.com, tom@talpey.com
Cc: linux-nfs@vger.kernel.org, linux-rdma@vger.kernel.org,
anna@kernel.org, jgg@ziepe.ca, leon@kernel.org,
trondmy@kernel.org, J Louis Kaplan <Louis.Kaplan@arm.com>
Subject: [RFC PATCH 1/6] sunrpc: Add helpers to build bvecs from contiguous pages
Date: Tue, 6 Oct 2026 10:00:23 +0100 [thread overview]
Message-ID: <20261006090028.3412544-2-Louis.Kaplan@arm.com> (raw)
In-Reply-To: <20261006090028.3412544-1-Louis.Kaplan@arm.com>
Add helpers to describe contiguous runs with multipage bvecs. These
functions have no callers. They are used in later commits.
Accept a caller-supplied maximum bvec length so transport callers
can enforce direct memory access (DMA) mapping and device segment
length limits. Also support counting entries without populating
an array so callers can size their allocations using the same
coalescing rules.
Coalescing requires contiguous physical memory and page descriptors,
and is disabled under KMSAN. Xen constraint handling remains WIP.
Signed-off-by: J Louis Kaplan <Louis.Kaplan@arm.com>
Assisted-by: LLM
---
include/linux/sunrpc/svc.h | 90 ++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index dfadea50e0c6d..e651c2312a912 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -11,6 +11,7 @@
#ifndef SUNRPC_SVC_H
#define SUNRPC_SVC_H
+#include <linux/bvec.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/sunrpc/types.h>
@@ -376,6 +377,95 @@ static inline void svc_thread_init_status(struct svc_rqst *rqstp, int err)
kthread_exit(1);
}
+/**
+ * svc_pages_to_bvec - build one bvec from physically contiguous pages
+ * @bv: bio_vec to initialize, or NULL to only measure the next extent
+ * @pages: first page-array slot in the range
+ * @nr_pages: number of page-array slots available from @pages
+ * @offset: byte offset in @pages[0]
+ * @len: maximum byte count to describe
+ * @max_bvec_len: maximum byte count in one bvec
+ *
+ * Return: The number of bytes described by @bv. The scan stops at a missing
+ * or physically non-contiguous page.
+ */
+static inline unsigned int
+svc_pages_to_bvec(struct bio_vec *bv, struct page *const *pages,
+ unsigned int nr_pages, unsigned int offset,
+ unsigned int len, unsigned int max_bvec_len)
+{
+ unsigned long first_pfn;
+ unsigned int bytes, used = 1;
+
+ if (WARN_ON_ONCE(!nr_pages || offset >= PAGE_SIZE || !len ||
+ !max_bvec_len || !pages[0]))
+ return 0;
+ first_pfn = page_to_pfn(pages[0]);
+
+ bytes = min3(len, max_bvec_len,
+ (unsigned int)(PAGE_SIZE - offset));
+ while (bytes < len && bytes < max_bvec_len && used < nr_pages) {
+ // TODO: handle Xen merge constraints, see `bvec_try_merge_page`
+ // for reference, or unify helper functionality
+ if (IS_ENABLED(CONFIG_KMSAN))
+ break;
+
+ if (!pages[used] ||
+ page_to_pfn(pages[used]) != first_pfn + used ||
+ pages[0] + used != pages[used])
+ break;
+ used++;
+ bytes = min3(len, max_bvec_len,
+ (used << PAGE_SHIFT) - offset);
+ }
+
+ if (bv)
+ bvec_set_page(bv, pages[0], bytes, offset);
+ return bytes;
+}
+
+/**
+ * svc_pages_to_bvecs - build bvecs for a service page-array range
+ * @bvecs: bio_vec array to populate, or NULL to only count the entries
+ * @pages: first page-array slot in the range
+ * @nr_pages: number of page-array slots available from @pages
+ * @offset: byte offset in @pages[0]
+ * @len: byte count to describe
+ * @max_bvec_len: maximum byte count in one bvec
+ *
+ * If @bvecs is not NULL, it must have room for the count returned by a
+ * preceding count-only call.
+ *
+ * Return: The number of populated or required bvecs, or zero if the range
+ * cannot be described from the supplied page-array slots.
+ */
+static inline unsigned int
+svc_pages_to_bvecs(struct bio_vec *bvecs, struct page *const *pages,
+ unsigned int nr_pages, unsigned int offset,
+ unsigned int len, unsigned int max_bvec_len)
+{
+ unsigned int remaining = len;
+ unsigned int nents = 0;
+
+ while (remaining && nr_pages) {
+ struct bio_vec *bv = bvecs ? &bvecs[nents] : NULL;
+ unsigned int advanced;
+ unsigned int bytes;
+
+ bytes = svc_pages_to_bvec(bv, pages, nr_pages, offset,
+ remaining, max_bvec_len);
+ if (!bytes)
+ break;
+ advanced = (offset + bytes) >> PAGE_SHIFT;
+ offset = offset_in_page(offset + bytes);
+ pages += advanced;
+ nr_pages -= advanced;
+ remaining -= bytes;
+ nents++;
+ }
+ return remaining ? 0 : nents;
+}
+
struct svc_deferred_req {
u32 prot; /* protocol (UDP or TCP) */
bool secure; /* RQ_SECURE of the original request */
--
2.43.0
next prev parent reply other threads:[~2026-10-06 9:01 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-06 9:00 [RFC PATCH 0/6] Improve NFS server direct throughput with passthrough enabled J Louis Kaplan
2026-10-06 9:00 ` J Louis Kaplan [this message]
2026-10-06 13:49 ` [RFC PATCH 1/6] sunrpc: Add helpers to build bvecs from contiguous pages Chuck Lever
2026-10-08 22:44 ` J Louis Kaplan
2026-10-06 9:00 ` [RFC PATCH 2/6] nfsd: Coalesce contiguous pages for direct reads J Louis Kaplan
2026-10-06 9:00 ` [RFC PATCH 3/6] svcrdma: Coalesce contiguous pages when mapping replies J Louis Kaplan
2026-10-06 13:55 ` Chuck Lever
2026-10-08 22:54 ` J Louis Kaplan
2026-10-06 9:00 ` [RFC PATCH 4/6] svcrdma: Coalesce contiguous pages in RDMA Write chunks J Louis Kaplan
2026-10-06 9:00 ` [RFC PATCH 5/6] svcrdma: Coalesce contiguous pages in RDMA Read chunks J Louis Kaplan
2026-10-06 9:00 ` [RFC PATCH 6/6] sunrpc: Allocate svc request pages from large folios J Louis Kaplan
2026-10-06 14:00 ` Chuck Lever
2026-10-08 22:58 ` J Louis Kaplan
2026-10-09 15:28 ` Chuck Lever
2026-10-06 13:47 ` [RFC PATCH 0/6] Improve NFS server direct throughput with passthrough enabled Chuck Lever
2026-10-08 22:50 ` J Louis Kaplan
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=20261006090028.3412544-2-Louis.Kaplan@arm.com \
--to=louis.kaplan@arm.com \
--cc=anna@kernel.org \
--cc=cel@kernel.org \
--cc=dai.ngo@oracle.com \
--cc=jgg@ziepe.ca \
--cc=jlayton@kernel.org \
--cc=leon@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=tom@talpey.com \
--cc=trondmy@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