All of lore.kernel.org
 help / color / mirror / Atom feed
From: trondmy@kernel.org
To: Anna Schumaker <Anna.Schumaker@netapp.com>
Cc: linux-nfs@vger.kernel.org
Subject: [PATCH v2 03/18] NFS: Support folios in nfs_generic_pgio()
Date: Thu, 19 Jan 2023 16:33:36 -0500	[thread overview]
Message-ID: <20230119213351.443388-4-trondmy@kernel.org> (raw)
In-Reply-To: <20230119213351.443388-3-trondmy@kernel.org>

From: Trond Myklebust <trond.myklebust@hammerspace.com>

Add support for multi-page folios in the generic NFS i/o engine.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 fs/nfs/internal.h |  7 +++--
 fs/nfs/pagelist.c | 68 +++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index ae7d4a8c728c..6197b165c8c8 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -807,11 +807,10 @@ unsigned char nfs_umode_to_dtype(umode_t mode)
  * Determine the number of pages in an array of length 'len' and
  * with a base offset of 'base'
  */
-static inline
-unsigned int nfs_page_array_len(unsigned int base, size_t len)
+static inline unsigned int nfs_page_array_len(unsigned int base, size_t len)
 {
-	return ((unsigned long)len + (unsigned long)base +
-		PAGE_SIZE - 1) >> PAGE_SHIFT;
+	return ((unsigned long)len + (unsigned long)base + PAGE_SIZE - 1) >>
+	       PAGE_SHIFT;
 }
 
 /*
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 315e58d73718..174462722266 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -31,6 +31,42 @@
 static struct kmem_cache *nfs_page_cachep;
 static const struct rpc_call_ops nfs_pgio_common_ops;
 
+struct nfs_page_iter_page {
+	const struct nfs_page *req;
+	size_t count;
+};
+
+static void nfs_page_iter_page_init(struct nfs_page_iter_page *i,
+				    const struct nfs_page *req)
+{
+	i->req = req;
+	i->count = 0;
+}
+
+static void nfs_page_iter_page_advance(struct nfs_page_iter_page *i, size_t sz)
+{
+	const struct nfs_page *req = i->req;
+	size_t tmp = i->count + sz;
+
+	i->count = (tmp < req->wb_bytes) ? tmp : req->wb_bytes;
+}
+
+static struct page *nfs_page_iter_page_get(struct nfs_page_iter_page *i)
+{
+	const struct nfs_page *req = i->req;
+	struct page *page;
+
+	if (i->count != req->wb_bytes) {
+		size_t base = i->count + req->wb_pgbase;
+		size_t len = PAGE_SIZE - offset_in_page(base);
+
+		page = nfs_page_to_page(req, base);
+		nfs_page_iter_page_advance(i, len);
+		return page;
+	}
+	return NULL;
+}
+
 static struct nfs_pgio_mirror *
 nfs_pgio_get_mirror(struct nfs_pageio_descriptor *desc, u32 idx)
 {
@@ -693,13 +729,14 @@ EXPORT_SYMBOL_GPL(nfs_pgio_header_free);
 /**
  * nfs_pgio_rpcsetup - Set up arguments for a pageio call
  * @hdr: The pageio hdr
+ * @pgbase: base
  * @count: Number of bytes to read
  * @how: How to commit data (writes only)
  * @cinfo: Commit information for the call (writes only)
  */
-static void nfs_pgio_rpcsetup(struct nfs_pgio_header *hdr,
-			      unsigned int count,
-			      int how, struct nfs_commit_info *cinfo)
+static void nfs_pgio_rpcsetup(struct nfs_pgio_header *hdr, unsigned int pgbase,
+			      unsigned int count, int how,
+			      struct nfs_commit_info *cinfo)
 {
 	struct nfs_page *req = hdr->req;
 
@@ -710,7 +747,7 @@ static void nfs_pgio_rpcsetup(struct nfs_pgio_header *hdr,
 	hdr->args.offset = req_offset(req);
 	/* pnfs_set_layoutcommit needs this */
 	hdr->mds_offset = hdr->args.offset;
-	hdr->args.pgbase = req->wb_pgbase;
+	hdr->args.pgbase = pgbase;
 	hdr->args.pages  = hdr->page_array.pagevec;
 	hdr->args.count  = count;
 	hdr->args.context = get_nfs_open_context(nfs_req_openctx(req));
@@ -896,9 +933,10 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
 	struct nfs_commit_info cinfo;
 	struct nfs_page_array *pg_array = &hdr->page_array;
 	unsigned int pagecount, pageused;
+	unsigned int pg_base = offset_in_page(mirror->pg_base);
 	gfp_t gfp_flags = nfs_io_gfp_mask();
 
-	pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count);
+	pagecount = nfs_page_array_len(pg_base, mirror->pg_count);
 	pg_array->npages = pagecount;
 
 	if (pagecount <= ARRAY_SIZE(pg_array->page_array))
@@ -918,19 +956,26 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
 	last_page = NULL;
 	pageused = 0;
 	while (!list_empty(head)) {
+		struct nfs_page_iter_page i;
+		struct page *page;
+
 		req = nfs_list_entry(head->next);
 		nfs_list_move_request(req, &hdr->pages);
 
 		if (req->wb_pgbase == 0)
 			last_page = NULL;
 
-		if (!last_page || last_page != req->wb_page) {
-			pageused++;
-			if (pageused > pagecount)
-				break;
-			*pages++ = last_page = req->wb_page;
+		nfs_page_iter_page_init(&i, req);
+		while ((page = nfs_page_iter_page_get(&i)) != NULL) {
+			if (last_page != page) {
+				pageused++;
+				if (pageused > pagecount)
+					goto full;
+				*pages++ = last_page = page;
+			}
 		}
 	}
+full:
 	if (WARN_ON_ONCE(pageused != pagecount)) {
 		nfs_pgio_error(hdr);
 		desc->pg_error = -EINVAL;
@@ -942,7 +987,8 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
 		desc->pg_ioflags &= ~FLUSH_COND_STABLE;
 
 	/* Set up the argument struct */
-	nfs_pgio_rpcsetup(hdr, mirror->pg_count, desc->pg_ioflags, &cinfo);
+	nfs_pgio_rpcsetup(hdr, pg_base, mirror->pg_count, desc->pg_ioflags,
+			  &cinfo);
 	desc->pg_rpc_callops = &nfs_pgio_common_ops;
 	return 0;
 }
-- 
2.39.0


  reply	other threads:[~2023-01-19 22:03 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-19 21:33 [PATCH v2 00/18] Initial conversion of NFS basic I/O to use folios trondmy
2023-01-19 21:33 ` [PATCH v2 01/18] NFS: Fix for xfstests generic/208 trondmy
2023-01-19 21:33   ` [PATCH v2 02/18] NFS: Add basic functionality for tracking folios in struct nfs_page trondmy
2023-01-19 21:33     ` trondmy [this message]
2023-01-19 21:33       ` [PATCH v2 04/18] NFS: Fix nfs_coalesce_size() to work with folios trondmy
2023-01-19 21:33         ` [PATCH v2 05/18] NFS: Add a helper to convert a struct nfs_page into an inode trondmy
2023-01-19 21:33           ` [PATCH v2 06/18] NFS: Convert the remaining pagelist helper functions to support folios trondmy
2023-01-19 21:33             ` [PATCH v2 07/18] NFS: Add a helper nfs_wb_folio() trondmy
2023-01-19 21:33               ` [PATCH v2 08/18] NFS: Convert buffered reads to use folios trondmy
2023-01-19 21:33                 ` [PATCH v2 09/18] NFS: Convert the function nfs_wb_page() " trondmy
2023-01-19 21:33                   ` [PATCH v2 10/18] NFS: Convert buffered writes " trondmy
2023-01-19 21:33                     ` [PATCH v2 11/18] NFS: Remove unused function nfs_wb_page() trondmy
2023-01-19 21:33                       ` [PATCH v2 12/18] NFS: Convert nfs_write_begin/end to use folios trondmy
2023-01-19 21:33                         ` [PATCH v2 13/18] NFS: Fix up nfs_vm_page_mkwrite() for folios trondmy
2023-01-19 21:33                           ` [PATCH v2 14/18] NFS: Clean up O_DIRECT request allocation trondmy
2023-01-19 21:33                             ` [PATCH v2 15/18] NFS: fix up nfs_release_folio() to try to release the page trondmy
2023-01-19 21:33                               ` [PATCH v2 16/18] NFS: Enable tracing of nfs_invalidate_folio() and nfs_launder_folio() trondmy
2023-01-19 21:33                                 ` [PATCH v2 17/18] NFS: Improve tracing of nfs_wb_folio() trondmy
2023-01-19 21:33                                   ` [PATCH v2 18/18] NFS: Remove unnecessary check in nfs_read_folio() trondmy
2023-02-23 13:22                                     ` Matthew Wilcox
2023-02-23 13:43                                       ` Dan Carpenter
2023-01-24 16:07 ` [PATCH v2 00/18] Initial conversion of NFS basic I/O to use folios Olga Kornievskaia
2023-01-24 16:41   ` Trond Myklebust

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=20230119213351.443388-4-trondmy@kernel.org \
    --to=trondmy@kernel.org \
    --cc=Anna.Schumaker@netapp.com \
    --cc=linux-nfs@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.