[PATCH 5/6] NFSv4.1/pnfs: remember when a server needs a larger LAYOUTGET reply buffer

Benjamin Coddington <ben.coddington-F/[email protected]>
Newsgroups gmane.linux.nfs
Message-ID <05a40a0ca55e214c9593b1cf717dde9b2b3d7bb9.1786653456.git.bcodding@hammerspace.com>
When a LAYOUTGET only succeeds after escalating the reply buffer, every
layout fetched from that server is likely to need the larger buffer:
remember the escalated size on the nfs_server and use it as the floor
for subsequent LAYOUTGET reply buffers, skipping the doomed attempt at
the layout driver's default size.

This also lets the LAYOUTGET attached to OPEN benefit: the lgopen path
is best-effort with no retry of its own, so without the learned size
it would fail with NFS4ERR_TOOSMALL at every open against a server
handing out wide layouts, and layouts would only ever be acquired by
the I/O path's retry.

The field is a hint: reads and writes are racy by design, the value
only ever grows toward the session's maximum response size, and a
stale-low read merely costs one escalation round trip.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Benjamin Coddington <bcodding-F/[email protected]>
---
 fs/nfs/pnfs.c             | 15 ++++++++++++---
 include/linux/nfs_fs_sb.h |  4 ++++
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index b596a65c7ef2..e9ec960ac22d 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1187,10 +1187,12 @@ pnfs_alloc_init_layoutget_args(struct inode *ino,
 	}
 
 	/*
-	 * A previous LAYOUTGET for this layout did not fit the reply
-	 * buffer: raise the layout driver's default up to the session's
-	 * maximum response size.
+	 * A previous LAYOUTGET on this layout or on this server did not
+	 * fit the reply buffer: raise the layout driver's default up to
+	 * the session's maximum response size.
 	 */
+	if (!min_reply_sz)
+		min_reply_sz = READ_ONCE(server->lg_reply_sz);
 	if (min_reply_sz) {
 		size_t npages = (min_reply_sz + PAGE_SIZE - 1) >> PAGE_SHIFT;
 		if (npages > max_pages)
@@ -2393,6 +2395,13 @@ pnfs_update_layout(struct inode *ino,
 			goto lookup_again;
 		}
 	} else {
+		/*
+		 * A LAYOUTGET that only succeeded with an escalated reply
+		 * buffer: remember the size so that future LAYOUTGETs to
+		 * this server skip the attempt at the driver's default.
+		 */
+		if (reply_sz)
+			WRITE_ONCE(server->lg_reply_sz, reply_sz);
 		pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
 	}
 
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 34d294774f8c..3e6bae7e5221 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -248,6 +248,10 @@ struct nfs_server {
 						   that are supported on this
 						   filesystem */
 	struct pnfs_layoutdriver_type  *pnfs_curr_ld; /* Active layout driver */
+	unsigned int		lg_reply_sz;	/* Learned LAYOUTGET reply
+						   buffer size, when the layout
+						   driver's default has proved
+						   too small */
 	struct rpc_wait_queue	roc_rpcwaitq;
 
 	/* the following fields are protected by nfs_client->cl_lock */
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.