Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 Jan 2012 01:01:42 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r230713 - in projects/nfsv4.1-client/sys/fs: nfs nfsclient
Message-ID:  <201201290101.q0T11g2f009016@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sun Jan 29 01:01:41 2012
New Revision: 230713
URL: http://svn.freebsd.org/changeset/base/230713

Log:
  Try and fix the NFSv4.1 client so that it performs server crash
  recovery correctly. Mainly required the addition of NFSERR_BADSESSION
  to the NFSv4.0 errors (NFSERR_STALECLIENTID, NFSERR_STALESTATEID)
  that indicate recovery is required. Also needed to re-initialize
  the session slot fields and an extra argument to nfsrpc_setclient(),
  so that it doesn't do a RECLAIM_COMPLETE for the recovery case.
  Tested minimally against the Linux NFSv4.1 server.

Modified:
  projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c
  projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h
  projects/nfsv4.1-client/sys/fs/nfs/nfsproto.h
  projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clport.c
  projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c
  projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c	Sun Jan 29 01:01:35 2012	(r230712)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_commonkrpc.c	Sun Jan 29 01:01:41 2012	(r230713)
@@ -975,6 +975,7 @@ if (j >= 10000) printf("n2op=%d n2st=%d\
 			 * reply, so that recovery isn't initiated.
 			 */
 			if ((nd->nd_repstat == NFSERR_STALECLIENTID ||
+			     nd->nd_repstat == NFSERR_BADSESSION ||
 			     nd->nd_repstat == NFSERR_STALESTATEID) &&
 			    rep != NULL && (rep->r_flags & R_DONTRECOVER))
 				nd->nd_repstat = NFSERR_STALEDONTRECOVER;

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Sun Jan 29 01:01:35 2012	(r230712)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfs_var.h	Sun Jan 29 01:01:41 2012	(r230713)
@@ -367,7 +367,7 @@ int nfsrpc_closerpc(struct nfsrv_descrip
     struct nfsclopen *, struct ucred *, NFSPROC_T *, int);
 int nfsrpc_openconfirm(vnode_t, u_int8_t *, int, struct nfsclopen *,
     struct ucred *, NFSPROC_T *);
-int nfsrpc_setclient(struct nfsmount *, struct nfsclclient *,
+int nfsrpc_setclient(struct nfsmount *, struct nfsclclient *, int,
     struct ucred *, NFSPROC_T *);
 int nfsrpc_getattr(vnode_t, struct ucred *, NFSPROC_T *,
     struct nfsvattr *, void *);

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsproto.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsproto.h	Sun Jan 29 01:01:35 2012	(r230712)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsproto.h	Sun Jan 29 01:01:41 2012	(r230713)
@@ -148,7 +148,9 @@
 #define	NFSERR_CBPATHDOWN	10048
 
 /* NFSv4.1 specific errors. */
+#define	NFSERR_BADSESSION	10052
 #define	NFSERR_BADSLOT		10053
+#define	NFSERR_COMPLETEALREADY	10054
 #define	NFSERR_LAYOUTTRYLATER	10058
 #define	NFSERR_SEQMISORDERED	10063
 #define	NFSERR_SEQUENCEPOS	10064

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clport.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clport.c	Sun Jan 29 01:01:35 2012	(r230712)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clport.c	Sun Jan 29 01:01:41 2012	(r230713)
@@ -1119,6 +1119,7 @@ nfscl_maperr(struct thread *td, int erro
 	case NFSERR_STALESTATEID:
 	case NFSERR_EXPIRED:
 	case NFSERR_BADSTATEID:
+	case NFSERR_BADSESSION:
 		printf("nfsv4 recover err returned %d\n", error);
 		return (EIO);
 	case NFSERR_BADHANDLE:

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Sun Jan 29 01:01:35 2012	(r230712)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Sun Jan 29 01:01:41 2012	(r230713)
@@ -89,6 +89,7 @@ static int nfsrpc_getlayout(struct nfsmo
     nfsv4stateid_t *, struct ucred *, NFSPROC_T *);
 static int nfsrpc_fillsa(struct nfsmount *, struct nfsclds *,
     struct sockaddr_storage *, NFSPROC_T *);
+static void nfscl_initsessionslots(struct nfsclsession *);
 
 /*
  * nfs null call from vfs.
@@ -326,7 +327,8 @@ else printf(" fhl=0\n");
 		op->nfso_opencnt++;
 	    nfscl_openrelease(op, error, newone);
 	    if (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
-		error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY) {
+		error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+		error == NFSERR_BADSESSION) {
 		(void) nfs_catnap(PZERO, error, "nfs_open");
 	    } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID)
 		&& clidrev != 0) {
@@ -335,6 +337,7 @@ else printf(" fhl=0\n");
 	    }
 	} while (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+	    error == NFSERR_BADSESSION ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
 	if (error && retrycnt >= 4)
@@ -519,14 +522,15 @@ nfsrpc_openrpc(struct nfsmount *nmp, vno
 			if (ndp != NULL)
 				FREE((caddr_t)ndp, M_NFSCLDELEG);
 			if (ret == NFSERR_STALECLIENTID ||
-			    ret == NFSERR_STALEDONTRECOVER)
+			    ret == NFSERR_STALEDONTRECOVER ||
+			    ret == NFSERR_BADSESSION)
 				error = ret;
 		    }
 		}
 	}
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
-	if (error == NFSERR_STALECLIENTID)
+	if (error == NFSERR_STALECLIENTID || error == NFSERR_BADSESSION)
 		nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
 nfsmout:
 	if (!error)
@@ -570,7 +574,7 @@ nfsrpc_opendowngrade(vnode_t vp, u_int32
 	}
 	if (nd->nd_repstat && error == 0)
 		error = nd->nd_repstat;
-	if (error == NFSERR_STALESTATEID)
+	if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
 		nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
 nfsmout:
 	mbuf_freem(nd->nd_mrep);
@@ -725,7 +729,7 @@ nfsrpc_closerpc(struct nfsrv_descript *n
 	if (nd->nd_repstat == 0)
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 	error = nd->nd_repstat;
-	if (error == NFSERR_STALESTATEID)
+	if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
 		nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
 nfsmout:
 	mbuf_freem(nd->nd_mrep);
@@ -766,7 +770,7 @@ nfsrpc_openconfirm(vnode_t vp, u_int8_t 
 		op->nfso_stateid.other[2] = *tl;
 	}
 	error = nd->nd_repstat;
-	if (error == NFSERR_STALESTATEID)
+	if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
 		nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
 nfsmout:
 	mbuf_freem(nd->nd_mrep);
@@ -778,7 +782,7 @@ nfsmout:
  * when a mount has just occurred and when the server replies NFSERR_EXPIRED.
  */
 APPLESTATIC int
-nfsrpc_setclient(struct nfsmount *nmp, struct nfsclclient *clp,
+nfsrpc_setclient(struct nfsmount *nmp, struct nfsclclient *clp, int reclaim,
     struct ucred *cred, NFSPROC_T *p)
 {
 	u_int32_t *tl;
@@ -799,13 +803,19 @@ nfsrpc_setclient(struct nfsmount *nmp, s
 		error = nfsrpc_exchangeid(nmp, clp, &nmp->nm_sess,
 		    NFSV4EXCH_USEPNFSMDS | NFSV4EXCH_USENONPNFS, cred, p);
 if (error) printf("exch=%d\n",error);
-		if (error == 0)
+		if (error == 0) {
+			nfscl_initsessionslots(&nmp->nm_sess);
 			error = nfsrpc_createsession(nmp, &nmp->nm_sess, cred,
 			    p);
 if (error) printf("aft crs=%d\n",error);
-		if (error == 0)
+		}
+		if (error == 0 && reclaim == 0) {
 			error = nfsrpc_reclaimcomplete(nmp, cred, p);
 if (error) printf("aft reclcom=%d\n",error);
+			if (error == NFSERR_COMPLETEALREADY)
+				/* Ignore this error. */
+				error = 0;
+		}
 		return (error);
 	}
 	nfscl_reqstart(nd, NFSPROC_SETCLIENTID, nmp, NULL, 0, NULL, NULL);
@@ -1042,7 +1052,7 @@ nfsrpc_setattr(vnode_t vp, struct vattr 
 		else
 			error = nfsrpc_setaclrpc(vp, cred, p, aclp, &stateid,
 			    stuff);
-		if (error == NFSERR_STALESTATEID)
+		if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (lckp != NULL)
 			nfscl_lockderef(lckp);
@@ -1050,7 +1060,7 @@ nfsrpc_setattr(vnode_t vp, struct vattr 
 			(void) nfsrpc_close(vp, 0, p);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
-		    error == NFSERR_OLDSTATEID) {
+		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_setattr");
 		} else if ((error == NFSERR_EXPIRED ||
 		    error == NFSERR_BADSTATEID) && clidrev != 0) {
@@ -1059,6 +1069,7 @@ nfsrpc_setattr(vnode_t vp, struct vattr 
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+	    error == NFSERR_BADSESSION ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
@@ -1288,13 +1299,13 @@ nfsrpc_read(vnode_t vp, struct uio *uiop
 			    NFSV4OPEN_ACCESSREAD, newcred, p, &stateid, &lckp);
 		error = nfsrpc_readrpc(vp, uiop, newcred, &stateid, p, nap,
 		    attrflagp, stuff);
-		if (error == NFSERR_STALESTATEID)
+		if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (lckp != NULL)
 			nfscl_lockderef(lckp);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
-		    error == NFSERR_OLDSTATEID) {
+		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_read");
 		} else if ((error == NFSERR_EXPIRED ||
 		    error == NFSERR_BADSTATEID) && clidrev != 0) {
@@ -1303,6 +1314,7 @@ nfsrpc_read(vnode_t vp, struct uio *uiop
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+	    error == NFSERR_BADSESSION ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
@@ -1456,13 +1468,13 @@ nfsrpc_write(vnode_t vp, struct uio *uio
 		else
 			error = nfsrpc_writerpc(vp, uiop, iomode, must_commit,
 			    newcred, &stateid, p, nap, attrflagp, stuff);
-		if (error == NFSERR_STALESTATEID)
+		if (error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (lckp != NULL)
 			nfscl_lockderef(lckp);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
-		    error == NFSERR_OLDSTATEID) {
+		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_write");
 		} else if ((error == NFSERR_EXPIRED ||
 		    error == NFSERR_BADSTATEID) && clidrev != 0) {
@@ -1470,13 +1482,13 @@ nfsrpc_write(vnode_t vp, struct uio *uio
 		}
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_DELAY ||
-	    ((error == NFSERR_STALESTATEID ||
+	    ((error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION ||
 	      error == NFSERR_STALEDONTRECOVER) && called_from_strategy == 0) ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
 	if (error != 0 && (retrycnt >= 4 ||
-	    ((error == NFSERR_STALESTATEID ||
+	    ((error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION ||
 	      error == NFSERR_STALEDONTRECOVER) && called_from_strategy != 0)))
 		error = EIO;
 	if (NFSHASNFSV4(nmp))
@@ -1790,7 +1802,8 @@ nfsrpc_create(vnode_t dvp, char *name, i
 			    (*nfhpp)->nfh_fh, (*nfhpp)->nfh_len, cred, p, &dp);
 		nfscl_ownerrelease(owp, error, newone, unlocked);
 		if (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
-		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY) {
+		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+		    error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_open");
 		} else if ((error == NFSERR_EXPIRED ||
 		    error == NFSERR_BADSTATEID) && clidrev != 0) {
@@ -1799,6 +1812,7 @@ nfsrpc_create(vnode_t dvp, char *name, i
 		}
 	    } while (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
 		error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
+		error == NFSERR_BADSESSION ||
 		((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 		 expireret == 0 && clidrev != 0 && retrycnt < 4));
 	    if (error && retrycnt >= 4)
@@ -2054,7 +2068,8 @@ nfsrpc_createv4(vnode_t dvp, char *name,
 			if (dp != NULL)
 				FREE((caddr_t)dp, M_NFSCLDELEG);
 			if (ret == NFSERR_STALECLIENTID ||
-			    ret == NFSERR_STALEDONTRECOVER)
+			    ret == NFSERR_STALEDONTRECOVER ||
+			    ret == NFSERR_BADSESSION)
 				error = ret;
 		    }
 		}
@@ -2063,7 +2078,7 @@ nfsrpc_createv4(vnode_t dvp, char *name,
 	}
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
-	if (error == NFSERR_STALECLIENTID)
+	if (error == NFSERR_STALECLIENTID || error == NFSERR_BADSESSION)
 		nfscl_initiate_recovery(owp->nfsow_clp);
 nfsmout:
 	if (!error)
@@ -3646,7 +3661,8 @@ nfsrpc_advlock(vnode_t vp, off_t size, i
 	        error = nd->nd_repstat;
 	    if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		error == NFSERR_STALEDONTRECOVER ||
-		error == NFSERR_STALECLIENTID || error == NFSERR_DELAY) {
+		error == NFSERR_STALECLIENTID || error == NFSERR_DELAY ||
+		error == NFSERR_BADSESSION) {
 		(void) nfs_catnap(PZERO, error, "nfs_advlock");
 	    } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID)
 		&& clidrev != 0) {
@@ -3656,6 +3672,7 @@ nfsrpc_advlock(vnode_t vp, off_t size, i
 	} while (error == NFSERR_GRACE ||
 	    error == NFSERR_STALECLIENTID || error == NFSERR_DELAY ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_STALESTATEID ||
+	    error == NFSERR_BADSESSION ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
 	if (error && retrycnt >= 4)
@@ -3729,7 +3746,8 @@ nfsrpc_lockt(struct nfsrv_descript *nd, 
 			error = EBADRPC;
 		if (!error)
 			error = nfsm_advance(nd, NFSM_RNDUP(size), -1);
-	} else if (nd->nd_repstat == NFSERR_STALECLIENTID)
+	} else if (nd->nd_repstat == NFSERR_STALECLIENTID ||
+	    nd->nd_repstat == NFSERR_BADSESSION)
 		nfscl_initiate_recovery(clp);
 nfsmout:
 	mbuf_freem(nd->nd_mrep);
@@ -3776,7 +3794,8 @@ nfsrpc_locku(struct nfsrv_descript *nd, 
 		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)
+	} else if (nd->nd_repstat == NFSERR_STALESTATEID ||
+	    nd->nd_repstat == NFSERR_BADSESSION)
 		nfscl_initiate_recovery(lp->nfsl_open->nfso_own->nfsow_clp);
 nfsmout:
 	mbuf_freem(nd->nd_mrep);
@@ -3856,7 +3875,8 @@ nfsrpc_lock(struct nfsrv_descript *nd, s
 			error = EBADRPC;
 		if (!error)
 			error = nfsm_advance(nd, NFSM_RNDUP(size), -1);
-	} else if (nd->nd_repstat == NFSERR_STALESTATEID)
+	} else if (nd->nd_repstat == NFSERR_STALESTATEID ||
+	    nd->nd_repstat == NFSERR_BADSESSION)
 		nfscl_initiate_recovery(lp->nfsl_open->nfso_own->nfsow_clp);
 nfsmout:
 	mbuf_freem(nd->nd_mrep);
@@ -5013,9 +5033,11 @@ nfsrpc_fillsa(struct nfsmount *nmp, stru
 	if (error == 0)
 		error = nfsrpc_exchangeid(nmp, clp, &dsp->nfsclds_sess,
 		    NFSV4EXCH_USEPNFSDS, dsp->nfsclds_sock.nr_cred, p);
-	if (error == 0)
+	if (error == 0) {
+		nfscl_initsessionslots(&dsp->nfsclds_sess);
 		error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
 		    dsp->nfsclds_sock.nr_cred, p);
+	}
 	if (error != 0) {
 		NFSFREECRED(dsp->nfsclds_sock.nr_cred);
 		free(dsp->nfsclds_sock.nr_nam, M_SONAME);
@@ -5048,3 +5070,21 @@ nfsrpc_reclaimcomplete(struct nfsmount *
 	return (error);
 }
 
+/*
+ * Initialize the slot tables for a session.
+ */
+static void
+nfscl_initsessionslots(struct nfsclsession *sep)
+{
+	int i;
+
+	for (i = 0; i < NFSV4_CBSLOTS; i++) {
+		if (sep->nfsess_cbslots[i].nfssl_reply != NULL)
+			m_freem(sep->nfsess_cbslots[i].nfssl_reply);
+		NFSBZERO(&sep->nfsess_cbslots[i], sizeof(struct nfsslot));
+	}
+	for (i = 0; i < 64; i++)
+		sep->nfsess_slotseq[i] = 0;
+	sep->nfsess_slots = 0;
+}
+

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c	Sun Jan 29 01:01:35 2012	(r230712)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clstate.c	Sun Jan 29 01:01:41 2012	(r230713)
@@ -830,13 +830,15 @@ nfscl_getcl(struct mount *mp, struct ucr
 			clidinusedelay = 120;
 		trystalecnt = 3;
 		do {
-			error = nfsrpc_setclient(nmp, clp, cred, p);
+			error = nfsrpc_setclient(nmp, clp, 0, cred, p);
 			if (error == NFSERR_STALECLIENTID ||
 			    error == NFSERR_STALEDONTRECOVER ||
+			    error == NFSERR_BADSESSION ||
 			    error == NFSERR_CLIDINUSE) {
 				(void) nfs_catnap(PZERO, error, "nfs_setcl");
 			}
 		} while (((error == NFSERR_STALECLIENTID ||
+		     error == NFSERR_BADSESSION ||
 		     error == NFSERR_STALEDONTRECOVER) && --trystalecnt > 0) ||
 		    (error == NFSERR_CLIDINUSE && --clidinusedelay > 0));
 		if (error) {
@@ -1840,7 +1842,7 @@ nfscl_umount(struct nfsmount *nmp, NFSPR
 			(void)nfsrpc_destroysession(nmp, clp, cred, p);
 			(void)nfsrpc_destroyclient(nmp, clp, cred, p);
 		} else
-			(void)nfsrpc_setclient(nmp, clp, cred, p);
+			(void)nfsrpc_setclient(nmp, clp, 0, cred, p);
 		nfscl_cleanclient(clp);
 		nmp->nm_clp = NULL;
 		NFSFREECRED(cred);
@@ -1851,8 +1853,9 @@ nfscl_umount(struct nfsmount *nmp, NFSPR
 
 /*
  * This function is called when a server replies with NFSERR_STALECLIENTID
- * or NFSERR_STALESTATEID. It traverses the clientid lists, doing Opens
- * and Locks with reclaim. If these fail, it deletes the corresponding state.
+ * NFSERR_STALESTATEID or NFSERR_BADSESSION. It traverses the clientid lists,
+ * doing Opens and Locks with reclaim. If these fail, it deletes the
+ * corresponding state.
  */
 static void
 nfscl_recover(struct nfsclclient *clp, struct ucred *cred, NFSPROC_T *p)
@@ -1888,8 +1891,9 @@ nfscl_recover(struct nfsclclient *clp, s
 		panic("nfscl recover");
 	trycnt = 5;
 	do {
-		error = nfsrpc_setclient(nmp, clp, cred, p);
+		error = nfsrpc_setclient(nmp, clp, 1, cred, p);
 	} while ((error == NFSERR_STALECLIENTID ||
+	     error == NFSERR_BADSESSION ||
 	     error == NFSERR_STALEDONTRECOVER) && --trycnt > 0);
 	if (error) {
 		nfscl_cleanclient(clp);
@@ -1908,9 +1912,10 @@ nfscl_recover(struct nfsclclient *clp, s
 	 * Mark requests already queued on the server, so that they don't
 	 * initiate another recovery cycle. Any requests already in the
 	 * queue that handle state information will have the old stale
-	 * clientid/stateid and will get a NFSERR_STALESTATEID or
-	 * NFSERR_STALECLIENTID reply from the server. This will be
-	 * translated to NFSERR_STALEDONTRECOVER when R_DONTRECOVER is set.
+	 * clientid/stateid and will get a NFSERR_STALESTATEID,
+	 * NFSERR_STALECLIENTID or NFSERR_BADSESSION reply from the server.
+	 * This will be translated to NFSERR_STALEDONTRECOVER when
+	 * R_DONTRECOVER is set.
 	 */
 	s = splsoftclock();
 	NFSLOCKREQ();
@@ -2209,8 +2214,9 @@ nfscl_hasexpired(struct nfsclclient *clp
 	cred = newnfs_getcred();
 	trycnt = 5;
 	do {
-		error = nfsrpc_setclient(nmp, clp, cred, p);
+		error = nfsrpc_setclient(nmp, clp, 0, cred, p);
 	} while ((error == NFSERR_STALECLIENTID ||
+	     error == NFSERR_BADSESSION ||
 	     error == NFSERR_STALEDONTRECOVER) && --trycnt > 0);
 	if (error) {
 		/*
@@ -2447,7 +2453,8 @@ nfscl_renewthread(struct nfsclclient *cl
 			error = nfsrpc_renew(clp, cred, p);
 			if (error == NFSERR_CBPATHDOWN)
 			    cbpathdown = 1;
-			else if (error == NFSERR_STALECLIENTID) {
+			else if (error == NFSERR_STALECLIENTID ||
+			    error == NFSERR_BADSESSION) {
 			    NFSLOCKCLSTATE();
 			    clp->nfsc_flags |= NFSCLFLAGS_RECOVER;
 			    NFSUNLOCKCLSTATE();
@@ -2618,8 +2625,8 @@ tryagain:
 }
 
 /*
- * Initiate state recovery. Called when NFSERR_STALECLIENTID or
- * NFSERR_STALESTATEID is received.
+ * Initiate state recovery. Called when NFSERR_STALECLIENTID,
+ * NFSERR_STALESTATEID or NFSERR_BADSESSION is received.
  */
 APPLESTATIC void
 nfscl_initiate_recovery(struct nfsclclient *clp)
@@ -3574,7 +3581,8 @@ nfscl_recalldeleg(struct nfsclclient *cl
 					ret = nfscl_moveopen(vp, clp, nmp, lop,
 					    owp, dp, cred, p);
 					if (ret == NFSERR_STALECLIENTID ||
-					    ret == NFSERR_STALEDONTRECOVER) {
+					    ret == NFSERR_STALEDONTRECOVER ||
+					    ret == NFSERR_BADSESSION) {
 						if (gotvp)
 							vrele(vp);
 						return (ret);
@@ -3605,7 +3613,8 @@ nfscl_recalldeleg(struct nfsclclient *cl
 				if (ret) {
 					nfscl_freeopenowner(owp, 0);
 					if (ret == NFSERR_STALECLIENTID ||
-					    ret == NFSERR_STALEDONTRECOVER) {
+					    ret == NFSERR_STALEDONTRECOVER ||
+					    ret == NFSERR_BADSESSION) {
 						if (gotvp)
 							vrele(vp);
 						return (ret);
@@ -3629,7 +3638,8 @@ nfscl_recalldeleg(struct nfsclclient *cl
 			ret = nfscl_relock(vp, clp, nmp, lp, lckp, cred, p);
 			if (ret == NFSERR_STALESTATEID ||
 			    ret == NFSERR_STALEDONTRECOVER ||
-			    ret == NFSERR_STALECLIENTID) {
+			    ret == NFSERR_STALECLIENTID ||
+			    ret == NFSERR_BADSESSION) {
 				if (gotvp)
 					vrele(vp);
 				return (ret);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201290101.q0T11g2f009016>