svn commit: r207180 - in stable/8/sys/fs: nfs nfsclient

Rick Macklem rmacklem at FreeBSD.org
Sun Apr 25 01:56:32 UTC 2010


Author: rmacklem
Date: Sun Apr 25 01:56:31 2010
New Revision: 207180
URL: http://svn.freebsd.org/changeset/base/207180

Log:
  MFC: r206818
  Avoid extraneous recovery cycles in the experimental NFS client
  when an NFSv4 server reboots, by doing two things.
  1 - Make the function that acquires a stateid for I/O operations
      block until recovery is complete, so that it doesn't acquire
      out of date stateids.
  2 - Only allow a recovery once every 1/2 of a lease duration, since
      the NFSv4 server must provide a recovery grace period of at
      least a lease duration. This should avoid recoveries caused
      by an out of date stateid that was acquired for an I/O op.
      just before a recovery cycle started.

Modified:
  stable/8/sys/fs/nfs/nfsclstate.h
  stable/8/sys/fs/nfsclient/nfs_clstate.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/geom/sched/   (props changed)

Modified: stable/8/sys/fs/nfs/nfsclstate.h
==============================================================================
--- stable/8/sys/fs/nfs/nfsclstate.h	Sun Apr 25 01:36:46 2010	(r207179)
+++ stable/8/sys/fs/nfs/nfsclstate.h	Sun Apr 25 01:56:31 2010	(r207180)
@@ -74,6 +74,7 @@ struct nfsclclient {
 #define	NFSCLFLAGS_EXPIREIT	0x0040
 #define	NFSCLFLAGS_FIRSTDELEG	0x0080
 #define	NFSCLFLAGS_GOTDELEG	0x0100
+#define	NFSCLFLAGS_RECVRINPROG	0x0200
 
 struct nfsclowner {
 	LIST_ENTRY(nfsclowner)	nfsow_list;

Modified: stable/8/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- stable/8/sys/fs/nfsclient/nfs_clstate.c	Sun Apr 25 01:36:46 2010	(r207179)
+++ stable/8/sys/fs/nfsclient/nfs_clstate.c	Sun Apr 25 01:56:31 2010	(r207180)
@@ -481,6 +481,13 @@ nfscl_getstateid(vnode_t vp, u_int8_t *n
 	}
 
 	/*
+	 * Wait for recovery to complete.
+	 */
+	while ((clp->nfsc_flags & NFSCLFLAGS_RECVRINPROG))
+		(void) nfsmsleep(&clp->nfsc_flags, NFSCLSTATEMUTEXPTR,
+		    PZERO, "nfsrecvr", NULL);
+
+	/*
 	 * First, look for a delegation.
 	 */
 	LIST_FOREACH(dp, NFSCLDELEGHASH(clp, nfhp, fhlen), nfsdl_hash) {
@@ -1778,6 +1785,7 @@ nfscl_recover(struct nfsclclient *clp, s
 	 * block when trying to use state.
 	 */
 	NFSLOCKCLSTATE();
+	clp->nfsc_flags |= NFSCLFLAGS_RECVRINPROG;
 	do {
 		igotlock = nfsv4_lock(&clp->nfsc_lock, 1, NULL,
 		    NFSCLSTATEMUTEXPTR);
@@ -1794,9 +1802,10 @@ nfscl_recover(struct nfsclclient *clp, s
 	     error == NFSERR_STALEDONTRECOVER) && --trycnt > 0);
 	if (error) {
 		nfscl_cleanclient(clp);
-		clp->nfsc_flags &= ~(NFSCLFLAGS_HASCLIENTID |
-		    NFSCLFLAGS_RECOVER);
 		NFSLOCKCLSTATE();
+		clp->nfsc_flags &= ~(NFSCLFLAGS_HASCLIENTID |
+		    NFSCLFLAGS_RECOVER | NFSCLFLAGS_RECVRINPROG);
+		wakeup(&clp->nfsc_flags);
 		nfsv4_unlock(&clp->nfsc_lock, 0);
 		NFSUNLOCKCLSTATE();
 		return;
@@ -2057,6 +2066,8 @@ nfscl_recover(struct nfsclclient *clp, s
 	}
 
 	NFSLOCKCLSTATE();
+	clp->nfsc_flags &= ~NFSCLFLAGS_RECVRINPROG;
+	wakeup(&clp->nfsc_flags);
 	nfsv4_unlock(&clp->nfsc_lock, 0);
 	NFSUNLOCKCLSTATE();
 	NFSFREECRED(tcred);
@@ -2316,6 +2327,7 @@ nfscl_renewthread(struct nfsclclient *cl
 	struct ucred *cred;
 	u_int32_t clidrev;
 	int error, cbpathdown, islept, igotlock, ret, clearok;
+	uint32_t recover_done_time = 0;
 
 	cred = newnfs_getcred();
 	NFSLOCKCLSTATE();
@@ -2324,8 +2336,21 @@ nfscl_renewthread(struct nfsclclient *cl
 	for(;;) {
 		newnfs_setroot(cred);
 		cbpathdown = 0;
-		if (clp->nfsc_flags & NFSCLFLAGS_RECOVER)
-			nfscl_recover(clp, cred, p);
+		if (clp->nfsc_flags & NFSCLFLAGS_RECOVER) {
+			/*
+			 * Only allow one recover within 1/2 of the lease
+			 * duration (nfsc_renew).
+			 */
+			if (recover_done_time < NFSD_MONOSEC) {
+				recover_done_time = NFSD_MONOSEC +
+				    clp->nfsc_renew;
+				nfscl_recover(clp, cred, p);
+			} else {
+				NFSLOCKCLSTATE();
+				clp->nfsc_flags &= ~NFSCLFLAGS_RECOVER;
+				NFSUNLOCKCLSTATE();
+			}
+		}
 		if (clp->nfsc_expire <= NFSD_MONOSEC &&
 		    (clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID)) {
 			clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;


More information about the svn-src-stable-8 mailing list