svn commit: r260158 - in projects/nfsv4.1-server/sys: conf fs/nfs fs/nfsserver modules/krpc rpc
Rick Macklem
rmacklem at FreeBSD.org
Wed Jan 1 01:46:58 UTC 2014
Author: rmacklem
Date: Wed Jan 1 01:46:56 2014
New Revision: 260158
URL: http://svnweb.freebsd.org/changeset/base/260158
Log:
Add backchannel support to the NFSv4.1 server.
Added:
projects/nfsv4.1-server/sys/rpc/clnt_bck.c (contents, props changed)
Modified:
projects/nfsv4.1-server/sys/conf/files
projects/nfsv4.1-server/sys/fs/nfs/nfs.h
projects/nfsv4.1-server/sys/fs/nfs/nfs_commonkrpc.c
projects/nfsv4.1-server/sys/fs/nfs/nfs_commonsubs.c
projects/nfsv4.1-server/sys/fs/nfs/nfs_var.h
projects/nfsv4.1-server/sys/fs/nfs/nfsclstate.h
projects/nfsv4.1-server/sys/fs/nfs/nfsport.h
projects/nfsv4.1-server/sys/fs/nfs/nfsrvstate.h
projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c
projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c
projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdstate.c
projects/nfsv4.1-server/sys/modules/krpc/Makefile
projects/nfsv4.1-server/sys/rpc/krpc.h
projects/nfsv4.1-server/sys/rpc/svc.h
projects/nfsv4.1-server/sys/rpc/svc_vc.c
Modified: projects/nfsv4.1-server/sys/conf/files
==============================================================================
--- projects/nfsv4.1-server/sys/conf/files Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/conf/files Wed Jan 1 01:46:56 2014 (r260158)
@@ -3749,6 +3749,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: projects/nfsv4.1-server/sys/fs/nfs/nfs.h
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfs/nfs.h Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfs/nfs.h Wed Jan 1 01:46:56 2014 (r260158)
@@ -281,6 +281,7 @@ struct nfsreferral {
#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 */
@@ -588,6 +589,7 @@ struct nfsrv_descript {
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
Modified: projects/nfsv4.1-server/sys/fs/nfs/nfs_commonkrpc.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfs/nfs_commonkrpc.c Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfs/nfs_commonkrpc.c Wed Jan 1 01:46:56 2014 (r260158)
@@ -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: projects/nfsv4.1-server/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfs/nfs_commonsubs.c Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfs/nfs_commonsubs.c Wed Jan 1 01:46:56 2014 (r260158)
@@ -3744,9 +3744,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;
@@ -3759,7 +3786,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;
@@ -3770,10 +3797,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,
@@ -3789,21 +3817,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: projects/nfsv4.1-server/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfs/nfs_var.h Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfs/nfs_var.h Wed Jan 1 01:46:56 2014 (r260158)
@@ -292,6 +292,8 @@ int nfsv4_seqsession(uint32_t, uint32_t,
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 */
Modified: projects/nfsv4.1-server/sys/fs/nfs/nfsclstate.h
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfs/nfsclstate.h Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfs/nfsclstate.h Wed Jan 1 01:46:56 2014 (r260158)
@@ -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: projects/nfsv4.1-server/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfs/nfsport.h Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfs/nfsport.h Wed Jan 1 01:46:56 2014 (r260158)
@@ -638,6 +638,7 @@ 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))
Modified: projects/nfsv4.1-server/sys/fs/nfs/nfsrvstate.h
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfs/nfsrvstate.h Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfs/nfsrvstate.h Wed Jan 1 01:46:56 2014 (r260158)
@@ -112,8 +112,22 @@ struct nfsclient {
/*
* 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];
@@ -129,8 +143,8 @@ struct nfsdsession {
uint32_t sess_cbmaxresp;
uint32_t sess_cbmaxrespcached;
uint32_t sess_cbmaxops;
- uint32_t sess_cbmaxslots;
uint8_t sess_sessionid[NFSX_V4SESSIONID];
+ struct nfsclsession sess_cbsess; /* Callback session. */
};
/*
Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdkrpc.c Wed Jan 1 01:46:56 2014 (r260158)
@@ -98,7 +98,7 @@ SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_m
&nfs_maxvers, 0, "The highest version of NFS handled by the server");
static int nfs_proc(struct nfsrv_descript *, u_int32_t, struct socket *,
- u_int64_t, struct nfsrvcache **);
+ u_int64_t, SVCXPRT *, struct nfsrvcache **);
extern u_long sb_max_adj;
extern int newnfs_numnfsd;
@@ -252,7 +252,7 @@ nfssvc_program(struct svc_req *rqst, SVC
}
cacherep = nfs_proc(&nd, rqst->rq_xid, xprt->xp_socket,
- xprt->xp_sockref, &rp);
+ xprt->xp_sockref, xprt, &rp);
NFSLOCKV4ROOTMUTEX();
nfsv4_relref(&nfsd_suspend_lock);
NFSUNLOCKV4ROOTMUTEX();
@@ -301,7 +301,7 @@ out:
*/
static int
nfs_proc(struct nfsrv_descript *nd, u_int32_t xid, struct socket *so,
- u_int64_t sockref, struct nfsrvcache **rpp)
+ u_int64_t sockref, SVCXPRT *xprt, struct nfsrvcache **rpp)
{
struct thread *td = curthread;
int cacherep = RC_DOIT, isdgram, taglen = -1;
@@ -357,6 +357,8 @@ nfs_proc(struct nfsrv_descript *nd, u_in
* RC_DROPIT - just throw the request away
*/
if (cacherep == RC_DOIT) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ nd->nd_xprt = xprt;
nfsrvd_dorpc(nd, isdgram, tagstr, taglen, minorvers, td);
if ((nd->nd_flag & ND_NFSV41) != 0) {
if (nd->nd_repstat != NFSERR_REPLYFROMCACHE &&
Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdserv.c Wed Jan 1 01:46:56 2014 (r260158)
@@ -666,10 +666,14 @@ nfsrvd_read(struct nfsrv_descript *nd, _
stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK1 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -818,10 +822,14 @@ nfsrvd_write(struct nfsrv_descript *nd,
stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK2 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -2196,10 +2204,14 @@ nfsrvd_lock(struct nfsrv_descript *nd, _
stp->ls_opentolockseq = fxdr_unsigned(int, *tl++);
clientid.lval[0] = *tl++;
clientid.lval[1] = *tl++;
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK3 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -2219,10 +2231,14 @@ nfsrvd_lock(struct nfsrv_descript *nd, _
stp->ls_seq = fxdr_unsigned(int, *tl);
clientid.lval[0] = stp->ls_stateid.other[0];
clientid.lval[1] = stp->ls_stateid.other[1];
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK4 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -2368,10 +2384,14 @@ nfsrvd_lockt(struct nfsrv_descript *nd,
tl += 2;
clientid.lval[0] = *tl++;
clientid.lval[1] = *tl;
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK5 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -2479,10 +2499,14 @@ nfsrvd_locku(struct nfsrv_descript *nd,
}
clientid.lval[0] = stp->ls_stateid.other[0];
clientid.lval[1] = stp->ls_stateid.other[1];
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK6 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -2601,10 +2625,14 @@ nfsrvd_open(struct nfsrv_descript *nd, _
};
clientid.lval[0] = *tl++;
clientid.lval[1] = *tl;
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK7 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -2954,10 +2982,14 @@ nfsrvd_close(struct nfsrv_descript *nd,
stp->ls_flags = NFSLCK_CLOSE;
clientid.lval[0] = stp->ls_stateid.other[0];
clientid.lval[1] = stp->ls_stateid.other[1];
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK8 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -2994,10 +3026,14 @@ nfsrvd_delegpurge(struct nfsrv_descript
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
clientid.lval[0] = *tl++;
clientid.lval[1] = *tl;
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK9 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -3025,10 +3061,14 @@ nfsrvd_delegreturn(struct nfsrv_descript
NFSBCOPY((caddr_t)tl, (caddr_t)stateid.other, NFSX_STATEIDOTHER);
clientid.lval[0] = stateid.other[0];
clientid.lval[1] = stateid.other[1];
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK10 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -3086,10 +3126,14 @@ nfsrvd_openconfirm(struct nfsrv_descript
stp->ls_flags = NFSLCK_CONFIRM;
clientid.lval[0] = stp->ls_stateid.other[0];
clientid.lval[1] = stp->ls_stateid.other[1];
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK11 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -3162,10 +3206,14 @@ nfsrvd_opendowngrade(struct nfsrv_descri
clientid.lval[0] = stp->ls_stateid.other[0];
clientid.lval[1] = stp->ls_stateid.other[1];
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK12 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -3205,10 +3253,14 @@ nfsrvd_renew(struct nfsrv_descript *nd,
NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
clientid.lval[0] = *tl++;
clientid.lval[1] = *tl;
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK13 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -3569,10 +3621,14 @@ nfsrvd_releaselckown(struct nfsrv_descri
stp->ls_uid = nd->nd_cred->cr_uid;
clientid.lval[0] = *tl++;
clientid.lval[1] = *tl;
- if (nd->nd_flag & ND_IMPLIEDCLID) {
- if (nd->nd_clientid.qval != clientid.qval)
- printf("EEK! multiple clids\n");
+ if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ clientid.qval = nd->nd_clientid.qval;
+ else if (nd->nd_clientid.qval != clientid.qval)
+ printf("EEK14 multiple clids\n");
} else {
+ if ((nd->nd_flag & ND_NFSV41) != 0)
+ printf("EEK! no clientid from session\n");
nd->nd_flag |= ND_IMPLIEDCLID;
nd->nd_clientid.qval = clientid.qval;
}
@@ -3634,13 +3690,13 @@ nfsrvd_exchangeid(struct nfsrv_descript
if (error != 0)
goto nfsmout;
if ((nd->nd_flag & ND_GSS) != 0) {
- clp->lc_flags = LCL_GSS;
+ clp->lc_flags = LCL_GSS | LCL_NFSV41;
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;
+ clp->lc_flags = LCL_NFSV41;
if ((nd->nd_flag & ND_GSS) != 0 && nd->nd_princlen > 0) {
clp->lc_flags |= LCL_NAME;
clp->lc_namelen = nd->nd_princlen;
@@ -3737,6 +3793,8 @@ nfsrvd_createsession(struct nfsrv_descri
}
sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession),
M_NFSDSESSION, M_WAITOK | M_ZERO);
+ sep->sess_refcnt = 1;
+ mtx_init(&sep->sess_cbsess.nfsess_mtx, "nfscbsession", NULL, MTX_DEF);
NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
clientid.lval[0] = *tl++;
clientid.lval[1] = *tl++;
@@ -3769,7 +3827,7 @@ nfsrvd_createsession(struct nfsrv_descri
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++);
+ sep->sess_cbsess.nfsess_foreslots = fxdr_unsigned(uint32_t, *tl++);
rdmacnt = fxdr_unsigned(uint32_t, *tl);
if (rdmacnt > 1) {
nd->nd_repstat = NFSERR_BADXDR;
@@ -3809,7 +3867,7 @@ nfsrvd_createsession(struct nfsrv_descri
*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(sep->sess_cbsess.nfsess_foreslots);
*tl++ = txdr_unsigned(1);
*tl = txdr_unsigned(0); /* No RDMA. */
}
Modified: projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdstate.c Wed Jan 1 01:26:39 2014 (r260157)
+++ projects/nfsv4.1-server/sys/fs/nfsserver/nfs_nfsdstate.c Wed Jan 1 01:46:56 2014 (r260158)
@@ -95,6 +95,8 @@ static int nfsrv_checkgrace(struct nfsrv
static int nfsrv_docallback(struct nfsclient *clp, int procnum,
nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp,
struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p);
+static int nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
+ uint32_t callback, int op, const char *optag, struct nfsdsession **sepp);
static u_int32_t nfsrv_nextclientindex(void);
static u_int32_t nfsrv_nextstateindex(struct nfsclient *clp);
static void nfsrv_markstable(struct nfsclient *clp);
@@ -127,6 +129,9 @@ static void nfsrv_locklf(struct nfslockf
static void nfsrv_unlocklf(struct nfslockfile *lfp);
static struct nfsdsession *nfsrv_findsession(uint8_t *sessionid);
static int nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid);
+static int nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
+ int dont_replycache, struct nfsdsession **sepp);
+static int nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp);
/*
* Scan the client list for a match and either return the current one,
@@ -148,6 +153,7 @@ nfsrv_setclient(struct nfsrv_descript *n
/*
* Check for state resource limit exceeded.
*/
+printf("in nfsrv_setcl\n");
if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) {
error = NFSERR_RESOURCE;
goto out;
@@ -205,6 +211,7 @@ nfsrv_setclient(struct nfsrv_descript *n
NFSUNLOCKV4ROOTMUTEX();
confirmp->lval[1] = 0;
error = NFSERR_NOENT;
+printf("reconfirming\n");
goto out;
}
/*
@@ -252,6 +259,7 @@ nfsrv_setclient(struct nfsrv_descript *n
if (zapit)
nfsrv_zapclient(clp, p);
*new_clpp = NULL;
+printf("new cl\n");
goto out;
}
@@ -367,6 +375,7 @@ nfsrv_setclient(struct nfsrv_descript *n
NFSUNLOCKSTATE();
nfsrv_zapclient(clp, p);
*new_clpp = NULL;
+printf("new cl2\n");
goto out;
}
@@ -411,6 +420,7 @@ nfsrv_setclient(struct nfsrv_descript *n
newnfsstats.srvclients++;
nfsrv_openpluslock++;
nfsrv_clients++;
+printf("new cl3\n");
}
NFSLOCKV4ROOTMUTEX();
nfsv4_unlock(&nfsv4rootfs_lock, 1);
@@ -568,15 +578,39 @@ nfsrv_getclient(nfsquad_t clientid, int
clp->lc_flags &= ~(LCL_NEEDSCONFIRM | LCL_DONTCLEAN);
if (clp->lc_program)
clp->lc_flags |= LCL_NEEDSCBNULL;
+printf("prog=%d\n", clp->lc_program);
/* For NFSv4.1, link the session onto the client. */
if (nsep != NULL) {
+printf("nsep not null\n");
+ /* Hold a reference on the xprt for a backchannel. */
+ if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN)
+ != 0 && clp->lc_req.nr_client == NULL) {
+printf("set backch\n");
+ clp->lc_req.nr_client = (struct __rpc_client *)
+ clnt_bck_create(nd->nd_xprt->xp_socket,
+ cbprogram, NFSV4_CBVERS);
+printf("cbcl=%p\n", clp->lc_req.nr_client);
+ if (clp->lc_req.nr_client != NULL) {
+ SVC_ACQUIRE(nd->nd_xprt);
+ nd->nd_xprt->xp_p2 =
+ clp->lc_req.nr_client->cl_private;
+ /* Disable idle timeout. */
+ nd->nd_xprt->xp_idletimeout = 0;
+ nsep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
+ } else
+ nsep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN;
+ }
NFSBCOPY(sessid, nsep->sess_sessionid,
NFSX_V4SESSIONID);
+ NFSBCOPY(sessid, nsep->sess_cbsess.nfsess_sessionid,
+ NFSX_V4SESSIONID);
shp = NFSSESSIONHASH(nsep->sess_sessionid);
NFSLOCKSESSION(shp);
LIST_INSERT_HEAD(&shp->list, nsep, sess_hash);
+ NFSLOCKSTATE();
LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list);
nsep->sess_clp = clp;
+ NFSUNLOCKSTATE();
NFSUNLOCKSESSION(shp);
}
}
@@ -3835,9 +3869,7 @@ nfsrv_checkgrace(struct nfsrv_descript *
{
int error = 0;
- if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0 ||
- (nd != NULL && clp != NULL && (nd->nd_flag & ND_NFSV41) != 0 &&
- (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0)) {
+ if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) {
if (flags & NFSLCK_RECLAIM) {
error = NFSERR_NOGRACE;
goto out;
@@ -3847,6 +3879,12 @@ nfsrv_checkgrace(struct nfsrv_descript *
error = NFSERR_GRACE;
goto out;
}
+ if (nd != NULL && clp != NULL &&
+ (nd->nd_flag & ND_NFSV41) != 0 &&
+ (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) {
+ error = NFSERR_NOGRACE;
+ goto out;
+ }
/*
* If grace is almost over and we are still getting Reclaims,
@@ -3877,6 +3915,7 @@ nfsrv_docallback(struct nfsclient *clp,
struct ucred *cred;
int error = 0;
u_int32_t callback;
+ struct nfsdsession *sep = NULL;
cred = newnfs_getcred();
NFSLOCKSTATE(); /* mostly for lc_cbref++ */
@@ -3891,7 +3930,12 @@ nfsrv_docallback(struct nfsclient *clp,
* structure for newnfs_connect() to use.
*/
clp->lc_req.nr_prog = clp->lc_program;
- clp->lc_req.nr_vers = NFSV4_CBVERS;
+#ifdef notnow
+ if ((clp->lc_flags & LCL_NFSV41) != 0)
+ clp->lc_req.nr_vers = NFSV41_CBVERS;
+ else
+#endif
+ clp->lc_req.nr_vers = NFSV4_CBVERS;
/*
* First, fill in some of the fields of nd and cr.
@@ -3899,6 +3943,8 @@ nfsrv_docallback(struct nfsclient *clp,
nd->nd_flag = ND_NFSV4;
if (clp->lc_flags & LCL_GSS)
nd->nd_flag |= ND_KERBV;
+ if ((clp->lc_flags & LCL_NFSV41) != 0)
+ nd->nd_flag |= ND_NFSV41;
nd->nd_repstat = 0;
cred->cr_uid = clp->lc_uid;
cred->cr_gid = clp->lc_gid;
@@ -3919,22 +3965,23 @@ nfsrv_docallback(struct nfsclient *clp,
*/
if (procnum == NFSV4OP_CBGETATTR) {
nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
- (void) nfsm_strtom(nd, "CB Getattr", 10);
- NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
- *tl++ = txdr_unsigned(callback);
- *tl++ = txdr_unsigned(1);
- *tl = txdr_unsigned(NFSV4OP_CBGETATTR);
- (void) nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
- (void) nfsrv_putattrbit(nd, attrbitp);
+ error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR,
+ "CB Getattr", &sep);
+ if (error != 0) {
+ mbuf_freem(nd->nd_mreq);
+ goto errout;
+ }
+ (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
+ (void)nfsrv_putattrbit(nd, attrbitp);
} else if (procnum == NFSV4OP_CBRECALL) {
nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
- (void) nfsm_strtom(nd, "CB Recall", 9);
- NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID);
- *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
- *tl++ = txdr_unsigned(callback);
- *tl++ = txdr_unsigned(1);
- *tl++ = txdr_unsigned(NFSV4OP_CBRECALL);
+ error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL,
+ "CB Recall", &sep);
+ if (error != 0) {
+ mbuf_freem(nd->nd_mreq);
+ goto errout;
+ }
+ NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
*tl++ = txdr_unsigned(stateidp->seqid);
NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl,
NFSX_STATEIDOTHER);
@@ -3943,9 +3990,18 @@ nfsrv_docallback(struct nfsclient *clp,
*tl = newnfs_true;
else
*tl = newnfs_false;
- (void) nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
- } else {
+ (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
+ } else if (procnum == NFSV4PROC_CBNULL) {
nd->nd_procnum = NFSV4PROC_CBNULL;
+ error = nfsv4_getcbsession(clp, &sep);
+ if (error != 0) {
+ mbuf_freem(nd->nd_mreq);
+ goto errout;
+ }
+ } else {
+ error = NFSERR_SERVERFAULT;
+ mbuf_freem(nd->nd_mreq);
+ goto errout;
}
/*
@@ -3953,7 +4009,9 @@ nfsrv_docallback(struct nfsclient *clp,
*/
(void) newnfs_sndlock(&clp->lc_req.nr_lock);
if (clp->lc_req.nr_client == NULL) {
- if (nd->nd_procnum == NFSV4PROC_CBNULL)
+ if ((clp->lc_flags & LCL_NFSV41) != 0)
+ error = ECONNREFUSED;
+ else if (nd->nd_procnum == NFSV4PROC_CBNULL)
error = newnfs_connect(NULL, &clp->lc_req, cred,
NULL, 1);
else
@@ -3962,10 +4020,19 @@ nfsrv_docallback(struct nfsclient *clp,
}
newnfs_sndunlock(&clp->lc_req.nr_lock);
if (!error) {
- error = newnfs_request(nd, NULL, clp, &clp->lc_req, NULL,
- NULL, cred, clp->lc_program, NFSV4_CBVERS, NULL, 1, NULL,
- NULL);
+ if ((nd->nd_flag & ND_NFSV41) != 0) {
+ KASSERT(sep != NULL, ("sep NULL"));
+ error = newnfs_request(nd, NULL, clp, &clp->lc_req,
+ NULL, NULL, cred, clp->lc_program,
+ clp->lc_req.nr_vers, NULL, 1, NULL,
+ &sep->sess_cbsess);
+ nfsrv_freesession(sep, NULL);
+ } else
+ error = newnfs_request(nd, NULL, clp, &clp->lc_req,
+ NULL, NULL, cred, clp->lc_program,
+ clp->lc_req.nr_vers, NULL, 1, NULL, NULL);
}
+errout:
NFSFREECRED(cred);
/*
@@ -3995,7 +4062,7 @@ nfsrv_docallback(struct nfsclient *clp,
NFSUNLOCKSTATE();
if (nd->nd_repstat)
error = nd->nd_repstat;
- else if (procnum == NFSV4OP_CBGETATTR)
+ else if (error == 0 && procnum == NFSV4OP_CBGETATTR)
error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL,
p, NULL);
@@ -4014,6 +4081,38 @@ nfsrv_docallback(struct nfsclient *clp,
}
/*
+ * Set up the compound RPC for the callback.
+ */
+static int
+nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
+ uint32_t callback, int op, const char *optag, struct nfsdsession **sepp)
+{
+ uint32_t *tl;
+ int error, len;
+
+ len = strlen(optag);
+ (void)nfsm_strtom(nd, optag, len);
+ NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
+ if ((nd->nd_flag & ND_NFSV41) != 0) {
+ *tl++ = txdr_unsigned(NFSV41_MINORVERSION);
+ *tl++ = txdr_unsigned(callback);
+ *tl++ = txdr_unsigned(2);
+ *tl = txdr_unsigned(NFSV4OP_CBSEQUENCE);
+ error = nfsv4_setcbsequence(nd, clp, 1, sepp);
+ if (error != 0)
+ return (error);
+ NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
+ *tl = txdr_unsigned(op);
+ } else {
+ *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
+ *tl++ = txdr_unsigned(callback);
+ *tl++ = txdr_unsigned(1);
+ *tl = txdr_unsigned(op);
+ }
+ return (0);
+}
+
+/*
* Return the next index# for a clientid. Mostly just increment and return
* the next one, but... if the 32bit unsigned does actually wrap around,
* it should be rebooted.
@@ -5476,7 +5575,9 @@ nfsrv_checksequence(struct nfsrv_descrip
{
struct nfsdsession *sep;
struct nfssessionhash *shp;
+ CLIENT *cl;
int error;
+ SVCXPRT *savxprt;
shp = NFSSESSIONHASH(nd->nd_sessionid);
NFSLOCKSESSION(shp);
@@ -5495,6 +5596,26 @@ nfsrv_checksequence(struct nfsrv_descrip
nd->nd_flag |= ND_SAVEREPLY;
/* Renew the lease. */
sep->sess_clp->lc_expiry = nfsrv_leaseexpiry();
+ nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval;
+ nd->nd_flag |= ND_IMPLIEDCLID;
+
+ /*
+ * If this session handles the backchannel, save the nd_xprt for this
+ * RPC, since this is the one being used.
+ */
+ if (sep->sess_cbsess.nfsess_xprt != NULL &&
+ (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) {
+ savxprt = sep->sess_cbsess.nfsess_xprt;
+ SVC_ACQUIRE(nd->nd_xprt);
+ nd->nd_xprt->xp_p2 = savxprt->xp_p2;
+ nd->nd_xprt->xp_idletimeout = 0; /* Disable timeout. */
+ sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
+ SVC_RELEASE(savxprt);
+ }
+
+ cl = sep->sess_clp->lc_req.nr_client;
+ if (cl == NULL)
+ *sflagsp |= NFSV4SEQ_CBPATHDOWN;
NFSUNLOCKSESSION(shp);
*sflagsp = 0;
if (error == NFSERR_EXPIRED) {
@@ -5616,8 +5737,16 @@ nfsrv_freesession(struct nfsdsession *se
NFSLOCKSESSION(shp);
}
if (sep != NULL) {
+ NFSLOCKSTATE();
+ sep->sess_refcnt--;
+ if (sep->sess_refcnt > 0) {
+ NFSUNLOCKSTATE();
+ NFSUNLOCKSESSION(shp);
+ return (0);
+ }
LIST_REMOVE(sep, sess_hash);
LIST_REMOVE(sep, sess_list);
+ NFSUNLOCKSTATE();
}
NFSUNLOCKSESSION(shp);
if (sep == NULL)
@@ -5625,6 +5754,8 @@ nfsrv_freesession(struct nfsdsession *se
for (i = 0; i < NFSV4_SLOTS; i++)
if (sep->sess_slots[i].nfssl_reply != NULL)
m_freem(sep->sess_slots[i].nfssl_reply);
+ if (sep->sess_cbsess.nfsess_xprt != NULL)
+ SVC_RELEASE(sep->sess_cbsess.nfsess_xprt);
free(sep, M_NFSDSESSION);
return (0);
}
@@ -5678,3 +5809,64 @@ nfsrv_freestateid(struct nfsrv_descript
return (error);
}
+/*
+ * Generate the xdr for an NFSv4.1 CBSequence Operation.
+ */
+static int
+nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
+ int dont_replycache, struct nfsdsession **sepp)
+{
+ struct nfsdsession *sep;
+ uint32_t *tl, slotseq = 0;
+ int maxslot, slotpos;
+ uint8_t sessionid[NFSX_V4SESSIONID];
+ int error;
+
+ error = nfsv4_getcbsession(clp, sepp);
+ if (error != 0)
+ return (error);
+ sep = *sepp;
+ (void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, &slotpos, &maxslot,
+ &slotseq, sessionid);
+ KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot"));
+
+ /* Build the Sequence arguments. */
+ NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * 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;
+ *tl = 0; /* No referring call list, for now. */
+ nd->nd_flag |= ND_HASSEQUENCE;
+ return (0);
+}
+
+/*
+ * Get a session for the callback.
+ */
+static int
+nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp)
+{
+ struct nfsdsession *sep;
+
+ NFSLOCKSTATE();
+ LIST_FOREACH(sep, &clp->lc_session, sess_list) {
+ if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0)
+ break;
+ }
+ if (sep == NULL) {
+ NFSUNLOCKSTATE();
+ return (NFSERR_BADSESSION);
+ }
+ sep->sess_refcnt++;
+ *sepp = sep;
+ NFSUNLOCKSTATE();
+ return (0);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list