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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox