Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148792892
D8745.id22794.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
37 KB
Referenced Files
None
Subscribers
None
D8745.id22794.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D8745: Fix the NFSv4.1 client for recovery from NFS4ERR_BAD_SESSION server failures
Attached
Detach File
Event Timeline
Log In to Comment