From owner-svn-src-stable@freebsd.org  Mon Dec 19 22:15:30 2016
Return-Path: <owner-svn-src-stable@freebsd.org>
Delivered-To: svn-src-stable@mailman.ysv.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org
 [IPv6:2001:1900:2254:206a::19:1])
 by mailman.ysv.freebsd.org (Postfix) with ESMTP id BD9DBC88237;
 Mon, 19 Dec 2016 22:15:30 +0000 (UTC)
 (envelope-from rmacklem@FreeBSD.org)
Received: from repo.freebsd.org (repo.freebsd.org
 [IPv6:2610:1c1:1:6068::e6a:0])
 (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
 (Client did not present a certificate)
 by mx1.freebsd.org (Postfix) with ESMTPS id 97A8E13C1;
 Mon, 19 Dec 2016 22:15:30 +0000 (UTC)
 (envelope-from rmacklem@FreeBSD.org)
Received: from repo.freebsd.org ([127.0.1.37])
 by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uBJMFTvq001085;
 Mon, 19 Dec 2016 22:15:29 GMT (envelope-from rmacklem@FreeBSD.org)
Received: (from rmacklem@localhost)
 by repo.freebsd.org (8.15.2/8.15.2/Submit) id uBJMFTbY001084;
 Mon, 19 Dec 2016 22:15:29 GMT (envelope-from rmacklem@FreeBSD.org)
Message-Id: <201612192215.uBJMFTbY001084@repo.freebsd.org>
X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to
 rmacklem@FreeBSD.org using -f
From: Rick Macklem <rmacklem@FreeBSD.org>
Date: Mon, 19 Dec 2016 22:15:29 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-all@freebsd.org,
 svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject: svn commit: r310301 - stable/11/sys/fs/nfsserver
X-SVN-Group: stable-11
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: svn-src-stable@freebsd.org
X-Mailman-Version: 2.1.23
Precedence: list
List-Id: SVN commit messages for all the -stable branches of the src tree
 <svn-src-stable.freebsd.org>
List-Unsubscribe: <https://lists.freebsd.org/mailman/options/svn-src-stable>, 
 <mailto:svn-src-stable-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-stable/>
List-Post: <mailto:svn-src-stable@freebsd.org>
List-Help: <mailto:svn-src-stable-request@freebsd.org?subject=help>
List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/svn-src-stable>,
 <mailto:svn-src-stable-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Mon, 19 Dec 2016 22:15:30 -0000

Author: rmacklem
Date: Mon Dec 19 22:15:29 2016
New Revision: 310301
URL: https://svnweb.freebsd.org/changeset/base/310301

Log:
  MFC: r309566
  Fix the NFSv4.1 server for Open reclaim after a reboot.
  
  The NFSv4.1 server failed to update the nfs-stablerestart file for
  a client when the client was issued its first Open. As such, recovery
  of Opens after a server reboot failed with NFSERR_NOGRACE.
  This patch fixes this.
  It also changes the code so that it malloc()'s the 1024 byte array
  instead of allocating it on the kernel stack for both NFSv4.0 and NFSv4.1.
  Note that this bug only affected NFSv4.1 and only when clients attempted
  to reclaim Opens after a server reboot.

Modified:
  stable/11/sys/fs/nfsserver/nfs_nfsdstate.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- stable/11/sys/fs/nfsserver/nfs_nfsdstate.c	Mon Dec 19 21:51:13 2016	(r310300)
+++ stable/11/sys/fs/nfsserver/nfs_nfsdstate.c	Mon Dec 19 22:15:29 2016	(r310301)
@@ -2501,6 +2501,8 @@ nfsrv_openctrl(struct nfsrv_descript *nd
 	struct nfsclient *clp;
 	int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1;
 	int readonly = 0, cbret = 1, getfhret = 0;
+	int gotstate = 0, len = 0;
+	u_char *clidp = NULL;
 
 	if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
 		readonly = 1;
@@ -2519,6 +2521,7 @@ nfsrv_openctrl(struct nfsrv_descript *nd
 		goto out;
 	}
 
+	clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
 tryagain:
 	MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile),
 	    M_NFSDLOCKFILE, M_WAITOK);
@@ -3181,6 +3184,16 @@ tryagain:
 				nfsrv_openpluslock++;
 				nfsrv_delegatecnt++;
 			}
+			/*
+			 * Since NFSv4.1 never does an OpenConfirm, the first
+			 * open state will be acquired here.
+			 */
+			if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
+				clp->lc_flags |= LCL_STAMPEDSTABLE;
+				len = clp->lc_idlen;
+				NFSBCOPY(clp->lc_id, clidp, len);
+				gotstate = 1;
+			}
 		} else {
 			*rflagsp |= NFSV4OPEN_RESULTCONFIRM;
 			new_stp->ls_flags = NFSLCK_NEEDSCONFIRM;
@@ -3217,7 +3230,17 @@ tryagain:
 	if (new_deleg)
 		FREE((caddr_t)new_deleg, M_NFSDSTATE);
 
+	/*
+	 * If the NFSv4.1 client just acquired its first open, write a timestamp
+	 * to the stable storage file.
+	 */
+	if (gotstate != 0) {
+		nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
+		nfsrv_backupstable();
+	}
+
 out:
+	free(clidp, M_TEMP);
 	NFSEXITCODE2(error, nd);
 	return (error);
 }
@@ -3234,7 +3257,7 @@ nfsrv_openupdate(vnode_t vp, struct nfss
 	struct nfslockfile *lfp;
 	u_int32_t bits;
 	int error = 0, gotstate = 0, len = 0;
-	u_char client[NFSV4_OPAQUELIMIT];
+	u_char *clidp = NULL;
 
 	/*
 	 * Check for restart conditions (client and server).
@@ -3244,6 +3267,7 @@ nfsrv_openupdate(vnode_t vp, struct nfss
 	if (error)
 		goto out;
 
+	clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
 	NFSLOCKSTATE();
 	/*
 	 * Get the open structure via clientid and stateid.
@@ -3322,7 +3346,7 @@ nfsrv_openupdate(vnode_t vp, struct nfss
 		if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
 			clp->lc_flags |= LCL_STAMPEDSTABLE;
 			len = clp->lc_idlen;
-			NFSBCOPY(clp->lc_id, client, len);
+			NFSBCOPY(clp->lc_id, clidp, len);
 			gotstate = 1;
 		}
 		NFSUNLOCKSTATE();
@@ -3369,11 +3393,12 @@ nfsrv_openupdate(vnode_t vp, struct nfss
 	 * to the stable storage file.
 	 */
 	if (gotstate != 0) {
-		nfsrv_writestable(client, len, NFSNST_NEWSTATE, p);
+		nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
 		nfsrv_backupstable();
 	}
 
 out:
+	free(clidp, M_TEMP);
 	NFSEXITCODE2(error, nd);
 	return (error);
 }