diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2017-06-08 21:30:34 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2017-06-08 21:30:34 +0000 |
commit | 779f106aa169256b7010a1d8f963ff656b881e92 (patch) | |
tree | 01f96ac5827e2a95a385258086155b37b80ec6b9 /sys/rpc | |
parent | 4623e047a7c87148916e11e6c7b80409f6e45519 (diff) | |
download | src-test2-779f106aa169256b7010a1d8f963ff656b881e92.tar.gz src-test2-779f106aa169256b7010a1d8f963ff656b881e92.zip |
Notes
Diffstat (limited to 'sys/rpc')
-rw-r--r-- | sys/rpc/svc_vc.c | 91 |
1 files changed, 50 insertions, 41 deletions
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index 731ba28ce9e3..8a8b2bdbc8ab 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -96,6 +96,7 @@ 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); static int svc_vc_soupcall(struct socket *so, void *arg, int waitflag); +static int svc_vc_rendezvous_soupcall(struct socket *, void *, int); static struct xp_ops svc_vc_rendezvous_ops = { .xp_recv = svc_vc_rendezvous_recv, @@ -183,10 +184,10 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, solisten(so, -1, curthread); - SOCKBUF_LOCK(&so->so_rcv); + SOLISTEN_LOCK(so); xprt->xp_upcallset = 1; - soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); - SOCKBUF_UNLOCK(&so->so_rcv); + solisten_upcall_set(so, svc_vc_rendezvous_soupcall, xprt); + SOLISTEN_UNLOCK(so); return (xprt); @@ -316,9 +317,11 @@ svc_vc_create_backchannel(SVCPOOL *pool) int svc_vc_accept(struct socket *head, struct socket **sop) { - int error = 0; struct socket *so; + int error = 0; + short nbio; + /* XXXGL: shouldn't that be an assertion? */ if ((head->so_options & SO_ACCEPTCONN) == 0) { error = EINVAL; goto done; @@ -328,38 +331,26 @@ svc_vc_accept(struct socket *head, struct socket **sop) if (error != 0) goto done; #endif - ACCEPT_LOCK(); - if (TAILQ_EMPTY(&head->so_comp)) { - ACCEPT_UNLOCK(); - error = EWOULDBLOCK; - goto done; - } - so = TAILQ_FIRST(&head->so_comp); - KASSERT(!(so->so_qstate & SQ_INCOMP), ("svc_vc_accept: so SQ_INCOMP")); - KASSERT(so->so_qstate & SQ_COMP, ("svc_vc_accept: so not SQ_COMP")); - /* - * Before changing the flags on the socket, we have to bump the - * reference count. Otherwise, if the protocol calls sofree(), - * the socket will be released due to a zero refcount. - * XXX might not need soref() since this is simpler than kern_accept. + * XXXGL: we want non-blocking semantics. The socket could be a + * socket created by kernel as well as socket shared with userland, + * so we can't be sure about presense of SS_NBIO. We also shall not + * toggle it on the socket, since that may surprise userland. So we + * set SS_NBIO only temporarily. */ - SOCK_LOCK(so); /* soref() and so_state update */ - soref(so); /* file descriptor reference */ - - TAILQ_REMOVE(&head->so_comp, so, so_list); - head->so_qlen--; - so->so_state |= (head->so_state & SS_NBIO); - so->so_qstate &= ~SQ_COMP; - so->so_head = NULL; - - SOCK_UNLOCK(so); - ACCEPT_UNLOCK(); + SOLISTEN_LOCK(head); + nbio = head->so_state & SS_NBIO; + head->so_state |= SS_NBIO; + error = solisten_dequeue(head, &so, 0); + head->so_state &= (nbio & ~SS_NBIO); + if (error) + goto done; + so->so_state |= nbio; *sop = so; /* connection has been removed from the listen queue */ - KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0); + KNOTE_UNLOCKED(&head->so_rdsel.si_note, 0); done: return (error); } @@ -392,21 +383,21 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, * connection arrives after our call to accept fails * with EWOULDBLOCK. */ - ACCEPT_LOCK(); - if (TAILQ_EMPTY(&xprt->xp_socket->so_comp)) + SOLISTEN_LOCK(xprt->xp_socket); + if (TAILQ_EMPTY(&xprt->xp_socket->sol_comp)) xprt_inactive_self(xprt); - ACCEPT_UNLOCK(); + SOLISTEN_UNLOCK(xprt->xp_socket); sx_xunlock(&xprt->xp_lock); return (FALSE); } if (error) { - SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); + SOLISTEN_LOCK(xprt->xp_socket); if (xprt->xp_upcallset) { xprt->xp_upcallset = 0; soupcall_clear(xprt->xp_socket, SO_RCV); } - SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); + SOLISTEN_UNLOCK(xprt->xp_socket); xprt_inactive_self(xprt); sx_xunlock(&xprt->xp_lock); return (FALSE); @@ -453,12 +444,6 @@ svc_vc_rendezvous_stat(SVCXPRT *xprt) static void svc_vc_destroy_common(SVCXPRT *xprt) { - SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - if (xprt->xp_upcallset) { - xprt->xp_upcallset = 0; - soupcall_clear(xprt->xp_socket, SO_RCV); - } - SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); if (xprt->xp_socket) (void)soclose(xprt->xp_socket); @@ -472,6 +457,13 @@ static void svc_vc_rendezvous_destroy(SVCXPRT *xprt) { + SOLISTEN_LOCK(xprt->xp_socket); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + solisten_upcall_set(xprt->xp_socket, NULL, NULL); + } + SOLISTEN_UNLOCK(xprt->xp_socket); + svc_vc_destroy_common(xprt); } @@ -480,6 +472,13 @@ svc_vc_destroy(SVCXPRT *xprt) { struct cf_conn *cd = (struct cf_conn *)xprt->xp_p1; + SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } + SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); + svc_vc_destroy_common(xprt); if (cd->mreq) @@ -958,6 +957,16 @@ svc_vc_soupcall(struct socket *so, void *arg, int waitflag) return (SU_OK); } +static int +svc_vc_rendezvous_soupcall(struct socket *head, void *arg, int waitflag) +{ + SVCXPRT *xprt = (SVCXPRT *) arg; + + if (!TAILQ_EMPTY(&head->sol_comp)) + xprt_active(xprt); + return (SU_OK); +} + #if 0 /* * Get the effective UID of the sending process. Used by rpcbind, keyserv |