svn commit: r336839 - in head/sys/fs: nfs nfsserver

Rick Macklem rmacklem at FreeBSD.org
Sat Jul 28 20:21:06 UTC 2018


Author: rmacklem
Date: Sat Jul 28 20:21:04 2018
New Revision: 336839
URL: https://svnweb.freebsd.org/changeset/base/336839

Log:
  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.
  
  Reported by:	andreas.nagy at frequentis.com
  Tested by:	andreas.nagy at frequentis.com, daniel at ftml.net (earlier version)
  MFC after:	2 weeks
  Relnotes:	yes

Modified:
  head/sys/fs/nfs/nfs.h
  head/sys/fs/nfs/nfs_var.h
  head/sys/fs/nfsserver/nfs_nfsdserv.c
  head/sys/fs/nfsserver/nfs_nfsdstate.c

Modified: head/sys/fs/nfs/nfs.h
==============================================================================
--- head/sys/fs/nfs/nfs.h	Sat Jul 28 20:04:39 2018	(r336838)
+++ head/sys/fs/nfs/nfs.h	Sat Jul 28 20:21:04 2018	(r336839)
@@ -329,6 +329,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: head/sys/fs/nfs/nfs_var.h
==============================================================================
--- head/sys/fs/nfs/nfs_var.h	Sat Jul 28 20:04:39 2018	(r336838)
+++ head/sys/fs/nfs/nfs_var.h	Sat Jul 28 20:21:04 2018	(r336839)
@@ -141,7 +141,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);
 int nfsrv_layoutcommit(struct nfsrv_descript *, vnode_t, int, int, uint64_t,

Modified: head/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdserv.c	Sat Jul 28 20:04:39 2018	(r336838)
+++ head/sys/fs/nfsserver/nfs_nfsdserv.c	Sat Jul 28 20:21:04 2018	(r336839)
@@ -4229,17 +4229,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: head/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdstate.c	Sat Jul 28 20:04:39 2018	(r336838)
+++ head/sys/fs/nfsserver/nfs_nfsdstate.c	Sat Jul 28 20:21:04 2018	(r336839)
@@ -6064,7 +6064,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;
@@ -6080,8 +6080,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;


More information about the svn-src-all mailing list