Date: Tue, 1 Jul 2014 20:47:16 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r268115 - in head/sys: conf fs/nfs fs/nfsclient fs/nfsserver modules/krpc rpc Message-ID: <201407012047.s61KlGYY090389@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407012047.s61KlGYY090389>