From owner-svn-src-head@freebsd.org Tue May 15 20:28:51 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A9DBDEAC987; Tue, 15 May 2018 20:28:51 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 5878C7CFB3; Tue, 15 May 2018 20:28:51 +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 mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 398EE105DF; Tue, 15 May 2018 20:28:51 +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 w4FKSpgp075559; Tue, 15 May 2018 20:28:51 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w4FKSoua075558; Tue, 15 May 2018 20:28:50 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <201805152028.w4FKSoua075558@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Tue, 15 May 2018 20:28:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r333645 - in head/sys/fs: nfs nfsserver X-SVN-Group: head X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in head/sys/fs: nfs nfsserver X-SVN-Commit-Revision: 333645 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 May 2018 20:28:52 -0000 Author: rmacklem Date: Tue May 15 20:28:50 2018 New Revision: 333645 URL: https://svnweb.freebsd.org/changeset/base/333645 Log: 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. Tested by: andreas.nagy@frequentis.com MFC after: 2 months Modified: head/sys/fs/nfs/nfsport.h head/sys/fs/nfsserver/nfs_nfsdstate.c Modified: head/sys/fs/nfs/nfsport.h ============================================================================== --- head/sys/fs/nfs/nfsport.h Tue May 15 20:14:38 2018 (r333644) +++ head/sys/fs/nfs/nfsport.h Tue May 15 20:28:50 2018 (r333645) @@ -590,6 +590,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: head/sys/fs/nfsserver/nfs_nfsdstate.c ============================================================================== --- head/sys/fs/nfsserver/nfs_nfsdstate.c Tue May 15 20:14:38 2018 (r333644) +++ head/sys/fs/nfsserver/nfs_nfsdstate.c Tue May 15 20:28:50 2018 (r333645) @@ -136,6 +136,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); @@ -4091,8 +4092,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; @@ -4749,6 +4769,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. */ @@ -5904,8 +5950,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);