aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2022-07-09 21:43:16 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2022-07-27 20:10:02 +0000
commit39f07893a5f6e12d6b3484de842d450ef6934904 (patch)
treec26e3ddc109298cdab3d02ad0f075ab7acf620a7
parent4c941909462bf9b7b2b3a14a2d22072eebc08de2 (diff)
downloadsrc-39f07893a5f6e12d6b3484de842d450ef6934904.tar.gz
src-39f07893a5f6e12d6b3484de842d450ef6934904.zip
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 (cherry picked from commit 40ada74ee1dade637675cc22d50da8254046a197)
-rw-r--r--sys/fs/nfs/nfs_commonkrpc.c2
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c69
-rw-r--r--sys/fs/nfs/nfs_var.h4
-rw-r--r--sys/fs/nfs/nfsclstate.h1
-rw-r--r--sys/fs/nfsserver/nfs_nfsdstate.c4
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 bae4c82a998b..72482784a0a0 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);
@@ -4773,14 +4779,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;
@@ -4817,12 +4832,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;
@@ -4836,14 +4857,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;
}
@@ -4858,10 +4883,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++) {
@@ -4873,6 +4907,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 cf963691109b..9dd3be3d5c42 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -356,9 +356,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 9059b032cb86..842d3c75f678 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. */