All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pranjal Shrivastava <praan@google.com>
To: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Trond Myklebust <trondmy@kernel.org>,
	Anna Schumaker <anna@kernel.org>, Christoph Hellwig <hch@lst.de>,
	 Christoph Hellwig <hch@infradead.org>,
	Shivaji Kant <shivajikant@google.com>,
	 Pranjal Shrivastava <praan@google.com>
Subject: [PATCH v2 6/7] nfs: Optimize direct I/O to use folios for requests
Date: Tue, 16 Jun 2026 13:39:59 +0000	[thread overview]
Message-ID: <20260616134000.2733403-7-praan@google.com> (raw)
In-Reply-To: <20260616134000.2733403-1-praan@google.com>

Optimize nfs_direct_extract_pages() to group contiguous pages from the
same folio into single nfs_page structures. This effectively migrates
NFS Direct I/O from being page-based to being folio-based.

Reduce the number of nfs_page allocations and subsequent iterations
by utilizing nfs_page_create_from_folio() to create aggregated
requests.

Signed-off-by: Pranjal Shrivastava <praan@google.com>
---
 fs/nfs/direct.c | 47 +++++++++++++++++++++++++++++++++++++----------
 1 file changed, 37 insertions(+), 10 deletions(-)

diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index e2a93cfb6c72..ddc6b27f5315 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -194,23 +194,45 @@ static ssize_t nfs_direct_extract_pages(struct nfs_direct_req *dreq,
 		return result;
 
 	npages = (result + pgbase + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	for (i = 0; i < npages; i++) {
+	for (i = 0; i < npages; ) {
+		unsigned int chunk_len, folio_offset;
+		unsigned int nr_to_add = 1;
 		struct nfs_page *req;
-		unsigned int req_len = min_t(size_t, result - bytes, PAGE_SIZE - pgbase);
+		struct folio *folio;
 
-		req = nfs_page_create_from_page(dreq->ctx, pagevec[i],
-						pinned, pgbase, *pos,
-						req_len);
+		folio = page_folio(pagevec[i]);
+		folio_offset = (folio_page_idx(folio, pagevec[i]) << PAGE_SHIFT) + pgbase;
+		chunk_len = min_t(size_t, result - bytes, PAGE_SIZE - pgbase);
+
+		while (i + nr_to_add < npages) {
+			struct page *next_page = pagevec[i + nr_to_add];
+			struct page *prev_page = pagevec[i + nr_to_add - 1];
+
+			if (page_folio(next_page) != folio ||
+			    next_page != prev_page + 1)
+				break;
+
+			chunk_len += min_t(size_t, result - bytes - chunk_len, PAGE_SIZE);
+			nr_to_add++;
+		}
+
+		req = nfs_page_create_from_folio(dreq->ctx, folio,
+						  pinned, folio_offset,
+						  chunk_len);
 		if (IS_ERR(req)) {
 			if (!bytes)
 				bytes = PTR_ERR(req);
 			break;
 		}
 
+		req->wb_index = *pos >> PAGE_SHIFT;
+		req->wb_offset = offset_in_page(*pos);
+
 		list_add_tail(&req->wb_list, list);
 		pgbase = 0;
-		bytes += req_len;
-		*pos += req_len;
+		bytes += chunk_len;
+		*pos += chunk_len;
+		i += nr_to_add;
 	}
 
 	if (i < npages) {
@@ -403,9 +425,9 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
 		if (result < 0)
 			break;
 
-		requested_bytes += result;
 		while (!list_empty(&nfs_page_list)) {
 			struct nfs_page *req = nfs_list_entry(nfs_page_list.next);
+			size_t req_len = req->wb_bytes;
 
 			nfs_list_remove_request(req);
 			if (!nfs_pageio_add_request(&desc, req)) {
@@ -414,6 +436,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
 				nfs_release_request_list(&nfs_page_list);
 				break;
 			}
+			requested_bytes += req_len;
 		}
 		if (result < 0)
 			break;
@@ -922,19 +945,22 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
 		if (result < 0)
 			break;
 
-		requested_bytes += result;
 		while (!list_empty(&nfs_page_list)) {
 			struct nfs_page *req = nfs_list_entry(nfs_page_list.next);
+			size_t req_len = req->wb_bytes;
 
 			nfs_list_remove_request(req);
 			if (defer) {
 				nfs_mark_request_commit(req, NULL, &cinfo, 0);
+				requested_bytes += req_len;
 				continue;
 			}
 
 			nfs_lock_request(req);
-			if (nfs_pageio_add_request(&desc, req))
+			if (nfs_pageio_add_request(&desc, req)) {
+				requested_bytes += req_len;
 				continue;
+			}
 
 			/* Exit on hard errors */
 			if (desc.pg_error < 0 && desc.pg_error != -EAGAIN) {
@@ -951,6 +977,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
 			spin_unlock(&dreq->lock);
 			nfs_unlock_request(req);
 			nfs_mark_request_commit(req, NULL, &cinfo, 0);
+			requested_bytes += req_len;
 			desc.pg_error = 0;
 			defer = true;
 		}
-- 
2.54.0.1136.gdb2ca164c4-goog


  parent reply	other threads:[~2026-06-16 13:40 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-16 13:39 [PATCH v2 0/7] nfs: Modernize Direct I/O path Pranjal Shrivastava
2026-06-16 13:39 ` [PATCH v2 1/7] nfs: make nfs_page pin-aware Pranjal Shrivastava
2026-06-16 13:39 ` [PATCH v2 2/7] nfs: Track number of pinned pages in nfs_page Pranjal Shrivastava
2026-06-16 13:39 ` [PATCH v2 3/7] nfs: Introduce nfs_release_request_list helper Pranjal Shrivastava
2026-06-16 13:39 ` [PATCH v2 4/7] nfs: migrate direct I/O to iov_iter_extract_pages Pranjal Shrivastava
2026-06-16 13:39 ` [PATCH v2 5/7] nfs: introduce nfs_direct_extract_pages helper Pranjal Shrivastava
2026-06-16 13:39 ` Pranjal Shrivastava [this message]
2026-06-16 15:29   ` [PATCH v2 6/7] nfs: Optimize direct I/O to use folios for requests Trond Myklebust
2026-06-16 17:23     ` Pranjal Shrivastava
2026-06-16 13:40 ` [PATCH v2 7/7] nfs: Cleanup the nfs_page_create_from_page helper Pranjal Shrivastava
2026-06-16 14:15 ` [PATCH v2 0/7] nfs: Modernize Direct I/O path Pranjal Shrivastava

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=20260616134000.2733403-7-praan@google.com \
    --to=praan@google.com \
    --cc=anna@kernel.org \
    --cc=hch@infradead.org \
    --cc=hch@lst.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=shivajikant@google.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 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.