Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Aug 2018 11:10:49 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r338131 - in stable/11/sys/fs: nfs nfsserver
Message-ID:  <201808211110.w7LBAnvW060288@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Tue Aug 21 11:10:49 2018
New Revision: 338131
URL: https://svnweb.freebsd.org/changeset/base/338131

Log:
  MFC: r336839
  Modify the NFSv4.1 server so that it allows ReclaimComplete as done by ESXi 6.7.
  
  I believe that a ReclaimComplete with rca_one_fs == TRUE is only
  to be used after a file system has been transferred to a different
  file server.  However, RFC5661 is somewhat vague w.r.t. this and
  the ESXi 6.7 client does both a ReclaimComplete with rca_one_fs == TRUE
  and one with ReclaimComplete with rca_one_fs == FALSE.
  Therefore, just ignore the rca_one_fs == TRUE operation and return
  NFS_OK without doing anything instead of replying NFS4ERR_NOTSUPP.
  This allows the ESXi 6.7 NFSv4.1 client to do a mount.
  After discussion on the NFSv4 IETF working group mailing list, doing this
  along with setting a flag to note that a ReclaimComplete with rca_one_fs TRUE
  was an appropriate way to handle this.
  The flag that indicates that a ReclaimComplete with rca_one_fs == TRUE was
  done may be used to disable replies of NFS4ERR_GRACE for non-reclaim
  state operations in a future commit.
  
  This patch along with r332790, r334492 and r336357 allow ESXi 6.7 NFSv4.1 mounts
  work ok. ESX 6.5 NFSv4.1 mounts do not work well, due to what I believe are
  violations of RFC-5661 and should not be used.

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

Modified: stable/11/sys/fs/nfs/nfs.h
==============================================================================
--- stable/11/sys/fs/nfs/nfs.h	Tue Aug 21 10:08:12 2018	(r338130)
+++ stable/11/sys/fs/nfs/nfs.h	Tue Aug 21 11:10:49 2018	(r338131)
@@ -289,6 +289,7 @@ struct nfsreferral {
 #define	LCL_RECLAIMCOMPLETE	0x00010000
 #define	LCL_NFSV41		0x00020000
 #define	LCL_DONEBINDCONN	0x00040000
+#define	LCL_RECLAIMONEFS	0x00080000
 
 #define	LCL_GSS		LCL_KERBV	/* Or of all mechs */
 

Modified: stable/11/sys/fs/nfs/nfs_var.h
==============================================================================
--- stable/11/sys/fs/nfs/nfs_var.h	Tue Aug 21 10:08:12 2018	(r338130)
+++ stable/11/sys/fs/nfs/nfs_var.h	Tue Aug 21 11:10:49 2018	(r338131)
@@ -135,7 +135,7 @@ void nfsrv_nfsuserddelport(void);
 void nfsrv_throwawayallstate(NFSPROC_T *);
 int nfsrv_checksequence(struct nfsrv_descript *, uint32_t, uint32_t *,
     uint32_t *, int, uint32_t *, NFSPROC_T *);
-int nfsrv_checkreclaimcomplete(struct nfsrv_descript *);
+int nfsrv_checkreclaimcomplete(struct nfsrv_descript *, int);
 void nfsrv_cache_session(uint8_t *, uint32_t, int, struct mbuf **);
 void nfsrv_freeallbackchannel_xprts(void);
 

Modified: stable/11/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- stable/11/sys/fs/nfsserver/nfs_nfsdserv.c	Tue Aug 21 10:08:12 2018	(r338130)
+++ stable/11/sys/fs/nfsserver/nfs_nfsdserv.c	Tue Aug 21 11:10:49 2018	(r338131)
@@ -4016,17 +4016,26 @@ nfsrvd_reclaimcomplete(struct nfsrv_descript *nd, __un
     __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp)
 {
 	uint32_t *tl;
-	int error = 0;
+	int error = 0, onefs;
 
 	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 		nd->nd_repstat = NFSERR_WRONGSEC;
 		goto nfsmout;
 	}
 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+	/*
+	 * I believe that a ReclaimComplete with rca_one_fs == TRUE is only
+	 * to be used after a file system has been transferred to a different
+	 * file server.  However, RFC5661 is somewhat vague w.r.t. this and
+	 * the ESXi 6.7 client does both a ReclaimComplete with rca_one_fs
+	 * == TRUE and one with ReclaimComplete with rca_one_fs == FALSE.
+	 * Therefore, just ignore the rca_one_fs == TRUE operation and return
+	 * NFS_OK without doing anything.
+	 */
+	onefs = 0;
 	if (*tl == newnfs_true)
-		nd->nd_repstat = NFSERR_NOTSUPP;
-	else
-		nd->nd_repstat = nfsrv_checkreclaimcomplete(nd);
+		onefs = 1;
+	nd->nd_repstat = nfsrv_checkreclaimcomplete(nd, onefs);
 nfsmout:
 	NFSEXITCODE2(error, nd);
 	return (error);

Modified: stable/11/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- stable/11/sys/fs/nfsserver/nfs_nfsdstate.c	Tue Aug 21 10:08:12 2018	(r338130)
+++ stable/11/sys/fs/nfsserver/nfs_nfsdstate.c	Tue Aug 21 11:10:49 2018	(r338131)
@@ -5946,7 +5946,7 @@ nfsrv_checksequence(struct nfsrv_descript *nd, uint32_
  * Check/set reclaim complete for this session/clientid.
  */
 int
-nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd)
+nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd, int onefs)
 {
 	struct nfsdsession *sep;
 	struct nfssessionhash *shp;
@@ -5962,8 +5962,10 @@ nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd)
 		return (NFSERR_BADSESSION);
 	}
 
-	/* Check to see if reclaim complete has already happened. */
-	if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0)
+	if (onefs != 0)
+		sep->sess_clp->lc_flags |= LCL_RECLAIMONEFS;
+		/* Check to see if reclaim complete has already happened. */
+	else if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0)
 		error = NFSERR_COMPLETEALREADY;
 	else {
 		sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE;



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