From owner-svn-src-projects@FreeBSD.ORG Wed Jan 1 01:46:58 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id BEA89E38; Wed, 1 Jan 2014 01:46:58 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id A94CF1222; Wed, 1 Jan 2014 01:46:58 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id s011kwMU089735; Wed, 1 Jan 2014 01:46:58 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.7/8.14.7/Submit) id s011ku84089718; Wed, 1 Jan 2014 01:46:56 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201401010146.s011ku84089718@svn.freebsd.org> From: Rick Macklem Date: Wed, 1 Jan 2014 01:46:56 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r260158 - in projects/nfsv4.1-server/sys: conf fs/nfs fs/nfsserver modules/krpc rpc X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Jan 2014 01:46:58 -0000 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 #include +#include #include @@ -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 ***