Page MenuHomeFreeBSD

D8745.id22794.diff
No OneTemporary

D8745.id22794.diff

Index: fs/nfs/nfs.h
===================================================================
--- fs/nfs/nfs.h
+++ fs/nfs/nfs.h
@@ -601,6 +601,7 @@
uint8_t nd_sessionid[NFSX_V4SESSIONID]; /* Session id */
uint32_t nd_slotid; /* Slotid for this RPC */
SVCXPRT *nd_xprt; /* Server RPC handle */
+ uint32_t *nd_sequence; /* Sequence Op. ptr */
};
#define nd_princlen nd_gssnamelen
@@ -636,6 +637,7 @@
#define ND_HASSEQUENCE 0x04000000
#define ND_CACHETHIS 0x08000000
#define ND_LASTOP 0x10000000
+#define ND_LOOPBADSESS 0x20000000
/*
* ND_GSS should be the "or" of all GSS type authentications.
@@ -649,6 +651,7 @@
int modifyfs;
int lktype;
int needsseq;
+ int loopbadsess;
};
/*
Index: fs/nfs/nfs_commonkrpc.c
===================================================================
--- fs/nfs/nfs_commonkrpc.c
+++ fs/nfs/nfs_commonkrpc.c
@@ -89,6 +89,7 @@
NFSSTATESPINLOCK;
NFSREQSPINLOCK;
NFSDLOCKMUTEX;
+NFSCLSTATEMUTEX;
extern struct nfsstatsv1 nfsstatsv1;
extern struct nfsreqhead nfsd_reqq;
extern int nfscl_ticks;
@@ -473,13 +474,13 @@
newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
struct nfsclient *clp, struct nfssockreq *nrp, vnode_t vp,
struct thread *td, struct ucred *cred, u_int32_t prog, u_int32_t vers,
- u_char *retsum, int toplevel, u_int64_t *xidp, struct nfsclsession *sep)
+ u_char *retsum, int toplevel, u_int64_t *xidp, struct nfsclsession *dssep)
{
- u_int32_t retseq, retval, *tl;
+ uint32_t retseq, retval, slotseq, *tl;
time_t waituntil;
int i = 0, j = 0, opcnt, set_sigset = 0, slot;
int trycnt, error = 0, usegssname = 0, secflavour = AUTH_SYS;
- int freeslot, timeo;
+ int freeslot, maxslot, reterr, slotpos, timeo;
u_int16_t procnum;
u_int trylater_delay = 1;
struct nfs_feedback_arg nf;
@@ -491,7 +492,10 @@
char *srv_principal = NULL, *clnt_principal = NULL;
sigset_t oldset;
struct ucred *authcred;
+ struct nfsclsession *sep;
+ uint8_t sessionid[NFSX_V4SESSIONID];
+ sep = dssep;
if (xidp != NULL)
*xidp = 0;
/* Reject requests while attempting a forced unmount. */
@@ -803,7 +807,7 @@
nd->nd_procnum != NFSV4PROC_CBNULL) {
/* If sep == NULL, set it to the default in nmp. */
if (sep == NULL && nmp != NULL)
- sep = NFSMNT_MDSSESSION(nmp);
+ sep = nfsmnt_mdssession(nmp);
/*
* and now the actual NFS xdr.
*/
@@ -847,18 +851,25 @@
NFSX_V4SESSIONID +
4 * NFSX_UNSIGNED);
mtx_lock(&sep->nfsess_mtx);
- tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
- retseq = fxdr_unsigned(uint32_t, *tl++);
- slot = fxdr_unsigned(int, *tl++);
- freeslot = slot;
- if (retseq != sep->nfsess_slotseq[slot])
- printf("retseq diff 0x%x\n", retseq);
- retval = fxdr_unsigned(uint32_t, *++tl);
- if ((retval + 1) < sep->nfsess_foreslots)
- sep->nfsess_foreslots = (retval + 1);
- else if ((retval + 1) > sep->nfsess_foreslots)
- sep->nfsess_foreslots = (retval < 64) ?
- (retval + 1) : 64;
+ if (bcmp(tl, sep->nfsess_sessionid,
+ NFSX_V4SESSIONID) == 0) {
+ tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
+ retseq = fxdr_unsigned(uint32_t, *tl++);
+ slot = fxdr_unsigned(int, *tl++);
+ freeslot = slot;
+ if (retseq != sep->nfsess_slotseq[slot])
+ printf("retseq diff 0x%x\n",
+ retseq);
+ retval = fxdr_unsigned(uint32_t, *++tl);
+ if ((retval + 1) < sep->nfsess_foreslots
+ )
+ sep->nfsess_foreslots = (retval
+ + 1);
+ else if ((retval + 1) >
+ sep->nfsess_foreslots)
+ sep->nfsess_foreslots = (retval
+ < 64) ? (retval + 1) : 64;
+ }
mtx_unlock(&sep->nfsess_mtx);
/* Grab the op and status for the next one. */
@@ -871,6 +882,76 @@
}
}
if (nd->nd_repstat != 0) {
+ if (nd->nd_repstat == NFSERR_BADSESSION &&
+ nmp != NULL && dssep == NULL) {
+ /*
+ * If this is a client side MDS RPC, mark
+ * the MDS session defunct and initiate
+ * recovery, as required.
+ * The nfsess_defunct field is protected by
+ * the NFSLOCKMNT()/nm_mtx lock and not the
+ * nfsess_mtx lock to simplify its handling,
+ * for the MDS session. This lock is also
+ * sufficient for nfsess_sessionid, since it
+ * never changes in the structure.
+ */
+ NFSCL_DEBUG(1, "Got badsession\n");
+ NFSLOCKCLSTATE();
+ NFSLOCKMNT(nmp);
+ sep = NFSMNT_MDSSESSION(nmp);
+ if (bcmp(sep->nfsess_sessionid, nd->nd_sequence,
+ NFSX_V4SESSIONID) == 0) {
+ /* Initiate recovery. */
+ sep->nfsess_defunct = 1;
+ NFSCL_DEBUG(1, "Marked defunct\n");
+ if (nmp->nm_clp != NULL) {
+ nmp->nm_clp->nfsc_flags |=
+ NFSCLFLAGS_RECOVER;
+ wakeup(nmp->nm_clp);
+ }
+ }
+ NFSUNLOCKCLSTATE();
+ /*
+ * Sleep for up to 1sec waiting for a new
+ * session.
+ */
+ mtx_sleep(&nmp->nm_sess, &nmp->nm_mtx, PZERO,
+ "nfsbadsess", hz);
+ /*
+ * Get the session again, in case a new one
+ * has been created during the sleep.
+ */
+ sep = NFSMNT_MDSSESSION(nmp);
+ NFSUNLOCKMNT(nmp);
+ if ((nd->nd_flag & ND_LOOPBADSESS) != 0) {
+ reterr = nfsv4_sequencelookup(nmp, sep,
+ &slotpos, &maxslot, &slotseq,
+ sessionid);
+ if (reterr == 0) {
+ /* Fill in new session info. */
+ NFSCL_DEBUG(1,
+ "Filling in new sequence\n");
+ tl = nd->nd_sequence;
+ bcopy(sessionid, tl,
+ NFSX_V4SESSIONID);
+ tl += NFSX_V4SESSIONID /
+ NFSX_UNSIGNED;
+ *tl++ = txdr_unsigned(slotseq);
+ *tl++ = txdr_unsigned(slotpos);
+ *tl = txdr_unsigned(maxslot);
+ }
+ if (reterr == NFSERR_BADSESSION ||
+ reterr == 0) {
+ NFSCL_DEBUG(1,
+ "Badsession looping\n");
+ m_freem(nd->nd_mrep);
+ nd->nd_mrep = NULL;
+ goto tryagain;
+ }
+ nd->nd_repstat = reterr;
+ NFSCL_DEBUG(1, "Got err=%d\n", reterr);
+ }
+ }
if (((nd->nd_repstat == NFSERR_DELAY ||
nd->nd_repstat == NFSERR_GRACE) &&
(nd->nd_flag & ND_NFSV4) &&
Index: fs/nfs/nfs_commonport.c
===================================================================
--- fs/nfs/nfs_commonport.c
+++ fs/nfs/nfs_commonport.c
@@ -129,6 +129,7 @@
struct mtx nfs_nameid_mutex;
struct mtx nfs_req_mutex;
struct mtx nfs_slock_mutex;
+struct mtx nfs_clstate_mutex;
/* local functions */
static int nfssvc_call(struct thread *, struct nfssvc_args *, struct ucred *);
@@ -647,6 +648,7 @@
/* Initialize SMP locks used by both client and server. */
mtx_init(&newnfsd_mtx, "newnfsd_mtx", NULL, MTX_DEF);
mtx_init(&nfs_state_mutex, "nfs_state_mutex", NULL, MTX_DEF);
+ mtx_init(&nfs_clstate_mutex, "nfs_clstate_mutex", NULL, MTX_DEF);
}
/*
@@ -712,6 +714,7 @@
mtx_destroy(&nfs_nameid_mutex);
mtx_destroy(&newnfsd_mtx);
mtx_destroy(&nfs_state_mutex);
+ mtx_destroy(&nfs_clstate_mutex);
mtx_destroy(&nfs_sockl_mutex);
mtx_destroy(&nfs_slock_mutex);
mtx_destroy(&nfs_req_mutex);
Index: fs/nfs/nfs_commonsubs.c
===================================================================
--- fs/nfs/nfs_commonsubs.c
+++ fs/nfs/nfs_commonsubs.c
@@ -90,65 +90,65 @@
* Define it here, since it is used by both the client and server.
*/
struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS] = {
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* undef */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* undef */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* undef */
- { 0, 1, 0, 0, LK_SHARED, 1 }, /* Access */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Close */
- { 0, 2, 0, 1, LK_EXCLUSIVE, 1 }, /* Commit */
- { 1, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Create */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Delegpurge */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Delegreturn */
- { 0, 1, 0, 0, LK_SHARED, 1 }, /* Getattr */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* GetFH */
- { 2, 1, 1, 1, LK_EXCLUSIVE, 1 }, /* Link */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Lock */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* LockT */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* LockU */
- { 1, 2, 0, 0, LK_EXCLUSIVE, 1 }, /* Lookup */
- { 1, 2, 0, 0, LK_EXCLUSIVE, 1 }, /* Lookupp */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* NVerify */
- { 1, 1, 0, 1, LK_EXCLUSIVE, 1 }, /* Open */
- { 1, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* OpenAttr */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* OpenConfirm */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* OpenDowngrade */
- { 1, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* PutFH */
- { 1, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* PutPubFH */
- { 1, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* PutRootFH */
- { 0, 1, 0, 0, LK_SHARED, 1 }, /* Read */
- { 0, 1, 0, 0, LK_SHARED, 1 }, /* Readdir */
- { 0, 1, 0, 0, LK_SHARED, 1 }, /* ReadLink */
- { 0, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Remove */
- { 2, 1, 1, 1, LK_EXCLUSIVE, 1 }, /* Rename */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Renew */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* RestoreFH */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* SaveFH */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* SecInfo */
- { 0, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Setattr */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* SetClientID */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* SetClientIDConfirm */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Verify */
- { 0, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Write */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* ReleaseLockOwner */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Backchannel Ctrl */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Bind Conn to Sess */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Exchange ID */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Create Session */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Destroy Session */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Free StateID */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Get Dir Deleg */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Get Device Info */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Get Device List */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Layout Commit */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Layout Get */
- { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Layout Return */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Secinfo No name */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Sequence */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Set SSV */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Test StateID */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Want Delegation */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Destroy ClientID */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Reclaim Complete */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* undef */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* undef */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* undef */
+ { 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Access */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Close */
+ { 0, 2, 0, 1, LK_EXCLUSIVE, 1, 1 }, /* Commit */
+ { 1, 2, 1, 1, LK_EXCLUSIVE, 1, 0 }, /* Create */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Delegpurge */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Delegreturn */
+ { 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Getattr */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* GetFH */
+ { 2, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Link */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Lock */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* LockT */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* LockU */
+ { 1, 2, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Lookup */
+ { 1, 2, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Lookupp */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* NVerify */
+ { 1, 1, 0, 1, LK_EXCLUSIVE, 1, 0 }, /* Open */
+ { 1, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* OpenAttr */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* OpenConfirm */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* OpenDowngrade */
+ { 1, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* PutFH */
+ { 1, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* PutPubFH */
+ { 1, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* PutRootFH */
+ { 0, 1, 0, 0, LK_SHARED, 1, 0 }, /* Read */
+ { 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Readdir */
+ { 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* ReadLink */
+ { 0, 2, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Remove */
+ { 2, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Rename */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Renew */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* RestoreFH */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* SaveFH */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* SecInfo */
+ { 0, 2, 1, 1, LK_EXCLUSIVE, 1, 0 }, /* Setattr */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* SetClientID */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* SetClientIDConfirm */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Verify */
+ { 0, 2, 1, 1, LK_EXCLUSIVE, 1, 0 }, /* Write */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* ReleaseLockOwner */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Backchannel Ctrl */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Bind Conn to Sess */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 }, /* Exchange ID */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 }, /* Create Session */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 }, /* Destroy Session */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Free StateID */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Get Dir Deleg */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Get Device Info */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Get Device List */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Layout Commit */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Layout Get */
+ { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Layout Return */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Secinfo No name */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* Sequence */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Set SSV */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Test StateID */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Want Delegation */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 }, /* Destroy ClientID */
+ { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Reclaim Complete */
};
#endif /* !APPLEKEXT */
@@ -4112,22 +4112,35 @@
error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, &slotseq,
sessionid);
- if (error != 0)
- return;
- KASSERT(maxslot >= 0, ("nfscl_setsequence neg maxslot"));
/* Build the Sequence arguments. */
NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
+ nd->nd_sequence = tl;
bcopy(sessionid, tl, NFSX_V4SESSIONID);
tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
nd->nd_slotseq = tl;
- *tl++ = txdr_unsigned(slotseq);
- *tl++ = txdr_unsigned(slotpos);
- *tl++ = txdr_unsigned(maxslot);
- if (dont_replycache == 0)
- *tl = newnfs_true;
- else
- *tl = newnfs_false;
+ if (error == 0) {
+ *tl++ = txdr_unsigned(slotseq);
+ *tl++ = txdr_unsigned(slotpos);
+ *tl++ = txdr_unsigned(maxslot);
+ if (dont_replycache == 0)
+ *tl = newnfs_true;
+ else
+ *tl = newnfs_false;
+ } else {
+ /*
+ * There are two errors and the rest of the session can
+ * just be zeros.
+ * NFSERR_BADSESSION: This bad session should just generate
+ * the same error again when the RPC is retried.
+ * ESTALE: A forced dismount is in progress and will cause the
+ * RPC to fail later.
+ */
+ *tl++ = 0;
+ *tl++ = 0;
+ *tl++ = 0;
+ *tl = 0;
+ }
nd->nd_flag |= ND_HASSEQUENCE;
}
@@ -4143,6 +4156,13 @@
maxslot = -1;
mtx_lock(&sep->nfsess_mtx);
do {
+ if (nmp != NULL && sep->nfsess_defunct != 0) {
+ /* Just return the bad session. */
+ bcopy(sep->nfsess_sessionid, sessionid,
+ NFSX_V4SESSIONID);
+ mtx_unlock(&sep->nfsess_mtx);
+ return (NFSERR_BADSESSION);
+ }
bitval = 1;
for (i = 0; i < sep->nfsess_foreslots; i++) {
if ((bitval & sep->nfsess_slots) == 0) {
Index: fs/nfs/nfsclstate.h
===================================================================
--- fs/nfs/nfsclstate.h
+++ fs/nfs/nfsclstate.h
@@ -65,6 +65,7 @@
uint16_t nfsess_foreslots;
uint16_t nfsess_backslots;
uint8_t nfsess_sessionid[NFSX_V4SESSIONID];
+ uint8_t nfsess_defunct; /* Non-zero for old sessions */
};
/*
Index: fs/nfsclient/nfs_clcomsubs.c
===================================================================
--- fs/nfsclient/nfs_clcomsubs.c
+++ fs/nfsclient/nfs_clcomsubs.c
@@ -200,13 +200,16 @@
*tl = txdr_unsigned(opcnt);
if ((nd->nd_flag & ND_NFSV41) != 0 &&
nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) {
+ if (nfsv4_opflag[nfsv4_opmap[procnum].op].loopbadsess >
+ 0)
+ nd->nd_flag |= ND_LOOPBADSESS;
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(NFSV4OP_SEQUENCE);
- if (sep == NULL)
- nfsv4_setsequence(nmp, nd,
- NFSMNT_MDSSESSION(nmp),
+ if (sep == NULL) {
+ sep = nfsmnt_mdssession(nmp);
+ nfsv4_setsequence(nmp, nd, sep,
nfs_bigreply[procnum]);
- else
+ } else
nfsv4_setsequence(nmp, nd, sep,
nfs_bigreply[procnum]);
}
Index: fs/nfsclient/nfs_clport.c
===================================================================
--- fs/nfsclient/nfs_clport.c
+++ fs/nfsclient/nfs_clport.c
@@ -82,7 +82,6 @@
extern int nfscl_enablecallb;
extern int nfs_numnfscbd;
extern int nfscl_inited;
-struct mtx nfs_clstate_mutex;
struct mtx ncl_iod_mutex;
NFSDLOCKMUTEX;
@@ -1381,8 +1380,6 @@
if (loaded)
return (0);
newnfs_portinit();
- mtx_init(&nfs_clstate_mutex, "nfs_clstate_mutex", NULL,
- MTX_DEF);
mtx_init(&ncl_iod_mutex, "ncl_iod_mutex", NULL, MTX_DEF);
nfscl_init();
NFSD_LOCK();
@@ -1406,7 +1403,6 @@
ncl_call_invalcaches = NULL;
nfsd_call_nfscl = NULL;
/* and get rid of the mutexes */
- mtx_destroy(&nfs_clstate_mutex);
mtx_destroy(&ncl_iod_mutex);
loaded = 0;
break;
Index: fs/nfsclient/nfs_clrpcops.c
===================================================================
--- fs/nfsclient/nfs_clrpcops.c
+++ fs/nfsclient/nfs_clrpcops.c
@@ -384,6 +384,7 @@
u_int32_t rflags, deleg;
nfsattrbit_t attrbits;
int error, ret, acesize, limitby;
+ struct nfsclsession *tsep;
dp = *dpp;
*dpp = NULL;
@@ -392,8 +393,9 @@
*tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
*tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH);
*tl++ = txdr_unsigned((mode >> NFSLCK_SHIFT) & NFSV4OPEN_DENYBOTH);
- *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
- *tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
+ tsep = nfsmnt_mdssession(nmp);
+ *tl++ = tsep->nfsess_clientid.lval[0];
+ *tl = tsep->nfsess_clientid.lval[1];
(void) nfsm_strtom(nd, op->nfso_own->nfsow_owner, NFSV4CL_LOCKNAMELEN);
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(NFSV4OPEN_NOCREATE);
@@ -557,7 +559,7 @@
}
if (nd->nd_repstat != 0 && error == 0)
error = nd->nd_repstat;
- if (error == NFSERR_STALECLIENTID || error == NFSERR_BADSESSION)
+ if (error == NFSERR_STALECLIENTID)
nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
nfsmout:
if (!error)
@@ -604,7 +606,7 @@
}
if (nd->nd_repstat && error == 0)
error = nd->nd_repstat;
- if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
+ if (error == NFSERR_STALESTATEID)
nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
nfsmout:
mbuf_freem(nd->nd_mrep);
@@ -762,7 +764,7 @@
if (nd->nd_repstat == 0)
NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
error = nd->nd_repstat;
- if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
+ if (error == NFSERR_STALESTATEID)
nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
nfsmout:
mbuf_freem(nd->nd_mrep);
@@ -803,7 +805,7 @@
op->nfso_stateid.other[2] = *tl;
}
error = nd->nd_repstat;
- if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
+ if (error == NFSERR_STALESTATEID)
nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
nfsmout:
mbuf_freem(nd->nd_mrep);
@@ -828,33 +830,53 @@
nfsquad_t confirm;
u_int32_t lease;
static u_int32_t rev = 0;
- struct nfsclds *dsp, *ndsp, *tdsp;
+ struct nfsclds *dsp;
struct in6_addr a6;
+ struct nfsclsession *tsep;
if (nfsboottime.tv_sec == 0)
NFSSETBOOTTIME(nfsboottime);
clp->nfsc_rev = rev++;
if (NFSHASNFSV4N(nmp)) {
+ /*
+ * Either there was no previous session or the
+ * CreateSession attempt failed, so...
+ * Do an ExchangeID followed by the CreateSession.
+ */
error = nfsrpc_exchangeid(nmp, clp, &nmp->nm_sockreq,
NFSV4EXCH_USEPNFSMDS | NFSV4EXCH_USENONPNFS, &dsp, cred, p);
NFSCL_DEBUG(1, "aft exch=%d\n", error);
- if (error == 0) {
+ if (error == 0)
error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
&nmp->nm_sockreq,
dsp->nfsclds_sess.nfsess_sequenceid, 1, cred, p);
- if (error == 0) {
- NFSLOCKMNT(nmp);
- TAILQ_FOREACH_SAFE(tdsp, &nmp->nm_sess,
- nfsclds_list, ndsp)
- nfscl_freenfsclds(tdsp);
- TAILQ_INIT(&nmp->nm_sess);
- TAILQ_INSERT_HEAD(&nmp->nm_sess, dsp,
- nfsclds_list);
- NFSUNLOCKMNT(nmp);
- } else
- nfscl_freenfsclds(dsp);
- NFSCL_DEBUG(1, "aft createsess=%d\n", error);
- }
+ if (error == 0) {
+ NFSLOCKMNT(nmp);
+ /*
+ * The old sessions cannot be safely free'd
+ * here, since they may still be used by
+ * in-progress RPCs.
+ */
+ tsep = NULL;
+ if (TAILQ_FIRST(&nmp->nm_sess) != NULL)
+ tsep = NFSMNT_MDSSESSION(nmp);
+ TAILQ_INSERT_HEAD(&nmp->nm_sess, dsp,
+ nfsclds_list);
+ /*
+ * Wake up RPCs waiting for a slot on the
+ * old session. These will then fail with
+ * NFSERR_BADSESSION and be retried with the
+ * new session by nfsv4_setsequence().
+ * Also wakeup() processes waiting for the
+ * new session.
+ */
+ if (tsep != NULL)
+ wakeup(&tsep->nfsess_slots);
+ wakeup(&nmp->nm_sess);
+ NFSUNLOCKMNT(nmp);
+ } else
+ nfscl_freenfsclds(dsp);
+ NFSCL_DEBUG(1, "aft createsess=%d\n", error);
if (error == 0 && reclaim == 0) {
error = nfsrpc_reclaimcomplete(nmp, cred, p);
NFSCL_DEBUG(1, "aft reclaimcomp=%d\n", error);
@@ -875,6 +897,7 @@
mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession", NULL, MTX_DEF);
NFSLOCKMNT(nmp);
TAILQ_INSERT_HEAD(&nmp->nm_sess, dsp, nfsclds_list);
+ tsep = NFSMNT_MDSSESSION(nmp);
NFSUNLOCKMNT(nmp);
nfscl_reqstart(nd, NFSPROC_SETCLIENTID, nmp, NULL, 0, NULL, NULL);
@@ -936,8 +959,8 @@
return (error);
if (nd->nd_repstat == 0) {
NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0] = *tl++;
- NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1] = *tl++;
+ tsep->nfsess_clientid.lval[0] = *tl++;
+ tsep->nfsess_clientid.lval[1] = *tl++;
confirm.lval[0] = *tl++;
confirm.lval[1] = *tl;
mbuf_freem(nd->nd_mrep);
@@ -949,8 +972,8 @@
nfscl_reqstart(nd, NFSPROC_SETCLIENTIDCFRM, nmp, NULL, 0, NULL,
NULL);
NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
- *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
+ *tl++ = tsep->nfsess_clientid.lval[0];
+ *tl++ = tsep->nfsess_clientid.lval[1];
*tl++ = confirm.lval[0];
*tl = confirm.lval[1];
nd->nd_flag |= ND_USEGSSNAME;
@@ -1111,7 +1134,7 @@
else
error = nfsrpc_setaclrpc(vp, cred, p, aclp, &stateid,
stuff);
- if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
+ if (error == NFSERR_STALESTATEID)
nfscl_initiate_recovery(nmp->nm_clp);
if (lckp != NULL)
nfscl_lockderef(lckp);
@@ -1368,7 +1391,7 @@
&lckp);
error = nfsrpc_readrpc(vp, uiop, newcred, &stateid, p, nap,
attrflagp, stuff);
- if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
+ if (error == NFSERR_STALESTATEID)
nfscl_initiate_recovery(nmp->nm_clp);
if (lckp != NULL)
nfscl_lockderef(lckp);
@@ -1538,7 +1561,7 @@
else
error = nfsrpc_writerpc(vp, uiop, iomode, must_commit,
newcred, &stateid, p, nap, attrflagp, stuff);
- if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
+ if (error == NFSERR_STALESTATEID)
nfscl_initiate_recovery(nmp->nm_clp);
if (lckp != NULL)
nfscl_lockderef(lckp);
@@ -1964,6 +1987,7 @@
nfsv4stateid_t stateid;
u_int32_t rflags;
struct nfsmount *nmp;
+ struct nfsclsession *tsep;
nmp = VFSTONFS(dvp->v_mount);
np = VTONFS(dvp);
@@ -1983,8 +2007,9 @@
*tl++ = txdr_unsigned(NFSV4OPEN_ACCESSWRITE |
NFSV4OPEN_ACCESSREAD);
*tl++ = txdr_unsigned(NFSV4OPEN_DENYNONE);
- *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
- *tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
+ tsep = nfsmnt_mdssession(nmp);
+ *tl++ = tsep->nfsess_clientid.lval[0];
+ *tl = tsep->nfsess_clientid.lval[1];
(void) nfsm_strtom(nd, owp->nfsow_owner, NFSV4CL_LOCKNAMELEN);
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(NFSV4OPEN_CREATE);
@@ -2178,7 +2203,7 @@
}
if (nd->nd_repstat != 0 && error == 0)
error = nd->nd_repstat;
- if (error == NFSERR_STALECLIENTID || error == NFSERR_BADSESSION)
+ if (error == NFSERR_STALECLIENTID)
nfscl_initiate_recovery(owp->nfsow_clp);
nfsmout:
if (!error)
@@ -3840,6 +3865,7 @@
uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
struct nfsnode *np;
struct nfsmount *nmp;
+ struct nfsclsession *tsep;
nmp = VFSTONFS(vp->v_mount);
NFSCL_REQSTART(nd, NFSPROC_LOCKT, vp);
@@ -3852,8 +3878,9 @@
tl += 2;
txdr_hyper(len, tl);
tl += 2;
- *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
- *tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
+ tsep = nfsmnt_mdssession(nmp);
+ *tl++ = tsep->nfsess_clientid.lval[0];
+ *tl = tsep->nfsess_clientid.lval[1];
nfscl_filllockowner(id, own, flags);
np = VTONFS(vp);
NFSBCOPY(np->n_fhp->nfh_fh, &own[NFSV4CL_LOCKNAMELEN],
@@ -3893,8 +3920,7 @@
error = EBADRPC;
if (!error)
error = nfsm_advance(nd, NFSM_RNDUP(size), -1);
- } else if (nd->nd_repstat == NFSERR_STALECLIENTID ||
- nd->nd_repstat == NFSERR_BADSESSION)
+ } else if (nd->nd_repstat == NFSERR_STALECLIENTID)
nfscl_initiate_recovery(clp);
nfsmout:
mbuf_freem(nd->nd_mrep);
@@ -3944,8 +3970,7 @@
lp->nfsl_stateid.other[0] = *tl++;
lp->nfsl_stateid.other[1] = *tl++;
lp->nfsl_stateid.other[2] = *tl;
- } else if (nd->nd_repstat == NFSERR_STALESTATEID ||
- nd->nd_repstat == NFSERR_BADSESSION)
+ } else if (nd->nd_repstat == NFSERR_STALESTATEID)
nfscl_initiate_recovery(lp->nfsl_open->nfso_own->nfsow_clp);
nfsmout:
mbuf_freem(nd->nd_mrep);
@@ -3964,6 +3989,7 @@
u_int32_t *tl;
int error, size;
uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
+ struct nfsclsession *tsep;
nfscl_reqstart(nd, NFSPROC_LOCK, nmp, nfhp, fhlen, NULL, NULL);
NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
@@ -3989,8 +4015,9 @@
*tl++ = lp->nfsl_open->nfso_stateid.other[1];
*tl++ = lp->nfsl_open->nfso_stateid.other[2];
*tl++ = txdr_unsigned(lp->nfsl_seqid);
- *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
- *tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
+ tsep = nfsmnt_mdssession(nmp);
+ *tl++ = tsep->nfsess_clientid.lval[0];
+ *tl = tsep->nfsess_clientid.lval[1];
NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
NFSBCOPY(nfhp, &own[NFSV4CL_LOCKNAMELEN], fhlen);
(void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + fhlen);
@@ -4031,8 +4058,7 @@
error = EBADRPC;
if (!error)
error = nfsm_advance(nd, NFSM_RNDUP(size), -1);
- } else if (nd->nd_repstat == NFSERR_STALESTATEID ||
- nd->nd_repstat == NFSERR_BADSESSION)
+ } else if (nd->nd_repstat == NFSERR_STALESTATEID)
nfscl_initiate_recovery(lp->nfsl_open->nfso_own->nfsow_clp);
nfsmout:
mbuf_freem(nd->nd_mrep);
@@ -4232,25 +4258,36 @@
struct nfsmount *nmp;
int error;
struct nfssockreq *nrp;
+ struct nfsclsession *tsep;
nmp = clp->nfsc_nmp;
if (nmp == NULL)
return (0);
- nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL,
- &dsp->nfsclds_sess);
+ if (dsp == NULL)
+ nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL, NULL);
+ else
+ nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL,
+ &dsp->nfsclds_sess);
if (!NFSHASNFSV4N(nmp)) {
/* NFSv4.1 just uses a Sequence Op and not a Renew. */
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
- *tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
- }
- nrp = dsp->nfsclds_sockp;
+ tsep = nfsmnt_mdssession(nmp);
+ *tl++ = tsep->nfsess_clientid.lval[0];
+ *tl = tsep->nfsess_clientid.lval[1];
+ }
+ nrp = NULL;
+ if (dsp != NULL)
+ nrp = dsp->nfsclds_sockp;
if (nrp == NULL)
/* If NULL, use the MDS socket. */
nrp = &nmp->nm_sockreq;
nd->nd_flag |= ND_USEGSSNAME;
- error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
- NFS_PROG, NFS_VER4, NULL, 1, NULL, &dsp->nfsclds_sess);
+ if (dsp == NULL)
+ error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
+ NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
+ else
+ error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
+ NFS_PROG, NFS_VER4, NULL, 1, NULL, &dsp->nfsclds_sess);
if (error)
return (error);
error = nd->nd_repstat;
@@ -4269,6 +4306,7 @@
u_int32_t *tl;
int error;
uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
+ struct nfsclsession *tsep;
if (NFSHASNFSV4N(nmp)) {
/* For NFSv4.1, do a FreeStateID. */
@@ -4279,8 +4317,9 @@
nfscl_reqstart(nd, NFSPROC_RELEASELCKOWN, nmp, NULL, 0, NULL,
NULL);
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
- *tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
+ tsep = nfsmnt_mdssession(nmp);
+ *tl++ = tsep->nfsess_clientid.lval[0];
+ *tl = tsep->nfsess_clientid.lval[1];
NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
NFSBCOPY(fh, &own[NFSV4CL_LOCKNAMELEN], fhlen);
(void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + fhlen);
@@ -4518,7 +4557,7 @@
error = NFSERR_BADXDR;
goto nfsmout;
}
- dsp = malloc(sizeof(struct nfsclds) + len, M_NFSCLDS,
+ dsp = malloc(sizeof(struct nfsclds) + len + 1, M_NFSCLDS,
M_WAITOK | M_ZERO);
dsp->nfsclds_expire = NFSD_MONOSEC + clp->nfsc_renew;
dsp->nfsclds_servownlen = len;
@@ -4661,10 +4700,12 @@
struct nfsrv_descript nfsd;
struct nfsrv_descript *nd = &nfsd;
int error;
+ struct nfsclsession *tsep;
nfscl_reqstart(nd, NFSPROC_DESTROYSESSION, nmp, NULL, 0, NULL, NULL);
NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
- bcopy(NFSMNT_MDSSESSION(nmp)->nfsess_sessionid, tl, NFSX_V4SESSIONID);
+ tsep = nfsmnt_mdssession(nmp);
+ bcopy(tsep->nfsess_sessionid, tl, NFSX_V4SESSIONID);
nd->nd_flag |= ND_USEGSSNAME;
error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
@@ -4686,11 +4727,13 @@
struct nfsrv_descript nfsd;
struct nfsrv_descript *nd = &nfsd;
int error;
+ struct nfsclsession *tsep;
nfscl_reqstart(nd, NFSPROC_DESTROYCLIENT, nmp, NULL, 0, NULL, NULL);
NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[0];
- *tl = NFSMNT_MDSSESSION(nmp)->nfsess_clientid.lval[1];
+ tsep = nfsmnt_mdssession(nmp);
+ *tl++ = tsep->nfsess_clientid.lval[0];
+ *tl = tsep->nfsess_clientid.lval[1];
nd->nd_flag |= ND_USEGSSNAME;
error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
@@ -5158,6 +5201,7 @@
struct nfsclflayouthead flh;
int error = 0, islocked, layoutlen, recalled, retonclose;
nfsv4stateid_t stateid;
+ struct nfsclsession *tsep;
*lypp = NULL;
/*
@@ -5172,7 +5216,8 @@
if (recalled != 0)
return (EIO);
LIST_INIT(&flh);
- layoutlen = NFSMNT_MDSSESSION(nmp)->nfsess_maxcache -
+ tsep = nfsmnt_mdssession(nmp);
+ layoutlen = tsep->nfsess_maxcache -
(NFSX_STATEID + 3 * NFSX_UNSIGNED);
if (lyp == NULL) {
stateid.seqid = 0;
@@ -5269,7 +5314,8 @@
if (msad != NULL && msad->sin_family == AF_INET &&
ssd->sin_addr.s_addr == msad->sin_addr.s_addr &&
ssd->sin_port == msad->sin_port &&
- (tdsp->nfsclds_flags & NFSCLDS_DS) != 0) {
+ (tdsp->nfsclds_flags & NFSCLDS_DS) != 0 &&
+ tdsp->nfsclds_sess.nfsess_defunct == 0) {
*dspp = tdsp;
NFSUNLOCKMNT(nmp);
NFSCL_DEBUG(4, "fnd same addr\n");
@@ -5309,7 +5355,8 @@
IN6_ARE_ADDR_EQUAL(&ssd6->sin6_addr,
&msad6->sin6_addr) &&
ssd6->sin6_port == msad6->sin6_port &&
- (tdsp->nfsclds_flags & NFSCLDS_DS) != 0) {
+ (tdsp->nfsclds_flags & NFSCLDS_DS) != 0 &&
+ tdsp->nfsclds_sess.nfsess_defunct == 0) {
*dspp = tdsp;
NFSUNLOCKMNT(nmp);
return (0);
@@ -5862,7 +5909,8 @@
if (dsp->nfsclds_servownlen == newdsp->nfsclds_servownlen &&
dsp->nfsclds_servownlen != 0 &&
!NFSBCMP(dsp->nfsclds_serverown, newdsp->nfsclds_serverown,
- dsp->nfsclds_servownlen)) {
+ dsp->nfsclds_servownlen) &&
+ dsp->nfsclds_sess.nfsess_defunct == 0) {
NFSCL_DEBUG(4, "fnd same fdsp=%p dsp=%p flg=0x%x\n",
TAILQ_FIRST(&nmp->nm_sess), dsp,
dsp->nfsclds_flags);
Index: fs/nfsclient/nfs_clstate.c
===================================================================
--- fs/nfsclient/nfs_clstate.c
+++ fs/nfsclient/nfs_clstate.c
@@ -2470,8 +2470,11 @@
if (recover_done_time < NFSD_MONOSEC) {
recover_done_time = NFSD_MONOSEC +
clp->nfsc_renew;
+ NFSCL_DEBUG(1, "Doing recovery..\n");
nfscl_recover(clp, cred, p);
} else {
+ NFSCL_DEBUG(1, "Clear Recovery dt=%u ms=%jd\n",
+ recover_done_time, (intmax_t)NFSD_MONOSEC);
NFSLOCKCLSTATE();
clp->nfsc_flags &= ~NFSCLFLAGS_RECOVER;
NFSUNLOCKCLSTATE();
@@ -2481,8 +2484,7 @@
(clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID)) {
clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
clidrev = clp->nfsc_clientidrev;
- error = nfsrpc_renew(clp,
- TAILQ_FIRST(&clp->nfsc_nmp->nm_sess), cred, p);
+ error = nfsrpc_renew(clp, NULL, cred, p);
if (error == NFSERR_CBPATHDOWN)
cbpathdown = 1;
else if (error == NFSERR_STALECLIENTID ||
@@ -2494,24 +2496,27 @@
(void) nfscl_hasexpired(clp, clidrev, p);
}
- /* Do renews for any DS sessions. */
checkdsrenew:
- NFSLOCKMNT(clp->nfsc_nmp);
- /* Skip first entry, since the MDS is handled above. */
- dsp = TAILQ_FIRST(&clp->nfsc_nmp->nm_sess);
- if (dsp != NULL)
- dsp = TAILQ_NEXT(dsp, nfsclds_list);
- while (dsp != NULL) {
- if (dsp->nfsclds_expire <= NFSD_MONOSEC) {
- dsp->nfsclds_expire = NFSD_MONOSEC +
- clp->nfsc_renew;
- NFSUNLOCKMNT(clp->nfsc_nmp);
- (void)nfsrpc_renew(clp, dsp, cred, p);
- goto checkdsrenew;
+ if (NFSHASNFSV4N(clp->nfsc_nmp)) {
+ /* Do renews for any DS sessions. */
+ NFSLOCKMNT(clp->nfsc_nmp);
+ /* Skip first entry, since the MDS is handled above. */
+ dsp = TAILQ_FIRST(&clp->nfsc_nmp->nm_sess);
+ if (dsp != NULL)
+ dsp = TAILQ_NEXT(dsp, nfsclds_list);
+ while (dsp != NULL) {
+ if (dsp->nfsclds_expire <= NFSD_MONOSEC &&
+ dsp->nfsclds_sess.nfsess_defunct == 0) {
+ dsp->nfsclds_expire = NFSD_MONOSEC +
+ clp->nfsc_renew;
+ NFSUNLOCKMNT(clp->nfsc_nmp);
+ (void)nfsrpc_renew(clp, dsp, cred, p);
+ goto checkdsrenew;
+ }
+ dsp = TAILQ_NEXT(dsp, nfsclds_list);
}
- dsp = TAILQ_NEXT(dsp, nfsclds_list);
+ NFSUNLOCKMNT(clp->nfsc_nmp);
}
- NFSUNLOCKMNT(clp->nfsc_nmp);
TAILQ_INIT(&dh);
NFSLOCKCLSTATE();
@@ -3163,6 +3168,7 @@
int changed, gotone, laytype, recalltype;
uint32_t iomode;
struct nfsclrecalllayout *recallp = NULL;
+ struct nfsclsession *tsep;
gotseq_ok = 0;
nfsrvd_rephead(nd);
@@ -3472,13 +3478,12 @@
error = NFSERR_SERVERFAULT;
} else
error = NFSERR_SEQUENCEPOS;
- if (error == 0)
+ if (error == 0) {
+ tsep = nfsmnt_mdssession(clp->nfsc_nmp);
error = nfsv4_seqsession(seqid, slotid,
- highslot,
- NFSMNT_MDSSESSION(clp->nfsc_nmp)->
- nfsess_cbslots, &rep,
- NFSMNT_MDSSESSION(clp->nfsc_nmp)->
- nfsess_backslots);
+ highslot, tsep->nfsess_cbslots, &rep,
+ tsep->nfsess_backslots);
+ }
NFSUNLOCKCLSTATE();
if (error == 0) {
gotseq_ok = 1;
@@ -3546,8 +3551,8 @@
NFSLOCKCLSTATE();
clp = nfscl_getclntsess(sessionid);
if (clp != NULL) {
- nfsv4_seqsess_cacherep(slotid,
- NFSMNT_MDSSESSION(clp->nfsc_nmp)->nfsess_cbslots,
+ tsep = nfsmnt_mdssession(clp->nfsc_nmp);
+ nfsv4_seqsess_cacherep(slotid, tsep->nfsess_cbslots,
NFSERR_OK, &rep);
NFSUNLOCKCLSTATE();
} else {
@@ -3603,15 +3608,17 @@
struct nfsclclient *clp;
mount_t mp;
int error;
+ struct nfsclsession *tsep;
*clpp = NULL;
NFSLOCKCLSTATE();
LIST_FOREACH(clp, &nfsclhead, nfsc_list) {
+ tsep = nfsmnt_mdssession(clp->nfsc_nmp);
if (minorvers == NFSV4_MINORVERSION) {
if (clp->nfsc_cbident == cbident)
break;
- } else if (!NFSBCMP(NFSMNT_MDSSESSION(clp->nfsc_nmp)->
- nfsess_sessionid, sessionid, NFSX_V4SESSIONID))
+ } else if (!NFSBCMP(tsep->nfsess_sessionid, sessionid,
+ NFSX_V4SESSIONID))
break;
}
if (clp == NULL) {
@@ -3650,11 +3657,14 @@
nfscl_getclntsess(uint8_t *sessionid)
{
struct nfsclclient *clp;
+ struct nfsclsession *tsep;
- LIST_FOREACH(clp, &nfsclhead, nfsc_list)
- if (!NFSBCMP(NFSMNT_MDSSESSION(clp->nfsc_nmp)->nfsess_sessionid,
- sessionid, NFSX_V4SESSIONID))
+ LIST_FOREACH(clp, &nfsclhead, nfsc_list) {
+ tsep = nfsmnt_mdssession(clp->nfsc_nmp);
+ if (!NFSBCMP(tsep->nfsess_sessionid, sessionid,
+ NFSX_V4SESSIONID))
break;
+ }
return (clp);
}
Index: fs/nfsclient/nfs_clvfsops.c
===================================================================
--- fs/nfsclient/nfs_clvfsops.c
+++ fs/nfsclient/nfs_clvfsops.c
@@ -1383,6 +1383,7 @@
krbnamelen + dirlen + srvkrbnamelen + 2,
M_NEWNFSMNT, M_WAITOK | M_ZERO);
TAILQ_INIT(&nmp->nm_bufq);
+ TAILQ_INIT(&nmp->nm_sess);
if (clval == 0)
clval = (u_int64_t)nfsboottime.tv_sec;
nmp->nm_clval = clval++;
Index: fs/nfsclient/nfsmount.h
===================================================================
--- fs/nfsclient/nfsmount.h
+++ fs/nfsclient/nfsmount.h
@@ -112,9 +112,22 @@
/*
* Get a pointer to the MDS session, which is always the first element
* in the list.
+ * This macro can only be safely used when the NFSLOCKMNT() lock is held.
+ * The inline function can be used when the lock isn't held.
*/
#define NFSMNT_MDSSESSION(m) (&(TAILQ_FIRST(&((m)->nm_sess))->nfsclds_sess))
+static __inline struct nfsclsession *
+nfsmnt_mdssession(struct nfsmount *nmp)
+{
+ struct nfsclsession *tsep;
+
+ mtx_lock(&nmp->nm_mtx);
+ tsep = NFSMNT_MDSSESSION(nmp);
+ mtx_unlock(&nmp->nm_mtx);
+ return (tsep);
+}
+
#ifndef NFS_DEFAULT_NAMETIMEO
#define NFS_DEFAULT_NAMETIMEO 60
#endif

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 21, 6:16 AM (6 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30066042
Default Alt Text
D8745.id22794.diff (37 KB)

Event Timeline