git: 40ada74ee1da - main - nfscl: Add optional support for slots marked bad
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 09 Jul 2022 21:47:01 UTC
The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=40ada74ee1dade637675cc22d50da8254046a197 commit 40ada74ee1dade637675cc22d50da8254046a197 Author: Rick Macklem <rmacklem@FreeBSD.org> AuthorDate: 2022-07-09 21:43:16 +0000 Commit: Rick Macklem <rmacklem@FreeBSD.org> CommitDate: 2022-07-09 21:43:16 +0000 nfscl: Add optional support for slots marked bad This patch adds support for session slots marked bad to nfsv4_sequencelookup(). An additional boolean argument indicates if the check for slots marked bad should be done. The "cred" argument added to nfscl_reqstart() by commit 326bcf9394c7 is now passed into nfsv4_setquence() so that it can optionally set the boolean argument for nfsv4_sequencelookup(). When optionally enabled, nfsv4_setsequence() will do a DestroySession when all slots are marked bad. Since the code that marks slots bad is not yet committed, this patch should not result in a semantics change. PR: 260011 MFC after: 2 weeks --- sys/fs/nfs/nfs_commonkrpc.c | 2 +- sys/fs/nfs/nfs_commonsubs.c | 69 ++++++++++++++++++++++++++++++---------- sys/fs/nfs/nfs_var.h | 4 +-- sys/fs/nfs/nfsclstate.h | 1 + sys/fs/nfsserver/nfs_nfsdstate.c | 4 +-- 5 files changed, 59 insertions(+), 21 deletions(-) diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c index 4d8db64f419f..20b12767d29d 100644 --- a/sys/fs/nfs/nfs_commonkrpc.c +++ b/sys/fs/nfs/nfs_commonkrpc.c @@ -1121,7 +1121,7 @@ tryagain: if ((nd->nd_flag & ND_LOOPBADSESS) != 0) { reterr = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, &slotseq, - sessionid); + sessionid, true); if (reterr == 0) { /* Fill in new session info. */ NFSCL_DEBUG(1, diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 4c38d29ed281..6dd1a3e4c579 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -323,7 +323,7 @@ static int nfs_bigrequest[NFSV42_NPROCS] = { void nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp, u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep, - int vers, int minorvers, __unused struct ucred *cred) + int vers, int minorvers, struct ucred *cred) { struct mbuf *mb; u_int32_t *tl; @@ -416,11 +416,17 @@ nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp, *tl = txdr_unsigned(NFSV4OP_SEQUENCE); if (sep == NULL) { sep = nfsmnt_mdssession(nmp); + /* + * For MDS mount sessions, check for bad + * slots. If the caller does not want this + * check to be done, the "cred" argument can + * be passed in as NULL. + */ nfsv4_setsequence(nmp, nd, sep, - nfs_bigreply[procnum]); + nfs_bigreply[procnum], cred); } else nfsv4_setsequence(nmp, nd, sep, - nfs_bigreply[procnum]); + nfs_bigreply[procnum], NULL); } if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) { NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); @@ -4769,14 +4775,23 @@ nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, int repstat, */ void nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd, - struct nfsclsession *sep, int dont_replycache) + struct nfsclsession *sep, int dont_replycache, struct ucred *cred) { uint32_t *tl, slotseq = 0; int error, maxslot, slotpos; uint8_t sessionid[NFSX_V4SESSIONID]; - error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, &slotseq, - sessionid); + if (cred != NULL) { + error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, + &slotseq, sessionid, false); + if (error == NFSERR_SEQMISORDERED) { + /* If all slots are bad, Destroy the session. */ + nfsrpc_destroysession(nmp, sep, cred, curthread); + error = 0; + } + } else + error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, + &slotseq, sessionid, true); nd->nd_maxreq = sep->nfsess_maxreq; nd->nd_maxresp = sep->nfsess_maxresp; @@ -4813,12 +4828,18 @@ nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd, nd->nd_flag |= ND_HASSEQUENCE; } +/* + * If fnd_init is true, ignore the badslots. + * If fnd_init is false, return NFSERR_SEQMISORDERED if all slots are bad. + */ int nfsv4_sequencelookup(struct nfsmount *nmp, struct nfsclsession *sep, - int *slotposp, int *maxslotp, uint32_t *slotseqp, uint8_t *sessionid) + int *slotposp, int *maxslotp, uint32_t *slotseqp, uint8_t *sessionid, + bool fnd_init) { int i, maxslot, slotpos; uint64_t bitval; + bool fnd_ok; /* Find an unused slot. */ slotpos = -1; @@ -4832,14 +4853,18 @@ nfsv4_sequencelookup(struct nfsmount *nmp, struct nfsclsession *sep, mtx_unlock(&sep->nfsess_mtx); return (NFSERR_BADSESSION); } + fnd_ok = fnd_init; bitval = 1; for (i = 0; i < sep->nfsess_foreslots; i++) { - if ((bitval & sep->nfsess_slots) == 0) { - slotpos = i; - sep->nfsess_slots |= bitval; - sep->nfsess_slotseq[i]++; - *slotseqp = sep->nfsess_slotseq[i]; - break; + if ((bitval & sep->nfsess_badslots) == 0 || fnd_init) { + fnd_ok = true; + if ((bitval & sep->nfsess_slots) == 0) { + slotpos = i; + sep->nfsess_slots |= bitval; + sep->nfsess_slotseq[i]++; + *slotseqp = sep->nfsess_slotseq[i]; + break; + } } bitval <<= 1; } @@ -4854,10 +4879,19 @@ nfsv4_sequencelookup(struct nfsmount *nmp, struct nfsclsession *sep, return (ESTALE); } /* Wake up once/sec, to check for a forced dismount. */ - (void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx, - PZERO, "nfsclseq", hz); + if (fnd_ok) + mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx, + PZERO, "nfsclseq", hz); } - } while (slotpos == -1); + } while (slotpos == -1 && fnd_ok); + /* + * If all slots are bad, just return slot 0 and NFSERR_SEQMISORDERED. + * The caller will do a DestroySession, so that the session's use + * will get a NFSERR_BADSESSION reply from the server. + */ + if (!fnd_ok) + slotpos = 0; + /* Now, find the highest slot in use. (nfsc_slots is 64bits) */ bitval = 1; for (i = 0; i < 64; i++) { @@ -4869,6 +4903,9 @@ nfsv4_sequencelookup(struct nfsmount *nmp, struct nfsclsession *sep, mtx_unlock(&sep->nfsess_mtx); *slotposp = slotpos; *maxslotp = maxslot; + + if (!fnd_ok) + return (NFSERR_SEQMISORDERED); return (0); } diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index a9648de6b028..6692bc19a725 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -358,9 +358,9 @@ int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *, struct mbuf **, uint16_t); void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, int, struct mbuf **); void nfsv4_setsequence(struct nfsmount *, struct nfsrv_descript *, - struct nfsclsession *, int); + struct nfsclsession *, int, struct ucred *); int nfsv4_sequencelookup(struct nfsmount *, struct nfsclsession *, int *, - int *, uint32_t *, uint8_t *); + int *, uint32_t *, uint8_t *, bool); void nfsv4_freeslot(struct nfsclsession *, int, bool); struct ucred *nfsrv_getgrpscred(struct ucred *); struct nfsdevice *nfsv4_findmirror(struct nfsmount *); diff --git a/sys/fs/nfs/nfsclstate.h b/sys/fs/nfs/nfsclstate.h index 03400a2cdea5..2b9b804a08dd 100644 --- a/sys/fs/nfs/nfsclstate.h +++ b/sys/fs/nfs/nfsclstate.h @@ -67,6 +67,7 @@ struct nfsclsession { SVCXPRT *nfsess_xprt; /* For backchannel callback */ uint32_t nfsess_slotseq[64]; /* Max for 64bit nm_slots */ uint64_t nfsess_slots; + uint64_t nfsess_badslots; /* Slots possibly broken */ uint32_t nfsess_sequenceid; uint32_t nfsess_maxcache; /* Max size for cached reply. */ uint32_t nfsess_maxreq; /* Max request size. */ diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index 419851895c7a..eafb7c958396 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -6637,8 +6637,8 @@ nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp, if (error != 0) return (error); sep = *sepp; - (void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, slotposp, &maxslot, - &slotseq, sessionid); + nfsv4_sequencelookup(NULL, &sep->sess_cbsess, slotposp, &maxslot, + &slotseq, sessionid, true); KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot")); /* Build the Sequence arguments. */