git: 7a0021a0988f - main - nfscl: Do not delay recovery for a stale ClientID

From: Olivier Cochard <olivier_at_FreeBSD.org>
Date: Sun, 01 Nov 2026 23:35:16 UTC
The branch main has been updated by olivier:

URL: https://cgit.FreeBSD.org/src/commit/?id=7a0021a0988fa39faee847953dd8df6bc9ff56b9

commit 7a0021a0988fa39faee847953dd8df6bc9ff56b9
Author:     Olivier Cochard <olivier@FreeBSD.org>
AuthorDate: 2026-11-01 23:24:45 +0000
Commit:     Olivier Cochard <olivier@FreeBSD.org>
CommitDate: 2026-11-01 23:29:58 +0000

    nfscl: Do not delay recovery for a stale ClientID
    
    When a CREATE_SESSION with the extant ClientID failed with
    NFS4ERR_STALE_CLIENTID within nfsc_renew of the previous full recovery,
    nfsrpc_setclient() returned EIO and the mount did no I/O until that window
    expired (about 45s).
    The server has discarded the ClientID, so waiting cannot help; RFC 8881
    Section 8.4.2 requires a new ClientID (EXCHANGE_ID) and a state reclaim.
    
    AWS EFS discards both the session and the ClientID of clients whose lease is
    current whenever it resets a connection, which makes this path common there.
    
    PR:             299221
    Approved by:    rmacklem@
    Sponsored by:   Netflix
---
 sys/fs/nfsclient/nfs_clrpcops.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 464481eca0e2..1f6227e0831a 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -1069,12 +1069,15 @@ nfsrpc_setclient(struct nfsmount *nmp, struct nfsclclient *clp, int reclaim,
 				nfscl_freenfsclds(dsp);
 				dsp = NULL;
 				/*
-				 * If *retokp is true, return any error other
-				 * than NFSERR_STALECLIENTID,
+				 * A stale ClientID needs a full recovery.
+				 * Otherwise, if *retokp is true, return any
+				 * error other than NFSERR_STALECLIENTID,
 				 * NFSERR_BADSESSION or NFSERR_STALEDONTRECOVER
 				 * so that nfscl_recover() will not loop.
 				 */
-				if (*retokp)
+				if (error == NFSERR_STALECLIENTID)
+					*retokp = false;
+				else if (*retokp)
 					return (NFSERR_IO);
 			} else
 				*retokp = true;