[PATCH 1/6] NFSv4.1/pnfs: suspend pNFS on NFS4ERR_TOOSMALL from LAYOUTGET
Benjamin Coddington <ben.coddington-F/[email protected]>
| Newsgroups | gmane.linux.nfs |
|---|---|
| Message-ID | <57c201555a87e999cd2de1747901f3b6cc3d5792.1786653456.git.bcodding@hammerspace.com> |
If the layout for the requested range is larger than the size the
client advertised in loga_maxcount, RFC 8881 Section 18.43.3 has the
metadata server return NFS4ERR_TOOSMALL. The client caps
loga_maxcount at a single page, so a flexfiles server that stripes a
layout segment across several dozen data servers produces this error
today.
The client has no handling for it: nfs4_stat_to_errno() maps the
error to -ETOOSMALL during decode, which nothing in the layoutget
path recognizes and nfs_error_is_fatal() does not consider fatal, so
pnfs_update_layout() clears the layout fail bit and returns no
segment. The I/O falls back to the MDS, but because no fail bit was
set, every subsequent pageio attempt sends another LAYOUTGET that is
doomed to the same NFS4ERR_TOOSMALL. Files whose layouts do not fit
the reply buffer never use pNFS and pay an extra round trip on every
pageio.
Map -ETOOSMALL to -EMSGSIZE in the layoutget exception handler and
have pnfs_update_layout() treat it like NFS4ERR_LAYOUTUNAVAILABLE:
mark the layout mode as failed and fall back to I/O through the MDS.
Fixes: d600ad1f2bdb ("NFS41: pop some layoutget errors to application")
Cc: [email protected]
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Benjamin Coddington <bcodding-F/[email protected]>
---
fs/nfs/nfs4proc.c | 9 +++++++++
fs/nfs/pnfs.c | 2 ++
2 files changed, 11 insertions(+)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5709c6fea85b..016e8b38b87b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -9623,6 +9623,15 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
case -NFS4ERR_BADLAYOUT:
status = -EOVERFLOW;
goto out;
+ /*
+ * NFS4ERR_TOOSMALL means the layout for the requested range
+ * exceeds what the client advertised in loga_maxcount (see
+ * RFC8881 section 18.43.3). Note nfs4_stat_to_errno() has
+ * already mapped it to -ETOOSMALL during decode.
+ */
+ case -ETOOSMALL:
+ status = -EMSGSIZE;
+ goto out;
/*
* NFS4ERR_LAYOUTTRYLATER is a conflict with another client
* (or clients) writing to the same RAID stripe except when
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 7715e2bd5871..10102bda6a38 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -2338,6 +2338,8 @@ pnfs_update_layout(struct inode *ino,
break;
case -ENODATA:
/* The server returned NFS4ERR_LAYOUTUNAVAILABLE */
+ case -EMSGSIZE:
+ /* The layout exceeded loga_maxcount (NFS4ERR_TOOSMALL) */
pnfs_layout_set_fail_bit(
lo, pnfs_iomode_to_fail_bit(iomode));
lseg = NULL;
--
2.53.0