svn commit: r336422 - in stable/10/sys/fs: nfs nfsserver

Rick Macklem rmacklem at FreeBSD.org
Tue Jul 17 19:26:19 UTC 2018


Author: rmacklem
Date: Tue Jul 17 19:26:17 2018
New Revision: 336422
URL: https://svnweb.freebsd.org/changeset/base/336422

Log:
  MFC: r333645
  End grace for the NFSv4 server if all mounts do ReclaimComplete.
  
  The NFSv4 protocol requires that the server only allow reclaim of state
  and not issue any new open/lock state for a grace period after booting.
  The NFSv4.0 protocol required this grace period to be greater than the
  lease duration (over 2minutes). For NFSv4.1, the client tells the server
  that it has done reclaiming state by doing a ReclaimComplete operation.
  If all NFSv4 clients are NFSv4.1, the grace period can end once all the
  clients have done ReclaimComplete, shortening the time period considerably.
  This patch does this. If there are any NFSv4.0 mounts, the grace period
  will still be over 2minutes.
  This change is only an optimization and does not affect correct operation.

Modified:
  stable/10/sys/fs/nfs/nfsport.h
  stable/10/sys/fs/nfsserver/nfs_nfsdstate.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/fs/nfs/nfsport.h
==============================================================================
--- stable/10/sys/fs/nfs/nfsport.h	Tue Jul 17 19:10:15 2018	(r336421)
+++ stable/10/sys/fs/nfs/nfsport.h	Tue Jul 17 19:26:17 2018	(r336422)
@@ -519,6 +519,7 @@ struct nfst_rec {
 #define	NFSNST_NEWSTATE	0x1
 #define	NFSNST_REVOKE		0x2
 #define	NFSNST_GOTSTATE		0x4
+#define	NFSNST_RECLAIMED	0x8
 
 /*
  * This structure is linked onto nfsrv_stablefirst for the duration of

Modified: stable/10/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- stable/10/sys/fs/nfsserver/nfs_nfsdstate.c	Tue Jul 17 19:10:15 2018	(r336421)
+++ stable/10/sys/fs/nfsserver/nfs_nfsdstate.c	Tue Jul 17 19:26:17 2018	(r336422)
@@ -139,6 +139,7 @@ static int nfsrv_cbcallargs(struct nfsrv_descript *nd,
 static u_int32_t nfsrv_nextclientindex(void);
 static u_int32_t nfsrv_nextstateindex(struct nfsclient *clp);
 static void nfsrv_markstable(struct nfsclient *clp);
+static void nfsrv_markreclaim(struct nfsclient *clp);
 static int nfsrv_checkstable(struct nfsclient *clp);
 static int nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, struct 
     vnode *vp, NFSPROC_T *p);
@@ -4087,8 +4088,27 @@ static int
 nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp,
     u_int32_t flags)
 {
-	int error = 0;
+	int error = 0, notreclaimed;
+	struct nfsrv_stable *sp;
 
+	if ((nfsrv_stablefirst.nsf_flags & (NFSNSF_UPDATEDONE |
+	     NFSNSF_GRACEOVER)) == 0) {
+		/*
+		 * First, check to see if all of the clients have done a
+		 * ReclaimComplete.  If so, grace can end now.
+		 */
+		notreclaimed = 0;
+		LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
+			if ((sp->nst_flag & NFSNST_RECLAIMED) == 0) {
+				notreclaimed = 1;
+				break;
+			}
+		}
+		if (notreclaimed == 0)
+			nfsrv_stablefirst.nsf_flags |= (NFSNSF_GRACEOVER |
+			    NFSNSF_NEEDLOCK);
+	}
+
 	if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) {
 		if (flags & NFSLCK_RECLAIM) {
 			error = NFSERR_NOGRACE;
@@ -4745,6 +4765,32 @@ nfsrv_markstable(struct nfsclient *clp)
 }
 
 /*
+ * This function is called when a NFSv4.1 client does a ReclaimComplete.
+ * Very similar to nfsrv_markstable(), except for the flag being set.
+ */
+static void
+nfsrv_markreclaim(struct nfsclient *clp)
+{
+	struct nfsrv_stable *sp;
+
+	/*
+	 * First find the client structure.
+	 */
+	LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
+		if (sp->nst_len == clp->lc_idlen &&
+		    !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
+			break;
+	}
+	if (sp == LIST_END(&nfsrv_stablefirst.nsf_head))
+		return;
+
+	/*
+	 * Now, just set the flag.
+	 */
+	sp->nst_flag |= NFSNST_RECLAIMED;
+}
+
+/*
  * This function is called for a reclaim, to see if it gets grace.
  * It returns 0 if a reclaim is allowed, 1 otherwise.
  */
@@ -5897,8 +5943,10 @@ nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd)
 	/* Check to see if reclaim complete has already happened. */
 	if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0)
 		error = NFSERR_COMPLETEALREADY;
-	else
+	else {
 		sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE;
+		nfsrv_markreclaim(sep->sess_clp);
+	}
 	NFSUNLOCKSESSION(shp);
 	NFSUNLOCKSTATE();
 	return (error);


More information about the svn-src-all mailing list