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.n...@frequentis.com
  Tested by:    andreas.n...@frequentis.com, dan...@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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to