svn commit: r253375 - projects/nfsv4.1-server/sys/fs/nfsserver
Rick Macklem
rmacklem at FreeBSD.org
Tue Jul 16 00:05:19 UTC 2013
Author: rmacklem
Date: Tue Jul 16 00:05:17 2013
New Revision: 253375
URL: http://svnweb.freebsd.org/changeset/base/253375
Log:
Merge in changes for the NFSv4.1 server to the first 4 files.
More to come soon.
Modified:
projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdcache.c
projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c
projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdport.c
projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c
Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdcache.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdcache.c Mon Jul 15 23:27:48 2013 (r253374)
+++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdcache.c Tue Jul 16 00:05:17 2013 (r253375)
@@ -811,6 +811,9 @@ APPLESTATIC void
nfsrvd_refcache(struct nfsrvcache *rp)
{
+ if (rp == NULL)
+ /* For NFSv4.1, there is no cache entry. */
+ return;
NFSLOCKCACHE();
if (rp->rc_refcnt < 0)
panic("nfs cache refcnt");
Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c Mon Jul 15 23:27:48 2013 (r253374)
+++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c Tue Jul 16 00:05:17 2013 (r253375)
@@ -304,7 +304,10 @@ nfs_proc(struct nfsrv_descript *nd, u_in
u_int64_t sockref, struct nfsrvcache **rpp)
{
struct thread *td = curthread;
- int cacherep = RC_DOIT, isdgram;
+ int cacherep = RC_DOIT, isdgram, taglen = -1;
+ struct mbuf *m;
+ u_char tag[NFSV4_SMALLSTR + 1], *tagstr = NULL;
+ u_int32_t minorvers = 0;
*rpp = NULL;
if (nd->nd_nam2 == NULL) {
@@ -337,7 +340,14 @@ nfs_proc(struct nfsrv_descript *nd, u_in
nd->nd_retxid = xid;
nd->nd_tcpconntime = NFSD_MONOSEC;
nd->nd_sockref = sockref;
- cacherep = nfsrvd_getcache(nd, so);
+ if ((nd->nd_flag & ND_NFSV4) != 0)
+ nfsd_getminorvers(nd, tag, &tagstr, &taglen,
+ &minorvers);
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ /* NFSv4.1 caches replies in the session slots. */
+ cacherep = RC_DOIT;
+ else
+ cacherep = nfsrvd_getcache(nd, so);
}
/*
@@ -347,13 +357,31 @@ nfs_proc(struct nfsrv_descript *nd, u_in
* RC_DROPIT - just throw the request away
*/
if (cacherep == RC_DOIT) {
- nfsrvd_dorpc(nd, isdgram, td);
- if (nd->nd_repstat == NFSERR_DONTREPLY)
- cacherep = RC_DROPIT;
- else
+ nfsrvd_dorpc(nd, isdgram, tagstr, taglen, minorvers, td);
+ if ((nd->nd_flag & ND_NFSV41) != 0) {
+ if (nd->nd_repstat != NFSERR_REPLYFROMCACHE &&
+ (nd->nd_flag & ND_SAVEREPLY) != 0) {
+ /* Cache a copy of the reply. */
+ m = m_copym(nd->nd_mreq, 0, M_COPYALL,
+ M_WAITOK);
+ } else
+ m = NULL;
+ if ((nd->nd_flag & ND_HASSEQUENCE) != 0)
+ nfsrv_cache_session(nd->nd_sessionid,
+ nd->nd_slotid, nd->nd_repstat, &m);
+ if (nd->nd_repstat == NFSERR_REPLYFROMCACHE)
+ nd->nd_repstat = 0;
cacherep = RC_REPLY;
- *rpp = nfsrvd_updatecache(nd, so);
+ } else {
+ if (nd->nd_repstat == NFSERR_DONTREPLY)
+ cacherep = RC_DROPIT;
+ else
+ cacherep = RC_REPLY;
+ *rpp = nfsrvd_updatecache(nd, so);
+ }
}
+ if (tagstr != NULL && taglen > NFSV4_SMALLSTR)
+ free(tagstr, M_TEMP);
NFSEXITCODE2(0, nd);
return (cacherep);
Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdport.c Mon Jul 15 23:27:48 2013 (r253374)
+++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdport.c Tue Jul 16 00:05:17 2013 (r253375)
@@ -58,6 +58,7 @@ extern struct nfsrv_stablefirst nfsrv_st
extern void (*nfsd_call_servertimer)(void);
extern SVCPOOL *nfsrvd_pool;
extern struct nfsv4lock nfsd_suspend_lock;
+extern struct nfssessionhash nfssessionhash[NFSSESSIONHASHSIZE];
struct vfsoptlist nfsv4root_opt, nfsv4root_newopt;
NFSDLOCKMUTEX;
struct mtx nfs_cache_mutex;
@@ -65,6 +66,7 @@ struct mtx nfs_v4root_mutex;
struct nfsrvfh nfs_rootfh, nfs_pubfh;
int nfs_pubfhset = 0, nfs_rootfhset = 0;
struct proc *nfsd_master_proc = NULL;
+int nfsd_debuglevel = 0;
static pid_t nfsd_master_pid = (pid_t)-1;
static char nfsd_master_comm[MAXCOMLEN + 1];
static struct timeval nfsd_master_start;
@@ -90,6 +92,8 @@ SYSCTL_INT(_vfs_nfsd, OID_AUTO, issue_de
&nfsrv_issuedelegs, 0, "Enable nfsd to issue delegations");
SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_locallocks, CTLFLAG_RW,
&nfsrv_dolocallocks, 0, "Enable nfsd to acquire local locks on files");
+SYSCTL_INT(_vfs_nfsd, OID_AUTO, debuglevel, CTLFLAG_RW, &nfsd_debuglevel,
+ 0, "Debug level for new nfs server");
#define MAX_REORDERED_RPC 16
#define NUM_HEURISTIC 1031
@@ -3245,6 +3249,18 @@ nfsrv_hashfh(fhandle_t *fhp)
}
/*
+ * Calculate a hash value for the sessionid.
+ */
+uint32_t
+nfsrv_hashsessionid(uint8_t *sessionid)
+{
+ uint32_t hashval;
+
+ hashval = hash32_buf(sessionid, NFSX_V4SESSIONID, 0);
+ return (hashval);
+}
+
+/*
* Signal the userland master nfsd to backup the stable restart file.
*/
void
@@ -3278,7 +3294,7 @@ extern int (*nfsd_call_nfsd)(struct thre
static int
nfsd_modevent(module_t mod, int type, void *data)
{
- int error = 0;
+ int error = 0, i;
static int loaded = 0;
switch (type) {
@@ -3290,6 +3306,9 @@ nfsd_modevent(module_t mod, int type, vo
mtx_init(&nfs_v4root_mutex, "nfs_v4root_mutex", NULL, MTX_DEF);
mtx_init(&nfsv4root_mnt.mnt_mtx, "struct mount mtx", NULL,
MTX_DEF);
+ for (i = 0; i < NFSSESSIONHASHSIZE; i++)
+ mtx_init(&nfssessionhash[i].mtx, "nfs_session_mutex",
+ NULL, MTX_DEF);
lockinit(&nfsv4root_mnt.mnt_explock, PVFS, "explock", 0, 0);
nfsrvd_initcache();
nfsd_init();
@@ -3333,6 +3352,8 @@ nfsd_modevent(module_t mod, int type, vo
mtx_destroy(&nfs_cache_mutex);
mtx_destroy(&nfs_v4root_mutex);
mtx_destroy(&nfsv4root_mnt.mnt_mtx);
+ for (i = 0; i < NFSSESSIONHASHSIZE; i++)
+ mtx_destroy(&nfssessionhash[i].mtx);
lockdestroy(&nfsv4root_mnt.mnt_explock);
loaded = 0;
break;
Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c Mon Jul 15 23:27:48 2013 (r253374)
+++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c Tue Jul 16 00:05:17 2013 (r253375)
@@ -2523,7 +2523,7 @@ nfsrvd_open(struct nfsrv_descript *nd, _
struct nfsexstuff *exp)
{
u_int32_t *tl;
- int i;
+ int i, retext;
struct nfsstate *stp = NULL;
int error = 0, create, claim, exclusive_flag = 0;
u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask;
@@ -2560,6 +2560,16 @@ nfsrvd_open(struct nfsrv_descript *nd, _
stp->ls_uid = nd->nd_cred->cr_uid;
stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
i = fxdr_unsigned(int, *tl++);
+ retext = -1;
+ if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG |
+ NFSV4OPEN_WANTPUSHDELEG)) != 0 && (nd->nd_flag & ND_NFSV41) != 0) {
+ retext = NFSV4OPEN_RESOURCE;
+ if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG |
+ NFSV4OPEN_WANTPUSHDELEG)) == NFSV4OPEN_WANTNODELEG)
+ retext = NFSV4OPEN_NOTWANTED;
+ i &= ~(NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG |
+ NFSV4OPEN_WANTPUSHDELEG);
+ }
switch (i) {
case NFSV4OPEN_ACCESSREAD:
stp->ls_flags |= NFSLCK_READACCESS;
@@ -2634,6 +2644,28 @@ nfsrvd_open(struct nfsrv_descript *nd, _
cverf[0] = *tl++;
cverf[1] = *tl;
break;
+ case NFSCREATE_EXCLUSIVE41:
+ NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
+ cverf[0] = *tl++;
+ cverf[1] = *tl;
+ error = nfsv4_sattr(nd, &nva, &attrbits, aclp, p);
+ if (error != 0)
+ goto nfsmout;
+ if (NFSISSET_ATTRBIT(&attrbits,
+ NFSATTRBIT_TIMEACCESSSET))
+ nd->nd_repstat = NFSERR_INVAL;
+ /*
+ * If the na_gid being set is the same as that of
+ * the directory it is going in, clear it, since
+ * that is what will be set by default. This allows
+ * a user that isn't in that group to do the create.
+ */
+ if (nd->nd_repstat == 0 && NFSVNO_ISSETGID(&nva) &&
+ nva.na_gid == dirfor.na_gid)
+ NFSVNO_UNSET(&nva, gid);
+ if (nd->nd_repstat == 0)
+ nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
+ break;
default:
nd->nd_repstat = NFSERR_BADXDR;
goto nfsmout;
@@ -2715,27 +2747,38 @@ nfsrvd_open(struct nfsrv_descript *nd, _
exclusive_flag = 1;
if (!named.ni_vp)
nva.na_mode = 0;
+ break;
+ case NFSCREATE_EXCLUSIVE41:
+ exclusive_flag = 1;
+ break;
};
}
nfsvno_open(nd, &named, clientid, &stateid, stp,
&exclusive_flag, &nva, cverf, create, aclp, &attrbits,
nd->nd_cred, p, exp, &vp);
- } else if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
- NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
- i = fxdr_unsigned(int, *tl);
- switch (i) {
- case NFSV4OPEN_DELEGATEREAD:
- stp->ls_flags |= NFSLCK_DELEGREAD;
- break;
- case NFSV4OPEN_DELEGATEWRITE:
- stp->ls_flags |= NFSLCK_DELEGWRITE;
- case NFSV4OPEN_DELEGATENONE:
- break;
- default:
- nd->nd_repstat = NFSERR_BADXDR;
- goto nfsmout;
- };
- stp->ls_flags |= NFSLCK_RECLAIM;
+ } else if (claim == NFSV4OPEN_CLAIMPREVIOUS || claim ==
+ NFSV4OPEN_CLAIMFH) {
+ if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
+ NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
+ i = fxdr_unsigned(int, *tl);
+ switch (i) {
+ case NFSV4OPEN_DELEGATEREAD:
+ stp->ls_flags |= NFSLCK_DELEGREAD;
+ break;
+ case NFSV4OPEN_DELEGATEWRITE:
+ stp->ls_flags |= NFSLCK_DELEGWRITE;
+ case NFSV4OPEN_DELEGATENONE:
+ break;
+ default:
+ nd->nd_repstat = NFSERR_BADXDR;
+ goto nfsmout;
+ };
+ stp->ls_flags |= NFSLCK_RECLAIM;
+ } else {
+ /* CLAIM_NULL_FH */
+ if (nd->nd_repstat == 0 && create == NFSV4OPEN_CREATE)
+ nd->nd_repstat = NFSERR_INVAL;
+ }
vp = dp;
NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
if ((vp->v_iflag & VI_DOOMED) == 0)
@@ -2824,7 +2867,18 @@ nfsrvd_open(struct nfsrv_descript *nd, _
*tl = txdr_unsigned(NFSV4OPEN_DELEGATEREAD);
else if (rflags & NFSV4OPEN_WRITEDELEGATE)
*tl = txdr_unsigned(NFSV4OPEN_DELEGATEWRITE);
- else
+ else if (retext != -1) {
+ *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONEEXT);
+ if (retext == NFSV4OPEN_RESOURCE ||
+ retext == NFSV4OPEN_CONTENTION) {
+ NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+ *tl++ = txdr_unsigned(retext);
+ *tl = newnfs_false;
+ } else {
+ NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
+ *tl = txdr_unsigned(retext);
+ }
+ } else
*tl = txdr_unsigned(NFSV4OPEN_DELEGATENONE);
if (rflags & (NFSV4OPEN_READDELEGATE|NFSV4OPEN_WRITEDELEGATE)) {
NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID+NFSX_UNSIGNED);
@@ -2947,7 +3001,7 @@ nfsrvd_delegpurge(struct nfsrv_descript
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
- nd->nd_repstat = nfsrv_delegupdate(clientid, NULL, NULL,
+ nd->nd_repstat = nfsrv_delegupdate(nd, clientid, NULL, NULL,
NFSV4OP_DELEGPURGE, nd->nd_cred, p);
nfsmout:
NFSEXITCODE2(error, nd);
@@ -2978,7 +3032,7 @@ nfsrvd_delegreturn(struct nfsrv_descript
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
- nd->nd_repstat = nfsrv_delegupdate(clientid, &stateid, vp,
+ nd->nd_repstat = nfsrv_delegupdate(nd, clientid, &stateid, vp,
NFSV4OP_DELEGRETURN, nd->nd_cred, p);
nfsmout:
vput(vp);
@@ -3016,6 +3070,10 @@ nfsrvd_openconfirm(struct nfsrv_descript
nfsv4stateid_t stateid;
nfsquad_t clientid;
+ if ((nd->nd_flag & ND_NFSV41) != 0) {
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ goto nfsmout;
+ }
NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
stp->ls_ownerlen = 0;
stp->ls_op = nd->nd_rp;
@@ -3136,6 +3194,10 @@ nfsrvd_renew(struct nfsrv_descript *nd,
int error = 0;
nfsquad_t clientid;
+ if ((nd->nd_flag & ND_NFSV41) != 0) {
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ goto nfsmout;
+ }
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
nd->nd_repstat = NFSERR_WRONGSEC;
goto nfsmout;
@@ -3151,7 +3213,7 @@ nfsrvd_renew(struct nfsrv_descript *nd,
nd->nd_clientid.qval = clientid.qval;
}
nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_RENEWOP|CLOPS_RENEW),
- NULL, (nfsquad_t)((u_quad_t)0), nd, p);
+ NULL, NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
nfsmout:
NFSEXITCODE2(error, nd);
return (error);
@@ -3275,6 +3337,10 @@ nfsrvd_setclientid(struct nfsrv_descript
u_char *verf, *ucp, *ucp2, addrbuf[24];
nfsquad_t clientid, confirm;
+ if ((nd->nd_flag & ND_NFSV41) != 0) {
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ goto nfsmout;
+ }
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
nd->nd_repstat = NFSERR_WRONGSEC;
goto out;
@@ -3387,6 +3453,10 @@ nfsrvd_setclientidcfrm(struct nfsrv_desc
int error = 0;
nfsquad_t clientid, confirm;
+ if ((nd->nd_flag & ND_NFSV41) != 0) {
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ goto nfsmout;
+ }
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
nd->nd_repstat = NFSERR_WRONGSEC;
goto nfsmout;
@@ -3402,7 +3472,7 @@ nfsrvd_setclientidcfrm(struct nfsrv_desc
* returns the appropriate NFSERR status.
*/
nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_CONFIRM|CLOPS_RENEW),
- NULL, confirm, nd, p);
+ NULL, NULL, confirm, 0, nd, p);
nfsmout:
NFSEXITCODE2(error, nd);
return (error);
@@ -3477,6 +3547,10 @@ nfsrvd_releaselckown(struct nfsrv_descri
int error = 0, len;
nfsquad_t clientid;
+ if ((nd->nd_flag & ND_NFSV41) != 0) {
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ goto nfsmout;
+ }
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
nd->nd_repstat = NFSERR_WRONGSEC;
goto nfsmout;
@@ -3516,3 +3590,383 @@ nfsmout:
NFSEXITCODE2(error, nd);
return (error);
}
+
+/*
+ * nfsv4 exchange_id service
+ */
+APPLESTATIC int
+nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram,
+ __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
+{
+ uint32_t *tl;
+ int error = 0, i, idlen;
+ struct nfsclient *clp = NULL;
+ nfsquad_t clientid, confirm;
+ uint8_t *verf;
+ uint32_t sp4type, v41flags;
+ uint64_t owner_minor;
+ struct timespec verstime;
+
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
+ verf = (uint8_t *)tl;
+ tl += (NFSX_VERF / NFSX_UNSIGNED);
+ i = fxdr_unsigned(int, *tl);
+ if (i > NFSV4_OPAQUELIMIT || i <= 0) {
+ nd->nd_repstat = NFSERR_BADXDR;
+ goto nfsmout;
+ }
+ idlen = i;
+ if (nd->nd_flag & ND_GSS)
+ i += nd->nd_princlen;
+ clp = (struct nfsclient *)malloc(sizeof(struct nfsclient) + i,
+ M_NFSDCLIENT, M_WAITOK | M_ZERO);
+ NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx);
+ NFSSOCKADDRALLOC(clp->lc_req.nr_nam);
+ NFSSOCKADDRSIZE(clp->lc_req.nr_nam, sizeof (struct sockaddr_in));
+ clp->lc_req.nr_cred = NULL;
+ NFSBCOPY(verf, clp->lc_verf, NFSX_VERF);
+ clp->lc_idlen = idlen;
+ error = nfsrv_mtostr(nd, clp->lc_id, idlen);
+ if (error != 0)
+ goto nfsmout;
+ if ((nd->nd_flag & ND_GSS) != 0) {
+ clp->lc_flags = LCL_GSS;
+ if ((nd->nd_flag & ND_GSSINTEGRITY) != 0)
+ clp->lc_flags |= LCL_GSSINTEGRITY;
+ else if ((nd->nd_flag & ND_GSSPRIVACY) != 0)
+ clp->lc_flags |= LCL_GSSPRIVACY;
+ } else
+ clp->lc_flags = 0;
+ if ((nd->nd_flag & ND_GSS) != 0 && nd->nd_princlen > 0) {
+ clp->lc_flags |= LCL_NAME;
+ clp->lc_namelen = nd->nd_princlen;
+ clp->lc_name = &clp->lc_id[idlen];
+ NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen);
+ } else {
+ clp->lc_uid = nd->nd_cred->cr_uid;
+ clp->lc_gid = nd->nd_cred->cr_gid;
+ }
+ NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+ v41flags = fxdr_unsigned(uint32_t, *tl++);
+ if ((v41flags & ~(NFSV4EXCH_SUPPMOVEDREFER | NFSV4EXCH_SUPPMOVEDMIGR |
+ NFSV4EXCH_BINDPRINCSTATEID | NFSV4EXCH_MASKPNFS |
+ NFSV4EXCH_UPDCONFIRMEDRECA)) != 0) {
+ nd->nd_repstat = NFSERR_INVAL;
+ goto nfsmout;
+ }
+ if ((v41flags & NFSV4EXCH_UPDCONFIRMEDRECA) != 0)
+ confirm.lval[1] = 1;
+ else
+ confirm.lval[1] = 0;
+ v41flags = NFSV4EXCH_USENONPNFS;
+ sp4type = fxdr_unsigned(uint32_t, *tl);
+ if (sp4type != NFSV4EXCH_SP4NONE) {
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ goto nfsmout;
+ }
+
+ /*
+ * nfsrv_setclient() does the actual work of adding it to the
+ * client list. If there is no error, the structure has been
+ * linked into the client list and clp should no longer be used
+ * here. When an error is returned, it has not been linked in,
+ * so it should be free'd.
+ */
+ nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p);
+ if (clp != NULL) {
+ NFSSOCKADDRFREE(clp->lc_req.nr_nam);
+ NFSFREEMUTEX(&clp->lc_req.nr_mtx);
+ free(clp, M_NFSDCLIENT);
+ }
+ if (nd->nd_repstat == 0) {
+ if (confirm.lval[1] != 0)
+ v41flags |= NFSV4EXCH_CONFIRMEDR;
+ NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + 3 * NFSX_UNSIGNED);
+ *tl++ = clientid.lval[0]; /* ClientID */
+ *tl++ = clientid.lval[1];
+ *tl++ = txdr_unsigned(confirm.lval[0]); /* SequenceID */
+ *tl++ = txdr_unsigned(v41flags); /* Exch flags */
+ *tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE); /* No SSV */
+ owner_minor = 0; /* Owner */
+ txdr_hyper(owner_minor, tl); /* Minor */
+ (void)nfsm_strtom(nd, nd->nd_cred->cr_prison->pr_hostuuid,
+ strlen(nd->nd_cred->cr_prison->pr_hostuuid)); /* Major */
+ NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED);
+ *tl++ = txdr_unsigned(NFSX_UNSIGNED);
+ NFSBCOPY(&time_uptime, tl++, NFSX_UNSIGNED);
+ *tl = txdr_unsigned(1);
+ (void)nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org"));
+ (void)nfsm_strtom(nd, version, strlen(version));
+ NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME);
+ verstime.tv_sec = 1293840000; /* Jan 1, 2011 */
+ verstime.tv_nsec = 0;
+ txdr_nfsv4time(&verstime, tl);
+ }
+ NFSEXITCODE2(0, nd);
+ return (0);
+nfsmout:
+ if (clp != NULL) {
+ NFSSOCKADDRFREE(clp->lc_req.nr_nam);
+ NFSFREEMUTEX(&clp->lc_req.nr_mtx);
+ free(clp, M_NFSDCLIENT);
+ }
+ NFSEXITCODE2(error, nd);
+ return (error);
+}
+
+/*
+ * nfsv4 create session service
+ */
+APPLESTATIC int
+nfsrvd_createsession(struct nfsrv_descript *nd, __unused int isdgram,
+ __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
+{
+ uint32_t *tl;
+ int error = 0;
+ nfsquad_t clientid, confirm;
+ struct nfsdsession *sep = NULL;
+ uint32_t rdmacnt;
+
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession),
+ M_NFSDSESSION, M_WAITOK | M_ZERO);
+ NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
+ clientid.lval[0] = *tl++;
+ clientid.lval[1] = *tl++;
+ confirm.lval[0] = fxdr_unsigned(uint32_t, *tl++);
+ sep->sess_crflags = fxdr_unsigned(uint32_t, *tl);
+ /* Persistent sessions and RDMA are not supported. */
+ sep->sess_crflags &= NFSV4CRSESS_CONNBACKCHAN;
+
+ /* Fore channel attributes. */
+ NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
+ tl++; /* Header pad always 0. */
+ sep->sess_maxreq = fxdr_unsigned(uint32_t, *tl++);
+ sep->sess_maxresp = fxdr_unsigned(uint32_t, *tl++);
+ sep->sess_maxrespcached = fxdr_unsigned(uint32_t, *tl++);
+ sep->sess_maxops = fxdr_unsigned(uint32_t, *tl++);
+ sep->sess_maxslots = fxdr_unsigned(uint32_t, *tl++);
+ if (sep->sess_maxslots > NFSV4_SLOTS)
+ sep->sess_maxslots = NFSV4_SLOTS;
+ rdmacnt = fxdr_unsigned(uint32_t, *tl);
+ if (rdmacnt > 1) {
+ nd->nd_repstat = NFSERR_BADXDR;
+ goto nfsmout;
+ } else if (rdmacnt == 1)
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+
+ /* Back channel attributes. */
+ NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
+ tl++; /* Header pad always 0. */
+ sep->sess_cbmaxreq = fxdr_unsigned(uint32_t, *tl++);
+ sep->sess_cbmaxresp = fxdr_unsigned(uint32_t, *tl++);
+ sep->sess_cbmaxrespcached = fxdr_unsigned(uint32_t, *tl++);
+ sep->sess_cbmaxops = fxdr_unsigned(uint32_t, *tl++);
+ sep->sess_cbmaxslots = fxdr_unsigned(uint32_t, *tl++);
+ rdmacnt = fxdr_unsigned(uint32_t, *tl);
+ if (rdmacnt > 1) {
+ nd->nd_repstat = NFSERR_BADXDR;
+ goto nfsmout;
+ } else if (rdmacnt == 1)
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ sep->sess_cbprogram = fxdr_unsigned(uint32_t, *tl);
+
+ /*
+ * nfsrv_getclient() searches the client list for a match and
+ * returns the appropriate NFSERR status.
+ */
+ nd->nd_repstat = nfsrv_getclient(clientid, CLOPS_CONFIRM | CLOPS_RENEW,
+ NULL, sep, confirm, sep->sess_cbprogram, nd, p);
+ if (nd->nd_repstat == 0) {
+ NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
+ NFSBCOPY(sep->sess_sessionid, tl, NFSX_V4SESSIONID);
+ NFSM_BUILD(tl, uint32_t *, 18 * NFSX_UNSIGNED);
+ *tl++ = txdr_unsigned(confirm.lval[0]); /* sequenceid */
+ *tl++ = txdr_unsigned(sep->sess_crflags);
+
+ /* Fore channel attributes. */
+ *tl++ = 0;
+ *tl++ = txdr_unsigned(sep->sess_maxreq);
+ *tl++ = txdr_unsigned(sep->sess_maxresp);
+ *tl++ = txdr_unsigned(sep->sess_maxrespcached);
+ *tl++ = txdr_unsigned(sep->sess_maxops);
+ *tl++ = txdr_unsigned(sep->sess_maxslots);
+ *tl++ = txdr_unsigned(1);
+ *tl++ = txdr_unsigned(0); /* No RDMA. */
+
+ /* Back channel attributes. */
+ *tl++ = 0;
+ *tl++ = txdr_unsigned(sep->sess_cbmaxreq);
+ *tl++ = txdr_unsigned(sep->sess_cbmaxresp);
+ *tl++ = txdr_unsigned(sep->sess_cbmaxrespcached);
+ *tl++ = txdr_unsigned(sep->sess_cbmaxops);
+ *tl++ = txdr_unsigned(sep->sess_cbmaxslots);
+ *tl++ = txdr_unsigned(1);
+ *tl = txdr_unsigned(0); /* No RDMA. */
+ }
+nfsmout:
+ if (nd->nd_repstat != 0)
+ free(sep, M_NFSDSESSION);
+ NFSEXITCODE2(error, nd);
+ return (error);
+}
+
+/*
+ * nfsv4 sequence service
+ */
+APPLESTATIC int
+nfsrvd_sequence(struct nfsrv_descript *nd, __unused int isdgram,
+ __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp)
+{
+ uint32_t *tl;
+ uint32_t highest_slotid, sequenceid, sflags, target_highest_slotid;
+ int cache_this, error = 0;
+
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID);
+ NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID);
+ NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
+ sequenceid = fxdr_unsigned(uint32_t, *tl++);
+ nd->nd_slotid = fxdr_unsigned(uint32_t, *tl++);
+ highest_slotid = fxdr_unsigned(uint32_t, *tl++);
+ if (*tl == newnfs_true)
+ cache_this = 1;
+ else
+ cache_this = 0;
+ nd->nd_flag |= ND_HASSEQUENCE;
+ nd->nd_repstat = nfsrv_checksequence(nd, sequenceid, &highest_slotid,
+ &target_highest_slotid, cache_this, &sflags, p);
+ if (nd->nd_repstat == 0) {
+ NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
+ NFSBCOPY(nd->nd_sessionid, tl, NFSX_V4SESSIONID);
+ NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED);
+ *tl++ = txdr_unsigned(sequenceid);
+ *tl++ = txdr_unsigned(nd->nd_slotid);
+ *tl++ = txdr_unsigned(highest_slotid);
+ *tl++ = txdr_unsigned(target_highest_slotid);
+ *tl = txdr_unsigned(sflags);
+ }
+nfsmout:
+ NFSEXITCODE2(error, nd);
+ return (error);
+}
+
+/*
+ * nfsv4 reclaim complete service
+ */
+APPLESTATIC int
+nfsrvd_reclaimcomplete(struct nfsrv_descript *nd, __unused int isdgram,
+ __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp)
+{
+ uint32_t *tl;
+ int error = 0;
+
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ if (*tl == newnfs_true)
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ else
+ nd->nd_repstat = nfsrv_checkreclaimcomplete(nd);
+nfsmout:
+ NFSEXITCODE2(error, nd);
+ return (error);
+}
+
+/*
+ * nfsv4 destroy clientid service
+ */
+APPLESTATIC int
+nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram,
+ __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
+{
+ uint32_t *tl;
+ nfsquad_t clientid;
+ int error = 0;
+
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+ clientid.lval[0] = *tl++;
+ clientid.lval[1] = *tl;
+ nd->nd_repstat = nfsrv_destroyclient(clientid, p);
+nfsmout:
+ NFSEXITCODE2(error, nd);
+ return (error);
+}
+
+/*
+ * nfsv4 destroy session service
+ */
+APPLESTATIC int
+nfsrvd_destroysession(struct nfsrv_descript *nd, __unused int isdgram,
+ __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp)
+{
+ uint8_t *cp, sessid[NFSX_V4SESSIONID];
+ int error = 0;
+
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID);
+ NFSBCOPY(cp, sessid, NFSX_V4SESSIONID);
+ nd->nd_repstat = nfsrv_destroysession(nd, sessid);
+nfsmout:
+ NFSEXITCODE2(error, nd);
+ return (error);
+}
+
+/*
+ * nfsv4 free stateid service
+ */
+APPLESTATIC int
+nfsrvd_freestateid(struct nfsrv_descript *nd, __unused int isdgram,
+ __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp)
+{
+ uint32_t *tl;
+ nfsv4stateid_t stateid;
+ int error = 0;
+
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID);
+ stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
+ NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
+ nd->nd_repstat = nfsrv_freestateid(nd, &stateid, p);
+nfsmout:
+ NFSEXITCODE2(error, nd);
+ return (error);
+}
+
+/*
+ * nfsv4 service not supported
+ */
+APPLESTATIC int
+nfsrvd_notsupp(struct nfsrv_descript *nd, __unused int isdgram,
+ __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp)
+{
+
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ NFSEXITCODE2(0, nd);
+ return (0);
+}
+
More information about the svn-src-projects
mailing list