diff --git a/sys/rpc/svc.c b/sys/rpc/svc.c index 8af9e80f0198..fbddafbfecbb 100644 --- a/sys/rpc/svc.c +++ b/sys/rpc/svc.c @@ -175,12 +175,12 @@ svcpool_destroy(SVCPOOL *pool) mtx_lock(&pool->sp_lock); } - mtx_destroy(&pool->sp_lock); - TAILQ_FOREACH_SAFE(xprt, &cleanup, xp_link, nxprt) { SVC_RELEASE(xprt); } + mtx_destroy(&pool->sp_lock); + if (pool->sp_rcache) replay_freecache(pool->sp_rcache); @@ -353,15 +353,16 @@ xprt_active(SVCXPRT *xprt) { SVCPOOL *pool = xprt->xp_pool; + mtx_lock(&pool->sp_lock); + if (!xprt->xp_registered) { /* * Race with xprt_unregister - we lose. */ + mtx_unlock(&pool->sp_lock); return; } - mtx_lock(&pool->sp_lock); - if (!xprt->xp_active) { TAILQ_INSERT_TAIL(&pool->sp_active, xprt, xp_alink); xprt->xp_active = TRUE; diff --git a/sys/rpc/svc.h b/sys/rpc/svc.h index 73c4414b3ef9..1bd3054b2be3 100644 --- a/sys/rpc/svc.h +++ b/sys/rpc/svc.h @@ -166,6 +166,7 @@ typedef struct __rpc_svcxprt { int xp_idletimeout; /* idle time before closing */ time_t xp_lastactive; /* time of last RPC */ u_int64_t xp_sockref; /* set by nfsv4 to identify socket */ + int xp_upcallset; /* socket upcall is set up */ #else int xp_fd; u_short xp_port; /* associated port number */ diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index be366de87b7f..7249270c5bdd 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -160,6 +160,7 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, solisten(so, SOMAXCONN, curthread); SOCKBUF_LOCK(&so->so_rcv); + xprt->xp_upcallset = 1; soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); SOCKBUF_UNLOCK(&so->so_rcv); @@ -234,6 +235,7 @@ svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr) xprt_register(xprt); SOCKBUF_LOCK(&so->so_rcv); + xprt->xp_upcallset = 1; soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); SOCKBUF_UNLOCK(&so->so_rcv); @@ -352,7 +354,10 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(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); xprt_inactive(xprt); sx_xunlock(&xprt->xp_lock); @@ -397,7 +402,10 @@ static void svc_vc_destroy_common(SVCXPRT *xprt) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(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); sx_destroy(&xprt->xp_lock); @@ -632,7 +640,10 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg, if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(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); xprt_inactive(xprt); cd->strm_stat = XPRT_DIED;