git: 9e1bbfb88e98 - main - nfs_clstate.c: Fix CB_RECALL handling for NFSv4.1/4.2
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 27 Jun 2026 23:37:13 UTC
The branch main has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=9e1bbfb88e986b209709ea765189a3ebb6581bcd
commit 9e1bbfb88e986b209709ea765189a3ebb6581bcd
Author: Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2026-06-27 23:35:20 +0000
Commit: Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2026-06-27 23:35:20 +0000
nfs_clstate.c: Fix CB_RECALL handling for NFSv4.1/4.2
Recent testing with a modified NFSv4.1/4.2 client that
sometimes ignored CB_RECALL callbacks, identified a few
problems when handling the unusual case of CB_RECALL not
be performed by the client.
- The csa_cachethis argument to CB_SEQUENCE was being ignored.
- The CB_SEQUENCE operation would reply NFSERR_DELAY
after the first CB_RECALL attempt, making retries
ineffective.
- The code could return NFSERR_RESOURCE, which is a
NFSv4.0 specific error code.
This patch fixes the above three problems.
The patch only affects the NFSv4.1/4.2 client when
delegations are being issued and the client somehow
fails to handle a CB_RECALL callback of a delegation,
which is an unusual case.
MFC after: 2 weeks
---
sys/fs/nfsclient/nfs_clstate.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c
index 1931964ed62e..e906de603c28 100644
--- a/sys/fs/nfsclient/nfs_clstate.c
+++ b/sys/fs/nfsclient/nfs_clstate.c
@@ -3585,7 +3585,7 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)
mount_t mp;
nfsattrbit_t attrbits, rattrbits;
nfsv4stateid_t stateid;
- uint32_t seqid, slotid = 0, highslot, cachethis __unused;
+ uint32_t seqid, slotid = 0, highslot, cachethis;
uint8_t sessionid[NFSX_V4SESSIONID];
struct mbuf *rep;
struct nfscllayout *lyp;
@@ -3596,6 +3596,7 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)
struct nfsclsession *tsep;
gotseq_ok = 0;
+ cachethis = 0;
nfsrvd_rephead(nd);
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
taglen = fxdr_unsigned(int, *tl);
@@ -3922,6 +3923,9 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)
error = nfsv4_seqsession(seqid, slotid,
highslot, tsep->nfsess_cbslots, &rep,
tsep->nfsess_backslots);
+ /* For callbacks, do not reply NFSERR_DELAY. */
+ if (error == NFSERR_DELAY)
+ error = 0;
}
NFSUNLOCKCLSTATE();
if (error == 0 || error == NFSERR_REPLYFROMCACHE) {
@@ -4065,8 +4069,9 @@ nfsmout:
}
*nd->nd_errp = nfscl_errmap(nd, minorvers);
out:
- if (gotseq_ok != 0) {
+ if (gotseq_ok != 0 && cachethis != 0) {
rep = m_copym(nd->nd_mreq, 0, M_COPYALL, M_WAITOK);
+ NFSCL_DEBUG(4, "Got reply for cbcache=%p\n", rep);
NFSLOCKCLSTATE();
clp = nfscl_getclntsess(sessionid);
if (clp != NULL) {
@@ -5283,6 +5288,8 @@ nfscl_errmap(struct nfsrv_descript *nd, u_int32_t minorvers)
while (*++errp)
if (*errp == (short)nd->nd_repstat)
return (txdr_unsigned(nd->nd_repstat));
+ if (minorvers > NFSV4_MINORVERSION && *defaulterrp == NFSERR_RESOURCE)
+ return (txdr_unsigned(NFSERR_SERVERFAULT));
return (txdr_unsigned(*defaulterrp));
}