Author: rmacklem
Date: Tue Jul  1 20:47:16 2014
New Revision: 268115
URL: http://svnweb.freebsd.org/changeset/base/268115

Log:
  Merge the NFSv4.1 server code in projects/nfsv4.1-server over
  into head. The code is not believed to have any effect
  on the semantics of non-NFSv4.1 server behaviour.
  It is a rather large merge, but I am hoping that there will
  not be any regressions for the NFS server.
  
  MFC after:    1 month

Added:
  head/sys/rpc/clnt_bck.c   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/fs/nfs/nfs.h
  head/sys/fs/nfs/nfs_commonkrpc.c
  head/sys/fs/nfs/nfs_commonport.c
  head/sys/fs/nfs/nfs_commonsubs.c
  head/sys/fs/nfs/nfs_var.h
  head/sys/fs/nfs/nfsclstate.h
  head/sys/fs/nfs/nfsdport.h
  head/sys/fs/nfs/nfsport.h
  head/sys/fs/nfs/nfsproto.h
  head/sys/fs/nfs/nfsrvstate.h
  head/sys/fs/nfsclient/nfs_clstate.c
  head/sys/fs/nfsserver/nfs_nfsdcache.c
  head/sys/fs/nfsserver/nfs_nfsdkrpc.c
  head/sys/fs/nfsserver/nfs_nfsdport.c
  head/sys/fs/nfsserver/nfs_nfsdserv.c
  head/sys/fs/nfsserver/nfs_nfsdsocket.c
  head/sys/fs/nfsserver/nfs_nfsdstate.c
  head/sys/fs/nfsserver/nfs_nfsdsubs.c
  head/sys/modules/krpc/Makefile
  head/sys/rpc/krpc.h
  head/sys/rpc/svc.h
  head/sys/rpc/svc_vc.c

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Tue Jul  1 20:00:35 2014        (r268114)
+++ head/sys/conf/files Tue Jul  1 20:47:16 2014        (r268115)
@@ -3810,6 +3810,7 @@ pci/viapm.c                       optional viapm pci
 rpc/auth_none.c                        optional krpc | nfslockd | nfsclient | 
nfsserver | nfscl | nfsd
 rpc/auth_unix.c                        optional krpc | nfslockd | nfsclient | 
nfscl | nfsd
 rpc/authunix_prot.c            optional krpc | nfslockd | nfsclient | 
nfsserver | nfscl | nfsd
+rpc/clnt_bck.c                 optional krpc | nfslockd | nfsserver | nfscl | 
nfsd
 rpc/clnt_dg.c                  optional krpc | nfslockd | nfsclient | nfscl | 
nfsd
 rpc/clnt_rc.c                  optional krpc | nfslockd | nfsclient | nfscl | 
nfsd
 rpc/clnt_vc.c                  optional krpc | nfslockd | nfsclient | 
nfsserver | nfscl | nfsd

Modified: head/sys/fs/nfs/nfs.h
==============================================================================
--- head/sys/fs/nfs/nfs.h       Tue Jul  1 20:00:35 2014        (r268114)
+++ head/sys/fs/nfs/nfs.h       Tue Jul  1 20:47:16 2014        (r268115)
@@ -50,7 +50,8 @@
 #define        NFS_MAXREXMIT   100             /* Stop counting after this 
many */
 #define        NFSV4_CALLBACKTIMEO (2 * NFS_HZ) /* Timeout in ticks */
 #define        NFSV4_CALLBACKRETRY 5           /* Number of retries before 
failure */
-#define        NFSV4_CBSLOTS   8               /* Number of slots for session 
*/
+#define        NFSV4_SLOTS     64              /* Number of slots, fore 
channel */
+#define        NFSV4_CBSLOTS   8               /* Number of slots, back 
channel */
 #define        NFSV4_CBRETRYCNT 4              /* # of CBRecall retries upon 
err */
 #define        NFSV4_UPCALLTIMEO (15 * NFS_HZ) /* Timeout in ticks for upcalls 
*/
                                        /* to gssd or nfsuserd */
@@ -91,6 +92,9 @@
 #ifndef NFSLOCKHASHSIZE
 #define        NFSLOCKHASHSIZE         20      /* Size of server nfslock hash 
table */
 #endif
+#ifndef NFSSESSIONHASHSIZE
+#define        NFSSESSIONHASHSIZE      20      /* Size of server session hash 
table */
+#endif
 #define        NFSSTATEHASHSIZE        10      /* Size of server stateid hash 
table */
 #ifndef NFSUSERHASHSIZE
 #define        NFSUSERHASHSIZE         30      /* Size of user id hash table */
@@ -276,6 +280,8 @@ struct nfsreferral {
 #define        LCL_GSSINTEGRITY        0x00002000
 #define        LCL_GSSPRIVACY          0x00004000
 #define        LCL_ADMINREVOKED        0x00008000
+#define        LCL_RECLAIMCOMPLETE     0x00010000
+#define        LCL_NFSV41              0x00020000
 
 #define        LCL_GSS         LCL_KERBV       /* Or of all mechs */
 
@@ -318,6 +324,11 @@ struct nfsreferral {
 #define        NFSLCK_SETATTR          0x02000000
 #define        NFSLCK_DELEGPURGE       0x04000000
 #define        NFSLCK_DELEGRETURN      0x08000000
+#define        NFSLCK_WANTWDELEG       0x10000000
+#define        NFSLCK_WANTRDELEG       0x20000000
+#define        NFSLCK_WANTNODELEG      0x40000000
+#define        NFSLCK_WANTBITS                                                 
\
+    (NFSLCK_WANTWDELEG | NFSLCK_WANTRDELEG | NFSLCK_WANTNODELEG)
 
 /* And bits for nid_flag */
 #define        NFSID_INITIALIZE        0x0001
@@ -341,68 +352,120 @@ struct nfsreferral {
  * THE MACROS MUST BE MANUALLY MODIFIED IF NFSATTRBIT_MAXWORDS CHANGES!!
  * It is (NFSATTRBIT_MAX + 31) / 32.
  */
-#define        NFSATTRBIT_MAXWORDS     2
+#define        NFSATTRBIT_MAXWORDS     3
 
 typedef struct {
        u_int32_t bits[NFSATTRBIT_MAXWORDS];
 } nfsattrbit_t;
 
-#define        NFSZERO_ATTRBIT(b) do { (b)->bits[0] = 0; (b)->bits[1] = 0; } 
while (0)
-#define        NFSSET_ATTRBIT(t, f) do { (t)->bits[0] = (f)->bits[0];          
\
-                                 (t)->bits[1] = (f)->bits[1]; } while (0)
+#define        NFSZERO_ATTRBIT(b) do {                                         
\
+       (b)->bits[0] = 0;                                               \
+       (b)->bits[1] = 0;                                               \
+       (b)->bits[2] = 0;                                               \
+} while (0)
+
+#define        NFSSET_ATTRBIT(t, f) do {                                       
\
+       (t)->bits[0] = (f)->bits[0];                                    \
+       (t)->bits[1] = (f)->bits[1];                                    \
+       (t)->bits[2] = (f)->bits[2];                                    \
+} while (0)
+
 #define        NFSSETSUPP_ATTRBIT(b) do {                                      
\
        (b)->bits[0] = NFSATTRBIT_SUPP0;                                \
-       (b)->bits[1] = (NFSATTRBIT_SUPP1 | NFSATTRBIT_SUPPSETONLY); } while (0)
+       (b)->bits[1] = (NFSATTRBIT_SUPP1 | NFSATTRBIT_SUPPSETONLY);     \
+       (b)->bits[2] = NFSATTRBIT_SUPP2;                                \
+} while (0)
+
 #define        NFSISSET_ATTRBIT(b, p)  ((b)->bits[(p) / 32] & (1 << ((p) % 
32)))
 #define        NFSSETBIT_ATTRBIT(b, p) ((b)->bits[(p) / 32] |= (1 << ((p) % 
32)))
 #define        NFSCLRBIT_ATTRBIT(b, p) ((b)->bits[(p) / 32] &= ~(1 << ((p) % 
32)))
+
 #define        NFSCLRALL_ATTRBIT(b, a) do {                                    
\
-               (b)->bits[0] &= ~((a)->bits[0]);                        \
-               (b)->bits[1] &= ~((a)->bits[1]);                        \
-               } while (0)
+       (b)->bits[0] &= ~((a)->bits[0]);                                \
+       (b)->bits[1] &= ~((a)->bits[1]);                                \
+       (b)->bits[2] &= ~((a)->bits[2]);                                \
+} while (0)
+
 #define        NFSCLRNOT_ATTRBIT(b, a) do {                                    
\
-               (b)->bits[0] &= ((a)->bits[0]);                         \
-               (b)->bits[1] &= ((a)->bits[1]);                         \
-               } while (0)
+       (b)->bits[0] &= ((a)->bits[0]);                                 \
+       (b)->bits[1] &= ((a)->bits[1]);                                 \
+       (b)->bits[2] &= ((a)->bits[2]);                                 \
+} while (0)
+
 #define        NFSCLRNOTFILLABLE_ATTRBIT(b) do {                               
\
-               (b)->bits[0] &= NFSATTRBIT_SUPP0;                       \
-               (b)->bits[1] &= NFSATTRBIT_SUPP1; } while (0)
+       (b)->bits[0] &= NFSATTRBIT_SUPP0;                               \
+       (b)->bits[1] &= NFSATTRBIT_SUPP1;                               \
+       (b)->bits[2] &= NFSATTRBIT_SUPP2;                               \
+} while (0)
+
 #define        NFSCLRNOTSETABLE_ATTRBIT(b) do {                                
\
-               (b)->bits[0] &= NFSATTRBIT_SETABLE0;                    \
-               (b)->bits[1] &= NFSATTRBIT_SETABLE1; } while (0)
-#define        NFSNONZERO_ATTRBIT(b)   ((b)->bits[0] || (b)->bits[1])
-#define        NFSEQUAL_ATTRBIT(b, p)                                          
\
-       ((b)->bits[0] == (p)->bits[0] && (b)->bits[1] == (p)->bits[1])
+       (b)->bits[0] &= NFSATTRBIT_SETABLE0;                            \
+       (b)->bits[1] &= NFSATTRBIT_SETABLE1;                            \
+       (b)->bits[2] &= NFSATTRBIT_SETABLE2;                            \
+} while (0)
+
+#define        NFSNONZERO_ATTRBIT(b)   ((b)->bits[0] || (b)->bits[1] || 
(b)->bits[2])
+#define        NFSEQUAL_ATTRBIT(b, p)  ((b)->bits[0] == (p)->bits[0] &&        
\
+       (b)->bits[1] == (p)->bits[1] && (b)->bits[2] == (p)->bits[2])
+
 #define        NFSGETATTR_ATTRBIT(b) do {                                      
\
-               (b)->bits[0] = NFSATTRBIT_GETATTR0;                     \
-               (b)->bits[1] = NFSATTRBIT_GETATTR1; } while (0)
+       (b)->bits[0] = NFSATTRBIT_GETATTR0;                             \
+       (b)->bits[1] = NFSATTRBIT_GETATTR1;                             \
+       (b)->bits[2] = NFSATTRBIT_GETATTR2;                             \
+} while (0)
+
 #define        NFSWCCATTR_ATTRBIT(b) do {                                      
\
-               (b)->bits[0] = NFSATTRBIT_WCCATTR0;                     \
-               (b)->bits[1] = NFSATTRBIT_WCCATTR1; } while (0)
+       (b)->bits[0] = NFSATTRBIT_WCCATTR0;                             \
+       (b)->bits[1] = NFSATTRBIT_WCCATTR1;                             \
+       (b)->bits[2] = NFSATTRBIT_WCCATTR2;                             \
+} while (0)
+
 #define        NFSWRITEGETATTR_ATTRBIT(b) do {                                 
\
-               (b)->bits[0] = NFSATTRBIT_WRITEGETATTR0;                \
-               (b)->bits[1] = NFSATTRBIT_WRITEGETATTR1; } while (0)
+       (b)->bits[0] = NFSATTRBIT_WRITEGETATTR0;                        \
+       (b)->bits[1] = NFSATTRBIT_WRITEGETATTR1;                        \
+       (b)->bits[2] = NFSATTRBIT_WRITEGETATTR2;                        \
+} while (0)
+
 #define        NFSCBGETATTR_ATTRBIT(b, c) do {                                 
\
-       (c)->bits[0] = ((b)->bits[0] & NFSATTRBIT_CBGETATTR0);          \
-       (c)->bits[1] = ((b)->bits[1] & NFSATTRBIT_CBGETATTR1); } while (0)
+       (c)->bits[0] = ((b)->bits[0] & NFSATTRBIT_CBGETATTR0);          \
+       (c)->bits[1] = ((b)->bits[1] & NFSATTRBIT_CBGETATTR1);          \
+       (c)->bits[2] = ((b)->bits[2] & NFSATTRBIT_CBGETATTR2);          \
+} while (0)
+
 #define        NFSPATHCONF_GETATTRBIT(b) do {                                  
\
-               (b)->bits[0] = NFSGETATTRBIT_PATHCONF0;                 \
-               (b)->bits[1] = NFSGETATTRBIT_PATHCONF1; } while (0)
+       (b)->bits[0] = NFSGETATTRBIT_PATHCONF0;                         \
+       (b)->bits[1] = NFSGETATTRBIT_PATHCONF1;                         \
+       (b)->bits[2] = NFSGETATTRBIT_PATHCONF2;                         \
+} while (0)
+
 #define        NFSSTATFS_GETATTRBIT(b) do {                                    
\
-               (b)->bits[0] = NFSGETATTRBIT_STATFS0;                   \
-               (b)->bits[1] = NFSGETATTRBIT_STATFS1; } while (0)
+       (b)->bits[0] = NFSGETATTRBIT_STATFS0;                           \
+       (b)->bits[1] = NFSGETATTRBIT_STATFS1;                           \
+       (b)->bits[2] = NFSGETATTRBIT_STATFS2;                           \
+} while (0)
+
 #define        NFSISSETSTATFS_ATTRBIT(b)                                       
\
                (((b)->bits[0] & NFSATTRBIT_STATFS0) ||                 \
-                ((b)->bits[1] & NFSATTRBIT_STATFS1))
+                ((b)->bits[1] & NFSATTRBIT_STATFS1) ||                 \
+                ((b)->bits[2] & NFSATTRBIT_STATFS2))
+
 #define        NFSCLRSTATFS_ATTRBIT(b) do {                                    
\
-               (b)->bits[0] &= ~NFSATTRBIT_STATFS0;                    \
-               (b)->bits[1] &= ~NFSATTRBIT_STATFS1; } while (0)
+       (b)->bits[0] &= ~NFSATTRBIT_STATFS0;                            \
+       (b)->bits[1] &= ~NFSATTRBIT_STATFS1;                            \
+       (b)->bits[2] &= ~NFSATTRBIT_STATFS2;                            \
+} while (0)
+
 #define        NFSREADDIRPLUS_ATTRBIT(b) do {                                  
\
-               (b)->bits[0] = NFSATTRBIT_READDIRPLUS0;                 \
-               (b)->bits[1] = NFSATTRBIT_READDIRPLUS1; } while (0)
+       (b)->bits[0] = NFSATTRBIT_READDIRPLUS0;                         \
+       (b)->bits[1] = NFSATTRBIT_READDIRPLUS1;                         \
+       (b)->bits[2] = NFSATTRBIT_READDIRPLUS2;                         \
+} while (0)
+
 #define        NFSREFERRAL_ATTRBIT(b) do {                                     
\
-               (b)->bits[0] = NFSATTRBIT_REFERRAL0;                    \
-               (b)->bits[1] = NFSATTRBIT_REFERRAL1; } while (0)
+       (b)->bits[0] = NFSATTRBIT_REFERRAL0;                            \
+       (b)->bits[1] = NFSATTRBIT_REFERRAL1;                            \
+       (b)->bits[2] = NFSATTRBIT_REFERRAL2;                            \
+} while (0)
 
 /*
  * Store uid, gid creds that were used when the stateid was acquired.
@@ -529,6 +592,9 @@ struct nfsrv_descript {
        int                     nd_gssnamelen;  /* principal name length */
        char                    *nd_gssname;    /* principal name */
        uint32_t                *nd_slotseq;    /* ptr to slot seq# in req */
+       uint8_t                 nd_sessionid[NFSX_V4SESSIONID]; /* Session id */
+       uint32_t                nd_slotid;      /* Slotid for this RPC */
+       SVCXPRT                 *nd_xprt;       /* Server RPC handle */
 };
 
 #define        nd_princlen     nd_gssnamelen
@@ -562,6 +628,8 @@ struct nfsrv_descript {
 #define        ND_NFSCL                0x01000000
 #define        ND_NFSV41               0x02000000
 #define        ND_HASSEQUENCE          0x04000000
+#define        ND_CACHETHIS            0x08000000
+#define        ND_LASTOP               0x10000000
 
 /*
  * ND_GSS should be the "or" of all GSS type authentications.

Modified: head/sys/fs/nfs/nfs_commonkrpc.c
==============================================================================
--- head/sys/fs/nfs/nfs_commonkrpc.c    Tue Jul  1 20:00:35 2014        
(r268114)
+++ head/sys/fs/nfs/nfs_commonkrpc.c    Tue Jul  1 20:47:16 2014        
(r268115)
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/vnode.h>
 
 #include <rpc/rpc.h>
+#include <rpc/krpc.h>
 
 #include <kgssapi/krb5/kcrypto.h>
 
@@ -738,8 +739,12 @@ tryagain:
        }
 
        nd->nd_mrep = NULL;
-       stat = CLNT_CALL_MBUF(nrp->nr_client, &ext, procnum, nd->nd_mreq,
-           &nd->nd_mrep, timo);
+       if (clp != NULL && sep != NULL)
+               stat = clnt_bck_call(nrp->nr_client, &ext, procnum,
+                   nd->nd_mreq, &nd->nd_mrep, timo, sep->nfsess_xprt);
+       else
+               stat = CLNT_CALL_MBUF(nrp->nr_client, &ext, procnum,
+                   nd->nd_mreq, &nd->nd_mrep, timo);
 
        if (rep != NULL) {
                /*
@@ -794,7 +799,8 @@ tryagain:
        nd->nd_md = nd->nd_mrep;
        nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t);
        nd->nd_repstat = 0;
-       if (nd->nd_procnum != NFSPROC_NULL) {
+       if (nd->nd_procnum != NFSPROC_NULL &&
+           nd->nd_procnum != NFSV4PROC_CBNULL) {
                /* If sep == NULL, set it to the default in nmp. */
                if (sep == NULL && nmp != NULL)
                        sep = NFSMNT_MDSSESSION(nmp);
@@ -826,11 +832,20 @@ tryagain:
                        /*
                         * If the first op is Sequence, free up the slot.
                         */
-                       if (nmp != NULL && i == NFSV4OP_SEQUENCE && j != 0)
+                       if ((nmp != NULL && i == NFSV4OP_SEQUENCE && j != 0) ||
+                           (clp != NULL && i == NFSV4OP_CBSEQUENCE && j != 0))
                                NFSCL_DEBUG(1, "failed seq=%d\n", j);
-                       if (nmp != NULL && i == NFSV4OP_SEQUENCE && j == 0) {
-                               NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID +
-                                   5 * NFSX_UNSIGNED);
+                       if ((nmp != NULL && i == NFSV4OP_SEQUENCE && j == 0) ||
+                           (clp != NULL && i == NFSV4OP_CBSEQUENCE && j == 0)
+                           ) {
+                               if (i == NFSV4OP_SEQUENCE)
+                                       NFSM_DISSECT(tl, uint32_t *,
+                                           NFSX_V4SESSIONID +
+                                           5 * NFSX_UNSIGNED);
+                               else
+                                       NFSM_DISSECT(tl, uint32_t *,
+                                           NFSX_V4SESSIONID +
+                                           4 * NFSX_UNSIGNED);
                                mtx_lock(&sep->nfsess_mtx);
                                tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
                                retseq = fxdr_unsigned(uint32_t, *tl++);

Modified: head/sys/fs/nfs/nfs_commonport.c
==============================================================================
--- head/sys/fs/nfs/nfs_commonport.c    Tue Jul  1 20:00:35 2014        
(r268114)
+++ head/sys/fs/nfs/nfs_commonport.c    Tue Jul  1 20:47:16 2014        
(r268115)
@@ -112,6 +112,7 @@ MALLOC_DEFINE(M_NEWNFSDEVINFO, "NFSCL de
 MALLOC_DEFINE(M_NEWNFSSOCKREQ, "NFSCL sockreq", "NFS Sock Req");
 MALLOC_DEFINE(M_NEWNFSCLDS, "NFSCL session", "NFSv4.1 Session");
 MALLOC_DEFINE(M_NEWNFSLAYRECALL, "NFSCL layrecall", "NFSv4.1 Layout Recall");
+MALLOC_DEFINE(M_NEWNFSDSESSION, "NFSD session", "NFSD Session for a client");
 
 /*
  * Definition of mutex locks.

Modified: head/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- head/sys/fs/nfs/nfs_commonsubs.c    Tue Jul  1 20:00:35 2014        
(r268114)
+++ head/sys/fs/nfs/nfs_commonsubs.c    Tue Jul  1 20:47:16 2014        
(r268115)
@@ -1733,6 +1733,23 @@ nfsv4_loadattr(struct nfsrv_descript *nd
                        }
                        attrsum += NFSX_HYPER;
                        break;
+               case NFSATTRBIT_SUPPATTREXCLCREAT:
+                       retnotsup = 0;
+                       error = nfsrv_getattrbits(nd, &retattrbits,
+                           &cnt, &retnotsup);
+                       if (error)
+                           goto nfsmout;
+                       if (compare && !(*retcmpp)) {
+                          NFSSETSUPP_ATTRBIT(&checkattrbits);
+                          NFSCLRNOTSETABLE_ATTRBIT(&checkattrbits);
+                          NFSCLRBIT_ATTRBIT(&checkattrbits,
+                               NFSATTRBIT_TIMEACCESSSET);
+                          if (!NFSEQUAL_ATTRBIT(&retattrbits, &checkattrbits)
+                              || retnotsup)
+                               *retcmpp = NFSERR_NOTSAME;
+                       }
+                       attrsum += cnt;
+                       break;
                default:
                        printf("EEK! nfsv4_loadattr unknown attr=%d\n",
                                bitpos);
@@ -2469,6 +2486,12 @@ nfsv4_fillattr(struct nfsrv_descript *nd
                        txdr_hyper(uquad, tl);
                        retnum += NFSX_HYPER;
                        break;
+               case NFSATTRBIT_SUPPATTREXCLCREAT:
+                       NFSSETSUPP_ATTRBIT(&attrbits);
+                       NFSCLRNOTSETABLE_ATTRBIT(&attrbits);
+                       NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET);
+                       retnum += nfsrv_putattrbit(nd, &attrbits);
+                       break;
                default:
                        printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos);
                };
@@ -3663,6 +3686,9 @@ nfsmout:
 
 /*
  * Handle an NFSv4.1 Sequence request for the session.
+ * If reply != NULL, use it to return the cached reply, as required.
+ * The client gets a cached reply via this call for callbacks, however the
+ * server gets a cached reply via the nfsv4_seqsess_cachereply() call.
  */
 int
 nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot,
@@ -3671,7 +3697,8 @@ nfsv4_seqsession(uint32_t seqid, uint32_
        int error;
 
        error = 0;
-       *reply = NULL;
+       if (reply != NULL)
+               *reply = NULL;
        if (slotid > maxslot)
                return (NFSERR_BADSLOT);
        if (seqid == slots[slotid].nfssl_seq) {
@@ -3679,13 +3706,18 @@ nfsv4_seqsession(uint32_t seqid, uint32_
                if (slots[slotid].nfssl_inprog != 0)
                        error = NFSERR_DELAY;
                else if (slots[slotid].nfssl_reply != NULL) {
-                       *reply = slots[slotid].nfssl_reply;
-                       slots[slotid].nfssl_reply = NULL;
+                       if (reply != NULL) {
+                               *reply = slots[slotid].nfssl_reply;
+                               slots[slotid].nfssl_reply = NULL;
+                       }
                        slots[slotid].nfssl_inprog = 1;
+                       error = NFSERR_REPLYFROMCACHE;
                } else
-                       error = NFSERR_SEQMISORDERED;
+                       /* No reply cached, so just do it. */
+                       slots[slotid].nfssl_inprog = 1;
        } else if ((slots[slotid].nfssl_seq + 1) == seqid) {
-               m_freem(slots[slotid].nfssl_reply);
+               if (slots[slotid].nfssl_reply != NULL)
+                       m_freem(slots[slotid].nfssl_reply);
                slots[slotid].nfssl_reply = NULL;
                slots[slotid].nfssl_inprog = 1;
                slots[slotid].nfssl_seq++;
@@ -3696,12 +3728,22 @@ nfsv4_seqsession(uint32_t seqid, uint32_
 
 /*
  * Cache this reply for the slot.
+ * Use the "rep" argument to return the cached reply if repstat is set to
+ * NFSERR_REPLYFROMCACHE. The client never sets repstat to this value.
  */
 void
-nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, struct mbuf 
*rep)
+nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, int repstat,
+   struct mbuf **rep)
 {
 
-       slots[slotid].nfssl_reply = rep;
+       if (repstat == NFSERR_REPLYFROMCACHE) {
+               *rep = slots[slotid].nfssl_reply;
+               slots[slotid].nfssl_reply = NULL;
+       } else {
+               if (slots[slotid].nfssl_reply != NULL)
+                       m_freem(slots[slotid].nfssl_reply);
+               slots[slotid].nfssl_reply = *rep;
+       }
        slots[slotid].nfssl_inprog = 0;
 }
 
@@ -3713,9 +3755,36 @@ nfsv4_setsequence(struct nfsmount *nmp, 
     struct nfsclsession *sep, int dont_replycache)
 {
        uint32_t *tl, slotseq = 0;
+       int error, maxslot, slotpos;
+       uint8_t sessionid[NFSX_V4SESSIONID];
+
+       error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, &slotseq,
+           sessionid);
+       if (error != 0)
+               return;
+       KASSERT(maxslot >= 0, ("nfscl_setsequence neg maxslot"));
+
+       /* Build the Sequence arguments. */
+       NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
+       bcopy(sessionid, tl, NFSX_V4SESSIONID);
+       tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
+       nd->nd_slotseq = tl;
+       *tl++ = txdr_unsigned(slotseq);
+       *tl++ = txdr_unsigned(slotpos);
+       *tl++ = txdr_unsigned(maxslot);
+       if (dont_replycache == 0)
+               *tl = newnfs_true;
+       else
+               *tl = newnfs_false;
+       nd->nd_flag |= ND_HASSEQUENCE;
+}
+
+int
+nfsv4_sequencelookup(struct nfsmount *nmp, struct nfsclsession *sep,
+    int *slotposp, int *maxslotp, uint32_t *slotseqp, uint8_t *sessionid)
+{
        int i, maxslot, slotpos;
        uint64_t bitval;
-       uint8_t sessionid[NFSX_V4SESSIONID];
 
        /* Find an unused slot. */
        slotpos = -1;
@@ -3728,7 +3797,7 @@ nfsv4_setsequence(struct nfsmount *nmp, 
                                slotpos = i;
                                sep->nfsess_slots |= bitval;
                                sep->nfsess_slotseq[i]++;
-                               slotseq = sep->nfsess_slotseq[i];
+                               *slotseqp = sep->nfsess_slotseq[i];
                                break;
                        }
                        bitval <<= 1;
@@ -3739,10 +3808,11 @@ nfsv4_setsequence(struct nfsmount *nmp, 
                         * This RPC attempt will fail when it calls
                         * newnfs_request().
                         */
-                       if ((nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF)
+                       if (nmp != NULL &&
+                           (nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF)
                            != 0) {
                                mtx_unlock(&sep->nfsess_mtx);
-                               return;
+                               return (ESTALE);
                        }
                        /* Wake up once/sec, to check for a forced dismount. */
                        (void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx,
@@ -3758,21 +3828,9 @@ nfsv4_setsequence(struct nfsmount *nmp, 
        }
        bcopy(sep->nfsess_sessionid, sessionid, NFSX_V4SESSIONID);
        mtx_unlock(&sep->nfsess_mtx);
-       KASSERT(maxslot >= 0, ("nfscl_setsequence neg maxslot"));
-
-       /* Build the Sequence arguments. */
-       NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
-       bcopy(sessionid, tl, NFSX_V4SESSIONID);
-       tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
-       nd->nd_slotseq = tl;
-       *tl++ = txdr_unsigned(slotseq);
-       *tl++ = txdr_unsigned(slotpos);
-       *tl++ = txdr_unsigned(maxslot);
-       if (dont_replycache == 0)
-               *tl = newnfs_true;
-       else
-               *tl = newnfs_false;
-       nd->nd_flag |= ND_HASSEQUENCE;
+       *slotposp = slotpos;
+       *maxslotp = maxslot;
+       return (0);
 }
 
 /*

Modified: head/sys/fs/nfs/nfs_var.h
==============================================================================
--- head/sys/fs/nfs/nfs_var.h   Tue Jul  1 20:00:35 2014        (r268114)
+++ head/sys/fs/nfs/nfs_var.h   Tue Jul  1 20:47:16 2014        (r268115)
@@ -61,6 +61,7 @@ union nethostaddr;
 struct nfsstate;
 struct nfslock;
 struct nfsclient;
+struct nfsdsession;
 struct nfslockconflict;
 struct nfsd_idargs;
 struct nfsd_clid;
@@ -90,8 +91,11 @@ NFS_READDIR_ARGS;
 /* nfs_nfsdstate.c */
 int nfsrv_setclient(struct nfsrv_descript *, struct nfsclient **,
     nfsquad_t *, nfsquad_t *, NFSPROC_T *);
-int nfsrv_getclient(nfsquad_t, int, struct nfsclient **, nfsquad_t,
-    struct nfsrv_descript *, NFSPROC_T *);
+int nfsrv_getclient(nfsquad_t, int, struct nfsclient **, struct nfsdsession *,
+    nfsquad_t, uint32_t, struct nfsrv_descript *, NFSPROC_T *);
+int nfsrv_destroyclient(nfsquad_t, NFSPROC_T *);
+int nfsrv_destroysession(struct nfsrv_descript *, uint8_t *);
+int nfsrv_freestateid(struct nfsrv_descript *, nfsv4stateid_t *, NFSPROC_T *);
 int nfsrv_adminrevoke(struct nfsd_clid *, NFSPROC_T *);
 void nfsrv_dumpclients(struct nfsd_dumpclients *, int);
 void nfsrv_dumplocks(vnode_t, struct nfsd_dumplocks *, int, NFSPROC_T *);
@@ -105,8 +109,8 @@ int nfsrv_opencheck(nfsquad_t, nfsv4stat
     vnode_t, struct nfsrv_descript *, NFSPROC_T *, int);
 int nfsrv_openupdate(vnode_t, struct nfsstate *, nfsquad_t,
     nfsv4stateid_t *, struct nfsrv_descript *, NFSPROC_T *);
-int nfsrv_delegupdate(nfsquad_t, nfsv4stateid_t *, vnode_t, int,
-    struct ucred *, NFSPROC_T *);
+int nfsrv_delegupdate(struct nfsrv_descript *, nfsquad_t, nfsv4stateid_t *,
+    vnode_t, int, struct ucred *, NFSPROC_T *);
 int nfsrv_releaselckown(struct nfsstate *, nfsquad_t, NFSPROC_T *);
 void nfsrv_zapclient(struct nfsclient *, NFSPROC_T *);
 int nfssvc_idname(struct nfsd_idargs *);
@@ -127,6 +131,10 @@ int nfsrv_checkgetattr(struct nfsrv_desc
 int nfsrv_nfsuserdport(u_short, NFSPROC_T *);
 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 *);
+void nfsrv_cache_session(uint8_t *, uint32_t, int, struct mbuf **);
 
 /* nfs_nfsdserv.c */
 int nfsrvd_access(struct nfsrv_descript *, int,
@@ -211,10 +219,27 @@ int nfsrvd_releaselckown(struct nfsrv_de
     vnode_t, NFSPROC_T *, struct nfsexstuff *);
 int nfsrvd_pathconf(struct nfsrv_descript *, int,
     vnode_t, NFSPROC_T *, struct nfsexstuff *);
+int nfsrvd_exchangeid(struct nfsrv_descript *, int,
+    vnode_t, NFSPROC_T *, struct nfsexstuff *);
+int nfsrvd_createsession(struct nfsrv_descript *, int,
+    vnode_t, NFSPROC_T *, struct nfsexstuff *);
+int nfsrvd_sequence(struct nfsrv_descript *, int,
+    vnode_t, NFSPROC_T *, struct nfsexstuff *);
+int nfsrvd_reclaimcomplete(struct nfsrv_descript *, int,
+    vnode_t, NFSPROC_T *, struct nfsexstuff *);
+int nfsrvd_destroyclientid(struct nfsrv_descript *, int,
+    vnode_t, NFSPROC_T *, struct nfsexstuff *);
+int nfsrvd_destroysession(struct nfsrv_descript *, int,
+    vnode_t, NFSPROC_T *, struct nfsexstuff *);
+int nfsrvd_freestateid(struct nfsrv_descript *, int,
+    vnode_t, NFSPROC_T *, struct nfsexstuff *);
+int nfsrvd_notsupp(struct nfsrv_descript *, int,
+    vnode_t, NFSPROC_T *, struct nfsexstuff *);
 
 /* nfs_nfsdsocket.c */
 void nfsrvd_rephead(struct nfsrv_descript *);
-void nfsrvd_dorpc(struct nfsrv_descript *, int, NFSPROC_T *);
+void nfsrvd_dorpc(struct nfsrv_descript *, int, u_char *, int, u_int32_t,
+    NFSPROC_T *);
 
 /* nfs_nfsdcache.c */
 void nfsrvd_initcache(void);
@@ -264,9 +289,11 @@ int nfsv4_getipaddr(struct nfsrv_descrip
     int *);
 int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *,
     struct mbuf **, uint16_t);
-void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, struct mbuf *);
+void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, int, struct mbuf **);
 void nfsv4_setsequence(struct nfsmount *, struct nfsrv_descript *,
     struct nfsclsession *, int);
+int nfsv4_sequencelookup(struct nfsmount *, struct nfsclsession *, int *,
+    int *, uint32_t *, uint8_t *);
 void nfsv4_freeslot(struct nfsclsession *, int);
 
 /* nfs_clcomsubs.c */
@@ -322,6 +349,8 @@ int nfsrv_parsename(struct nfsrv_descrip
     NFSPATHLEN_T *);
 void nfsd_init(void);
 int nfsd_checkrootexp(struct nfsrv_descript *);
+void nfsd_getminorvers(struct nfsrv_descript *, u_char *, u_char **, int *,
+    u_int32_t *);
 
 /* nfs_clvfsops.c */
 void nfscl_retopts(struct nfsmount *, char *, size_t);
@@ -628,6 +657,7 @@ int nfsvno_advlock(vnode_t, int, u_int64
 int nfsrv_v4rootexport(void *, struct ucred *, NFSPROC_T *);
 int nfsvno_testexp(struct nfsrv_descript *, struct nfsexstuff *);
 uint32_t nfsrv_hashfh(fhandle_t *);
+uint32_t nfsrv_hashsessionid(uint8_t *);
 void nfsrv_backupstable(void);
 
 /* nfs_commonkrpc.c */

Modified: head/sys/fs/nfs/nfsclstate.h
==============================================================================
--- head/sys/fs/nfs/nfsclstate.h        Tue Jul  1 20:00:35 2014        
(r268114)
+++ head/sys/fs/nfs/nfsclstate.h        Tue Jul  1 20:47:16 2014        
(r268115)
@@ -57,6 +57,7 @@ struct nfsclsession {
        struct mtx      nfsess_mtx;
        struct nfsslot  nfsess_cbslots[NFSV4_CBSLOTS];
        nfsquad_t       nfsess_clientid;
+       SVCXPRT         *nfsess_xprt;           /* For backchannel callback */
        uint32_t        nfsess_slotseq[64];     /* Max for 64bit nm_slots */
        uint64_t        nfsess_slots;
        uint32_t        nfsess_sequenceid;

Modified: head/sys/fs/nfs/nfsdport.h
==============================================================================
--- head/sys/fs/nfs/nfsdport.h  Tue Jul  1 20:00:35 2014        (r268114)
+++ head/sys/fs/nfs/nfsdport.h  Tue Jul  1 20:47:16 2014        (r268115)
@@ -115,3 +115,9 @@ struct nfsexstuff {
 #define        NFSRV_MINFH     (sizeof (fhandle_t))
 #define        NFSRV_MAXFH     (sizeof (fhandle_t))
 
+/* Use this macro for debug printfs. */
+#define        NFSD_DEBUG(level, ...)  do {                                    
\
+               if (nfsd_debuglevel >= (level))                         \
+                       printf(__VA_ARGS__);                            \
+       } while (0)
+

Modified: head/sys/fs/nfs/nfsport.h
==============================================================================
--- head/sys/fs/nfs/nfsport.h   Tue Jul  1 20:00:35 2014        (r268114)
+++ head/sys/fs/nfs/nfsport.h   Tue Jul  1 20:47:16 2014        (r268115)
@@ -638,6 +638,9 @@ void nfsrvd_rcv(struct socket *, void *,
 #define        NFSUNLOCKSOCKREQ(r)     mtx_unlock(&((r)->nr_mtx))
 #define        NFSLOCKDS(d)            mtx_lock(&((d)->nfsclds_mtx))
 #define        NFSUNLOCKDS(d)          mtx_unlock(&((d)->nfsclds_mtx))
+#define        NFSSESSIONMUTEXPTR(s)   (&((s)->mtx))
+#define        NFSLOCKSESSION(s)       mtx_lock(&((s)->mtx))
+#define        NFSUNLOCKSESSION(s)     mtx_unlock(&((s)->mtx))
 
 /*
  * Use these macros to initialize/free a mutex.
@@ -733,6 +736,7 @@ MALLOC_DECLARE(M_NEWNFSDEVINFO);
 MALLOC_DECLARE(M_NEWNFSSOCKREQ);
 MALLOC_DECLARE(M_NEWNFSCLDS);
 MALLOC_DECLARE(M_NEWNFSLAYRECALL);
+MALLOC_DECLARE(M_NEWNFSDSESSION);
 #define        M_NFSRVCACHE    M_NEWNFSRVCACHE
 #define        M_NFSDCLIENT    M_NEWNFSDCLIENT
 #define        M_NFSDSTATE     M_NEWNFSDSTATE
@@ -758,6 +762,7 @@ MALLOC_DECLARE(M_NEWNFSLAYRECALL);
 #define        M_NFSSOCKREQ    M_NEWNFSSOCKREQ
 #define        M_NFSCLDS       M_NEWNFSCLDS
 #define        M_NFSLAYRECALL  M_NEWNFSLAYRECALL
+#define        M_NFSDSESSION   M_NEWNFSDSESSION
 
 #define        NFSINT_SIGMASK(set)                                             
\
        (SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) ||       \

Modified: head/sys/fs/nfs/nfsproto.h
==============================================================================
--- head/sys/fs/nfs/nfsproto.h  Tue Jul  1 20:00:35 2014        (r268114)
+++ head/sys/fs/nfs/nfsproto.h  Tue Jul  1 20:47:16 2014        (r268115)
@@ -389,9 +389,13 @@
 #define        NFSV4OPEN_CLAIMPREVIOUS         1
 #define        NFSV4OPEN_CLAIMDELEGATECUR      2
 #define        NFSV4OPEN_CLAIMDELEGATEPREV     3
+#define        NFSV4OPEN_CLAIMFH               4
+#define        NFSV4OPEN_CLAIMDELEGATECURFH    5
+#define        NFSV4OPEN_CLAIMDELEGATEPREVFH   6
 #define        NFSV4OPEN_DELEGATENONE          0
 #define        NFSV4OPEN_DELEGATEREAD          1
 #define        NFSV4OPEN_DELEGATEWRITE         2
+#define        NFSV4OPEN_DELEGATENONEEXT       3
 #define        NFSV4OPEN_LIMITSIZE             1
 #define        NFSV4OPEN_LIMITBLOCKS           2
 
@@ -479,6 +483,14 @@
 #define        NFSV4OPEN_ACCESSREAD            0x00000001
 #define        NFSV4OPEN_ACCESSWRITE           0x00000002
 #define        NFSV4OPEN_ACCESSBOTH            0x00000003
+#define        NFSV4OPEN_WANTDELEGMASK         0x0000ff00
+#define        NFSV4OPEN_WANTREADDELEG         0x00000100
+#define        NFSV4OPEN_WANTWRITEDELEG        0x00000200
+#define        NFSV4OPEN_WANTANYDELEG          0x00000300
+#define        NFSV4OPEN_WANTNODELEG           0x00000400
+#define        NFSV4OPEN_WANTCANCEL            0x00000500
+#define        NFSV4OPEN_WANTSIGNALDELEG       0x00010000
+#define        NFSV4OPEN_WANTPUSHDELEG         0x00020000
 
 #define        NFSV4OPEN_DENYNONE              0x00000000
 #define        NFSV4OPEN_DENYREAD              0x00000001
@@ -486,16 +498,35 @@
 #define        NFSV4OPEN_DENYBOTH              0x00000003
 
 /*
+ * Delegate_none_ext reply values.
+ */
+#define        NFSV4OPEN_NOTWANTED             0
+#define        NFSV4OPEN_CONTENTION            1
+#define        NFSV4OPEN_RESOURCE              2
+#define        NFSV4OPEN_NOTSUPPFTYPE          3
+#define        NFSV4OPEN_NOTSUPPWRITEFTYPE     4
+#define        NFSV4OPEN_NOTSUPPUPGRADE        5
+#define        NFSV4OPEN_NOTSUPPDOWNGRADE      6
+#define        NFSV4OPEN_CANCELLED             7
+#define        NFSV4OPEN_ISDIR                 8
+
+/*
  * Open result flags
- * (The first two are in the spec. The rest are used internally.)
+ * (The first four are in the spec. The rest are used internally.)
  */
 #define        NFSV4OPEN_RESULTCONFIRM         0x00000002
 #define        NFSV4OPEN_LOCKTYPEPOSIX         0x00000004
+#define        NFSV4OPEN_PRESERVEUNLINKED      0x00000008
+#define        NFSV4OPEN_MAYNOTIFYLOCK         0x00000020
 #define        NFSV4OPEN_RFLAGS                                                
\
-               (NFSV4OPEN_RESULTCONFIRM | NFSV4OPEN_LOCKTYPEPOSIX)
+    (NFSV4OPEN_RESULTCONFIRM | NFSV4OPEN_LOCKTYPEPOSIX |               \
+    NFSV4OPEN_PRESERVEUNLINKED | NFSV4OPEN_MAYNOTIFYLOCK)
 #define        NFSV4OPEN_RECALL                0x00010000
 #define        NFSV4OPEN_READDELEGATE          0x00020000
 #define        NFSV4OPEN_WRITEDELEGATE         0x00040000
+#define        NFSV4OPEN_WDRESOURCE            0x00080000
+#define        NFSV4OPEN_WDCONTENTION          0x00100000
+#define        NFSV4OPEN_WDNOTWANTED           0x00200000
 
 /*
  * NFS V4 File Handle types
@@ -805,6 +836,27 @@ struct nfsv3_sattr {
 #define        NFSATTRBIT_TIMEMODIFY           53
 #define        NFSATTRBIT_TIMEMODIFYSET        54
 #define        NFSATTRBIT_MOUNTEDONFILEID      55
+#define        NFSATTRBIT_DIRNOTIFDELAY        56
+#define        NFSATTRBIT_DIRENTNOTIFDELAY     57
+#define        NFSATTRBIT_DACL                 58
+#define        NFSATTRBIT_SACL                 59
+#define        NFSATTRBIT_CHANGEPOLICY         60
+#define        NFSATTRBIT_FSSTATUS             61
+#define        NFSATTRBIT_FSLAYOUTTYPE         62
+#define        NFSATTRBIT_LAYOUTHINT           63
+#define        NFSATTRBIT_LAYOUTTYPE           64
+#define        NFSATTRBIT_LAYOUTBLKSIZE        65
+#define        NFSATTRBIT_LAYOUTALIGNMENT      66
+#define        NFSATTRBIT_FSLOCATIONSINFO      67
+#define        NFSATTRBIT_MDSTHRESHOLD         68
+#define        NFSATTRBIT_RETENTIONGET         69
+#define        NFSATTRBIT_RETENTIONSET         70
+#define        NFSATTRBIT_RETENTEVTGET         71
+#define        NFSATTRBIT_RETENTEVTSET         72
+#define        NFSATTRBIT_RETENTIONHOLD        73
+#define        NFSATTRBIT_MODESETMASKED        74
+#define        NFSATTRBIT_SUPPATTREXCLCREAT    75
+#define        NFSATTRBIT_FSCHARSETCAP         76
 
 #define        NFSATTRBM_SUPPORTEDATTRS        0x00000001
 #define        NFSATTRBM_TYPE                  0x00000002
@@ -862,8 +914,29 @@ struct nfsv3_sattr {
 #define        NFSATTRBM_TIMEMODIFY            0x00200000
 #define        NFSATTRBM_TIMEMODIFYSET         0x00400000
 #define        NFSATTRBM_MOUNTEDONFILEID       0x00800000
+#define        NFSATTRBM_DIRNOTIFDELAY         0x01000000
+#define        NFSATTRBM_DIRENTNOTIFDELAY      0x02000000
+#define        NFSATTRBM_DACL                  0x04000000
+#define        NFSATTRBM_SACL                  0x08000000
+#define        NFSATTRBM_CHANGEPOLICY          0x10000000
+#define        NFSATTRBM_FSSTATUS              0x20000000
+#define        NFSATTRBM_FSLAYOUTTYPE          0x40000000
+#define        NFSATTRBM_LAYOUTHINT            0x80000000
+#define        NFSATTRBM_LAYOUTTYPE            0x00000001
+#define        NFSATTRBM_LAYOUTBLKSIZE         0x00000002
+#define        NFSATTRBM_LAYOUTALIGNMENT       0x00000004
+#define        NFSATTRBM_FSLOCATIONSINFO       0x00000008
+#define        NFSATTRBM_MDSTHRESHOLD          0x00000010
+#define        NFSATTRBM_RETENTIONGET          0x00000020
+#define        NFSATTRBM_RETENTIONSET          0x00000040
+#define        NFSATTRBM_RETENTEVTGET          0x00000080
+#define        NFSATTRBM_RETENTEVTSET          0x00000100
+#define        NFSATTRBM_RETENTIONHOLD         0x00000200
+#define        NFSATTRBM_MODESETMASKED         0x00000400
+#define        NFSATTRBM_SUPPATTREXCLCREAT     0x00000800
+#define        NFSATTRBM_FSCHARSETCAP          0x00001000
 
-#define        NFSATTRBIT_MAX                  56
+#define        NFSATTRBIT_MAX                  77
 
 /*
  * Sets of attributes that are supported, by words in the bitmap.
@@ -871,6 +944,7 @@ struct nfsv3_sattr {
 /*
  * NFSATTRBIT_SUPPORTED - SUPP0 - bits 0<->31
  *                       SUPP1 - bits 32<->63
+ *                       SUPP2 - bits 64<->95
  */
 #define        NFSATTRBIT_SUPP0                                                
\
        (NFSATTRBM_SUPPORTEDATTRS |                                     \
@@ -937,6 +1011,8 @@ struct nfsv3_sattr {
 #define        NFSATTRBIT_SUPP1        NFSATTRBIT_S1
 #endif
 
+#define        NFSATTRBIT_SUPP2        NFSATTRBM_SUPPATTREXCLCREAT
+
 /*
  * NFSATTRBIT_SUPPSETONLY is the OR of NFSATTRBIT_TIMEACCESSSET and
  * NFSATTRBIT_TIMEMODIFYSET.
@@ -947,6 +1023,7 @@ struct nfsv3_sattr {
 /*
  * NFSATTRBIT_SETABLE - SETABLE0 - bits 0<->31
  *                     SETABLE1 - bits 32<->63
+ *                     SETABLE2 - bits 64<->95
  */
 #define        NFSATTRBIT_SETABLE0                                             
\
        (NFSATTRBM_SIZE |                                               \
@@ -957,6 +1034,7 @@ struct nfsv3_sattr {
        NFSATTRBM_OWNERGROUP |                                          \
        NFSATTRBM_TIMEACCESSSET |                                       \
        NFSATTRBM_TIMEMODIFYSET)
+#define        NFSATTRBIT_SETABLE2             0
 
 /*
  * Set of attributes that the getattr vnode op needs.
@@ -987,6 +1065,11 @@ struct nfsv3_sattr {
        NFSATTRBM_TIMEMODIFY)
 
 /*
+ * NFSATTRBIT_GETATTR2 - bits 64<->95
+ */
+#define        NFSATTRBIT_GETATTR2             0
+
+/*
  * Subset of the above that the Write RPC gets.
  * OR of the following bits.
  * NFSATTRBIT_WRITEGETATTR0 - bits 0<->31
@@ -1013,6 +1096,11 @@ struct nfsv3_sattr {
        NFSATTRBM_TIMEMODIFY)
 
 /*
+ * NFSATTRBIT_WRITEGETATTR2 - bits 64<->95
+ */
+#define        NFSATTRBIT_WRITEGETATTR2        0
+
+/*
  * Set of attributes that the wccattr operation op needs.
  * OR of the following bits.
  * NFSATTRBIT_WCCATTR0 - bits 0<->31
@@ -1026,6 +1114,11 @@ struct nfsv3_sattr {
        (NFSATTRBM_TIMEMODIFY)
 
 /*
+ * NFSATTRBIT_WCCATTR2 - bits 64<->95
+ */
+#define        NFSATTRBIT_WCCATTR2             0
+
+/*
  * NFSATTRBIT_CBGETATTR0 - bits 0<->31
  */
 #define        NFSATTRBIT_CBGETATTR0   (NFSATTRBM_CHANGE | NFSATTRBM_SIZE)
@@ -1036,6 +1129,11 @@ struct nfsv3_sattr {
 #define        NFSATTRBIT_CBGETATTR1           0x0
 
 /*
+ * NFSATTRBIT_CBGETATTR2 - bits 64<->95
+ */
+#define        NFSATTRBIT_CBGETATTR2           0x0
+
+/*
  * Sets of attributes that require a VFS_STATFS() call to get the
  * values of.
  * NFSATTRBIT_STATFS0 - bits 0<->31
@@ -1067,6 +1165,11 @@ struct nfsv3_sattr {
        NFSATTRBM_TIMEDELTA)
 
 /*
+ * NFSATTRBIT_STATFS2 - bits 64<->95
+ */
+#define        NFSATTRBIT_STATFS2              0
+
+/*
  * These are the bits that are needed by the nfs_statfs() call.
  * (The regular getattr bits are or'd in so the vnode gets the correct
  *  type, etc.)
@@ -1094,6 +1197,11 @@ struct nfsv3_sattr {
                                NFSATTRBM_TIMEDELTA)
 
 /*
+ * NFSGETATTRBIT_STATFS2 - bits 64<->95
+ */
+#define        NFSGETATTRBIT_STATFS2           0
+
+/*
  * Set of attributes for the equivalent of an nfsv3 pathconf rpc.
  * NFSGETATTRBIT_PATHCONF0 - bits 0<->31
  */
@@ -1111,6 +1219,11 @@ struct nfsv3_sattr {
                                NFSATTRBM_NOTRUNC)
 
 /*
+ * NFSGETATTRBIT_PATHCONF2 - bits 64<->95
+ */
+#define        NFSGETATTRBIT_PATHCONF2         0
+
+/*
  * Sets of attributes required by readdir and readdirplus.
  * NFSATTRBIT_READDIRPLUS0     (NFSATTRBIT_GETATTR0 | NFSATTRBIT_FILEHANDLE |
  *                              NFSATTRBIT_RDATTRERROR)
@@ -1118,6 +1231,7 @@ struct nfsv3_sattr {
 #define        NFSATTRBIT_READDIRPLUS0 (NFSATTRBIT_GETATTR0 | 
NFSATTRBM_FILEHANDLE | \
                                NFSATTRBM_RDATTRERROR)
 #define        NFSATTRBIT_READDIRPLUS1 NFSATTRBIT_GETATTR1
+#define        NFSATTRBIT_READDIRPLUS2         0
 
 /*
  * Set of attributes supported by Referral vnodes.
@@ -1125,6 +1239,7 @@ struct nfsv3_sattr {
 #define        NFSATTRBIT_REFERRAL0    (NFSATTRBM_TYPE | NFSATTRBM_FSID |      
\
        NFSATTRBM_RDATTRERROR | NFSATTRBM_FSLOCATIONS)
 #define        NFSATTRBIT_REFERRAL1    NFSATTRBM_MOUNTEDONFILEID
+#define        NFSATTRBIT_REFERRAL2            0
 
 /*
  * Structure for data handled by the statfs rpc. Since some fields are

Modified: head/sys/fs/nfs/nfsrvstate.h
==============================================================================
--- head/sys/fs/nfs/nfsrvstate.h        Tue Jul  1 20:00:35 2014        
(r268114)
+++ head/sys/fs/nfs/nfsrvstate.h        Tue Jul  1 20:47:16 2014        
(r268115)
@@ -42,6 +42,8 @@ LIST_HEAD(nfsclienthashhead, nfsclient);
 LIST_HEAD(nfsstatehead, nfsstate);
 LIST_HEAD(nfslockhead, nfslock);
 LIST_HEAD(nfslockhashhead, nfslockfile);
+LIST_HEAD(nfssessionhead, nfsdsession);
+LIST_HEAD(nfssessionhashhead, nfsdsession);
 
 /*
  * List head for nfsusrgrp.
@@ -64,6 +66,13 @@ TAILQ_HEAD(nfsuserlruhead, nfsusrgrp);
        (&nfsgroupnamehash[((l)>=4?(*(p)+*((p)+1)+*((p)+2)+*((p)+3)):*(p)) \
                % NFSGROUPHASHSIZE])
 
+struct nfssessionhash {
+       struct mtx                      mtx;
+       struct nfssessionhashhead       list;
+};
+#define        NFSSESSIONHASH(f)                                               
\
+       (&nfssessionhash[nfsrv_hashsessionid(f) % NFSSESSIONHASHSIZE])
+
 /*
  * Client server structure for V4. It is doubly linked into two lists.
  * The first is a hash table based on the clientid and the second is a
@@ -76,6 +85,7 @@ struct nfsclient {
        struct nfsstatehead lc_open;            /* Open owner list */
        struct nfsstatehead lc_deleg;           /* Delegations */
        struct nfsstatehead lc_olddeleg;        /* and old delegations */
+       struct nfssessionhead lc_session;       /* List of NFSv4.1 sessions */
        time_t          lc_expiry;              /* Expiry time (sec) */
        time_t          lc_delegtime;           /* Old deleg expiry (sec) */
        nfsquad_t       lc_clientid;            /* 64 bit clientid */
@@ -101,6 +111,43 @@ struct nfsclient {
 #define        CLOPS_RENEWOP           0x0004
 
 /*
+ * Structure for an NFSv4.1 session.
+ * Locking rules for this structure.
+ * To add/delete one of these structures from the lists, you must lock
+ * both: NFSLOCKSESSION(session hashhead) and NFSLOCKSTATE() in that order.
+ * To traverse the lists looking for one of these, you must hold one
+ * of these two locks.
+ * The exception is if the thread holds the exclusive root sleep lock.
+ * In this case, all other nfsd threads are blocked, so locking the
+ * mutexes isn't required.
+ * When manipulating sess_refcnt, NFSLOCKSTATE() must be locked.
+ * When manipulating the fields withinsess_cbsess except nfsess_xprt,
+ * sess_cbsess.nfsess_mtx must be locked.
+ * When manipulating sess_slots and sess_cbsess.nfsess_xprt,
+ * NFSLOCKSESSION(session hashhead) must be locked.
+ */
+struct nfsdsession {
+       uint64_t                sess_refcnt;    /* Reference count. */
+       LIST_ENTRY(nfsdsession) sess_hash;      /* Hash list of sessions. */
+       LIST_ENTRY(nfsdsession) sess_list;      /* List of client sessions. */
+       struct nfsslot          sess_slots[NFSV4_SLOTS];
+       struct nfsclient        *sess_clp;      /* Associated clientid. */
+       uint32_t                sess_crflags;
+       uint32_t                sess_cbprogram;
+       uint32_t                sess_maxreq;
+       uint32_t                sess_maxresp;
+       uint32_t                sess_maxrespcached;
+       uint32_t                sess_maxops;
+       uint32_t                sess_maxslots;
+       uint32_t                sess_cbmaxreq;
+       uint32_t                sess_cbmaxresp;
+       uint32_t                sess_cbmaxrespcached;
+       uint32_t                sess_cbmaxops;
+       uint8_t                 sess_sessionid[NFSX_V4SESSIONID];
+       struct nfsclsession     sess_cbsess;    /* Callback session. */
+};
+
+/*
  * Nfs state structure. I couldn't resist overloading this one, since
  * it makes cleanup, etc. simpler. These structures are used in four ways:
  * - open_owner structures chained off of nfsclient

Modified: head/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clstate.c Tue Jul  1 20:00:35 2014        
(r268114)
+++ head/sys/fs/nfsclient/nfs_clstate.c Tue Jul  1 20:47:16 2014        
(r268115)
@@ -3548,7 +3548,7 @@ out:
                if (clp != NULL) {
                        nfsv4_seqsess_cacherep(slotid,
                            NFSMNT_MDSSESSION(clp->nfsc_nmp)->nfsess_cbslots,
-                           rep);
+                           NFSERR_OK, &rep);
                        NFSUNLOCKCLSTATE();
                } else {
                        NFSUNLOCKCLSTATE();

Modified: head/sys/fs/nfsserver/nfs_nfsdcache.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdcache.c       Tue Jul  1 20:00:35 2014        
(r268114)
+++ head/sys/fs/nfsserver/nfs_nfsdcache.c       Tue Jul  1 20:47:16 2014        
(r268115)
@@ -977,6 +977,9 @@ nfsrvd_refcache(struct nfsrvcache *rp)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to