The branch stable/15 has been updated by rmacklem:

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

commit d2b2fac918a447ea04a3321c10ffe1f0efe19261
Author:     Rick Macklem <[email protected]>
AuthorDate: 2026-06-27 23:35:20 +0000
Commit:     Rick Macklem <[email protected]>
CommitDate: 2026-07-11 01:00:18 +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.
    
    (cherry picked from commit 9e1bbfb88e986b209709ea765189a3ebb6581bcd)
---
 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 a511c31d5202..93e543197265 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));
 }
 

Reply via email to