From owner-svn-src-projects@FreeBSD.ORG Sun Dec 11 00:04:19 2011 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 399F0106566B; Sun, 11 Dec 2011 00:04:19 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2920B8FC0C; Sun, 11 Dec 2011 00:04:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id pBB04JMq027666; Sun, 11 Dec 2011 00:04:19 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id pBB04JFO027663; Sun, 11 Dec 2011 00:04:19 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201112110004.pBB04JFO027663@svn.freebsd.org> From: Rick Macklem Date: Sun, 11 Dec 2011 00:04:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r228404 - projects/nfsv4.1-client/sys/rpc X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 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: Sun, 11 Dec 2011 00:04:19 -0000 Author: rmacklem Date: Sun Dec 11 00:04:18 2011 New Revision: 228404 URL: http://svn.freebsd.org/changeset/base/228404 Log: Add the backchannel methods and svc_vc_create_backchannel() to the server side kernel RPC, so that a backchannel xprt structure can be created and used to handle RPC requests received by the clnt_vc receive upcall. Once the RPC request is marshalled to the server using the xprt structure, it is handled like any other server side RPC, with the reply being sent on the clnt_vc socket. Modified: projects/nfsv4.1-client/sys/rpc/svc.h projects/nfsv4.1-client/sys/rpc/svc_vc.c Modified: projects/nfsv4.1-client/sys/rpc/svc.h ============================================================================== --- projects/nfsv4.1-client/sys/rpc/svc.h Sat Dec 10 23:57:32 2011 (r228403) +++ projects/nfsv4.1-client/sys/rpc/svc.h Sun Dec 11 00:04:18 2011 (r228404) @@ -703,6 +703,8 @@ extern SVCXPRT *svc_vc_create(SVCPOOL *, * const size_t recvsize; -- max recv size */ +extern SVCXPRT *svc_vc_create_backchannel(SVCPOOL *); + /* * Generic TLI create routine */ Modified: projects/nfsv4.1-client/sys/rpc/svc_vc.c ============================================================================== --- projects/nfsv4.1-client/sys/rpc/svc_vc.c Sat Dec 10 23:57:32 2011 (r228403) +++ projects/nfsv4.1-client/sys/rpc/svc_vc.c Sun Dec 11 00:04:18 2011 (r228404) @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include @@ -83,6 +84,14 @@ static bool_t svc_vc_reply(SVCXPRT *, st static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in); static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq, void *in); +static void svc_vc_backchannel_destroy(SVCXPRT *); +static enum xprt_stat svc_vc_backchannel_stat(SVCXPRT *); +static bool_t svc_vc_backchannel_recv(SVCXPRT *, struct rpc_msg *, + struct sockaddr **, struct mbuf **); +static bool_t svc_vc_backchannel_reply(SVCXPRT *, struct rpc_msg *, + struct sockaddr *, struct mbuf *); +static bool_t svc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq, + void *in); static SVCXPRT *svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr); static int svc_vc_accept(struct socket *head, struct socket **sop); @@ -105,12 +114,12 @@ static struct xp_ops svc_vc_ops = { .xp_control = svc_vc_control }; -struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ - enum xprt_stat strm_stat; - struct mbuf *mpending; /* unparsed data read from the socket */ - struct mbuf *mreq; /* current record being built from mpending */ - uint32_t resid; /* number of bytes needed for fragment */ - bool_t eor; /* reading last fragment of current record */ +static struct xp_ops svc_vc_backchannel_ops = { + .xp_recv = svc_vc_backchannel_recv, + .xp_stat = svc_vc_backchannel_stat, + .xp_reply = svc_vc_backchannel_reply, + .xp_destroy = svc_vc_backchannel_destroy, + .xp_control = svc_vc_backchannel_control }; /* @@ -267,6 +276,31 @@ cleanup_svc_vc_create: } /* + * Create a new transport for a backchannel on a clnt_vc socket. + */ +SVCXPRT * +svc_vc_create_backchannel(SVCPOOL *pool) +{ + SVCXPRT *xprt = NULL; + struct cf_conn *cd = NULL; + + cd = mem_alloc(sizeof(*cd)); + cd->strm_stat = XPRT_IDLE; + + xprt = svc_xprt_alloc(); + sx_init(&xprt->xp_lock, "xprt->xp_lock"); + xprt->xp_pool = pool; + xprt->xp_socket = NULL; + xprt->xp_p1 = cd; + xprt->xp_p2 = NULL; + xprt->xp_ops = &svc_vc_backchannel_ops; + + xprt_register(xprt); + + return (xprt); +} + +/* * This does all of the accept except the final call to soaccept. The * caller will call soaccept after dropping its locks (soaccept may * call malloc). @@ -452,6 +486,22 @@ svc_vc_destroy(SVCXPRT *xprt) mem_free(cd, sizeof(*cd)); } +static void +svc_vc_backchannel_destroy(SVCXPRT *xprt) +{ + struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1; + struct mbuf *m, *m2; + + svc_xprt_free(xprt); + m = cd->mreq; + while (m != NULL) { + m2 = m; + m = m->m_nextpkt; + m_freem(m2); + } + mem_free(cd, sizeof(*cd)); +} + /*ARGSUSED*/ static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in) @@ -466,6 +516,13 @@ svc_vc_rendezvous_control(SVCXPRT *xprt, return (FALSE); } +static bool_t +svc_vc_backchannel_control(SVCXPRT *xprt, const u_int rq, void *in) +{ + + return (FALSE); +} + static enum xprt_stat svc_vc_stat(SVCXPRT *xprt) { @@ -506,6 +563,19 @@ svc_vc_stat(SVCXPRT *xprt) return (XPRT_IDLE); } +static enum xprt_stat +svc_vc_backchannel_stat(SVCXPRT *xprt) +{ + struct cf_conn *cd; + + cd = (struct cf_conn *)(xprt->xp_p1); + + if (cd->mreq != NULL) + return (XPRT_MOREREQS); + + return (XPRT_IDLE); +} + static bool_t svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg, struct sockaddr **addrp, struct mbuf **mp) @@ -680,6 +750,45 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_ms } static bool_t +svc_vc_backchannel_recv(SVCXPRT *xprt, struct rpc_msg *msg, + struct sockaddr **addrp, struct mbuf **mp) +{ + struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1; + struct ct_data *ct; + struct mbuf *m; + XDR xdrs; + +printf("back rcv\n"); + sx_xlock(&xprt->xp_lock); + ct = (struct ct_data *)xprt->xp_p2; + if (ct == NULL) { + sx_xunlock(&xprt->xp_lock); + return (FALSE); + } + mtx_lock(&ct->ct_lock); + m = cd->mreq; + if (m == NULL) { + xprt_inactive(xprt); + mtx_unlock(&ct->ct_lock); + sx_xunlock(&xprt->xp_lock); + return (FALSE); + } + cd->mreq = m->m_nextpkt; + mtx_unlock(&ct->ct_lock); + sx_xunlock(&xprt->xp_lock); + + xdrmbuf_create(&xdrs, m, XDR_DECODE); + if (! xdr_callmsg(&xdrs, msg)) { + XDR_DESTROY(&xdrs); + return (FALSE); + } + *addrp = NULL; + *mp = xdrmbuf_getall(&xdrs); + XDR_DESTROY(&xdrs); + return (TRUE); +} + +static bool_t svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg, struct sockaddr *addr, struct mbuf *m) { @@ -733,6 +842,65 @@ svc_vc_reply(SVCXPRT *xprt, struct rpc_m } static bool_t +svc_vc_backchannel_reply(SVCXPRT *xprt, struct rpc_msg *msg, + struct sockaddr *addr, struct mbuf *m) +{ + struct ct_data *ct; + XDR xdrs; + struct mbuf *mrep; + bool_t stat = TRUE; + int error; + + /* + * Leave space for record mark. + */ + MGETHDR(mrep, M_WAIT, MT_DATA); + mrep->m_len = 0; + mrep->m_data += sizeof(uint32_t); + + xdrmbuf_create(&xdrs, mrep, XDR_ENCODE); + + if (msg->rm_reply.rp_stat == MSG_ACCEPTED && + msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { + if (!xdr_replymsg(&xdrs, msg)) + stat = FALSE; + else + xdrmbuf_append(&xdrs, m); + } else { + stat = xdr_replymsg(&xdrs, msg); + } + + if (stat) { + m_fixhdr(mrep); + + /* + * Prepend a record marker containing the reply length. + */ + M_PREPEND(mrep, sizeof(uint32_t), M_WAIT); + *mtod(mrep, uint32_t *) = + htonl(0x80000000 | (mrep->m_pkthdr.len + - sizeof(uint32_t))); + sx_xlock(&xprt->xp_lock); + ct = (struct ct_data *)xprt->xp_p2; + if (ct != NULL) + error = sosend(ct->ct_socket, NULL, NULL, mrep, NULL, + 0, curthread); + else + error = EPIPE; + sx_xunlock(&xprt->xp_lock); + if (!error) { + stat = TRUE; + } + } else { + m_freem(mrep); + } + + XDR_DESTROY(&xdrs); + + return (stat); +} + +static bool_t svc_vc_null() {