--- sys/fs/nfsserver/nfs_nfsdstate.c 2017-05-06 10:46:41.000000000 -0400 +++ sys/fs/nfsserver/nfs_nfsdstate.c 2017-05-20 11:30:47.708705000 -0400 @@ -644,8 +644,9 @@ nfsrv_getclient(nfsquad_t clientid, int cbprogram, NFSV4_CBVERS); if (clp->lc_req.nr_client != NULL) { SVC_ACQUIRE(nd->nd_xprt); - nd->nd_xprt->xp_p2 = - clp->lc_req.nr_client->cl_private; + mtx_lock(&nd->nd_xprt->xp_p2lock); + nd->nd_xprt->xp_p2 = clp->lc_req.nr_client; + mtx_unlock(&nd->nd_xprt->xp_p2lock); /* Disable idle timeout. */ nd->nd_xprt->xp_idletimeout = 0; nsep->sess_cbsess.nfsess_xprt = nd->nd_xprt; @@ -5881,8 +5882,9 @@ nfsrv_checksequence(struct nfsrv_descrip (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) { savxprt = sep->sess_cbsess.nfsess_xprt; SVC_ACQUIRE(nd->nd_xprt); - nd->nd_xprt->xp_p2 = - sep->sess_clp->lc_req.nr_client->cl_private; + mtx_lock(&nd->nd_xprt->xp_p2lock); + nd->nd_xprt->xp_p2 = sep->sess_clp->lc_req.nr_client; + mtx_unlock(&nd->nd_xprt->xp_p2lock); nd->nd_xprt->xp_idletimeout = 0; /* Disable timeout. */ sep->sess_cbsess.nfsess_xprt = nd->nd_xprt; if (savxprt != NULL) --- sys/rpc/clnt_bck.c 2017-04-26 12:45:36.000000000 -0400 +++ sys/rpc/clnt_bck.c 2017-05-13 08:15:45.078590000 -0400 @@ -299,7 +299,6 @@ call_again: /* * sosend consumes mreq. */ - sx_xlock(&xprt->xp_lock); error = sosend(xprt->xp_socket, NULL, NULL, mreq, NULL, 0, curthread); if (error != 0) printf("sosend=%d\n", error); mreq = NULL; @@ -308,13 +307,11 @@ printf("emsgsize\n"); SOCKBUF_LOCK(&xprt->xp_socket->so_snd); sbwait(&xprt->xp_socket->so_snd); SOCKBUF_UNLOCK(&xprt->xp_socket->so_snd); - sx_xunlock(&xprt->xp_lock); AUTH_VALIDATE(auth, xid, NULL, NULL); mtx_lock(&ct->ct_lock); TAILQ_REMOVE(&ct->ct_pending, cr, cr_link); goto call_again; } - sx_xunlock(&xprt->xp_lock); reply_msg.acpted_rply.ar_verf.oa_flavor = AUTH_NULL; reply_msg.acpted_rply.ar_verf.oa_base = cr->cr_verf; @@ -550,10 +547,12 @@ clnt_bck_destroy(CLIENT *cl) void clnt_bck_svccall(void *arg, struct mbuf *mrep, uint32_t xid) { - struct ct_data *ct = (struct ct_data *)arg; + CLIENT *cl = (CLIENT *)arg; + struct ct_data *ct; struct ct_request *cr; int foundreq; + ct = (struct ct_data *)cl->cl_private; mtx_lock(&ct->ct_lock); ct->ct_upcallrefs++; /* --- sys/rpc/clnt_vc.c 2017-05-08 07:40:04.000000000 -0400 +++ sys/rpc/clnt_vc.c 2017-05-13 08:15:45.081819000 -0400 @@ -726,7 +726,9 @@ clnt_vc_control(CLIENT *cl, u_int reques case CLSET_BACKCHANNEL: xprt = (SVCXPRT *)info; if (ct->ct_backchannelxprt == NULL) { - xprt->xp_p2 = ct; + mtx_lock(&xprt->xp_p2lock); + xprt->xp_p2 = cl; + mtx_unlock(&xprt->xp_p2lock); ct->ct_backchannelxprt = xprt; } break; @@ -804,11 +806,9 @@ clnt_vc_destroy(CLIENT *cl) xprt = ct->ct_backchannelxprt; ct->ct_backchannelxprt = NULL; if (xprt != NULL) { - mtx_unlock(&ct->ct_lock); /* To avoid a LOR. */ - sx_xlock(&xprt->xp_lock); - mtx_lock(&ct->ct_lock); + mtx_lock(&xprt->xp_p2lock); xprt->xp_p2 = NULL; - sx_xunlock(&xprt->xp_lock); + mtx_unlock(&xprt->xp_p2lock); } if (ct->ct_socket) { --- sys/rpc/svc.h 2017-04-26 12:45:36.000000000 -0400 +++ sys/rpc/svc.h 2017-05-13 08:15:45.084121000 -0400 @@ -173,6 +173,7 @@ typedef struct __rpc_svcxprt { int xp_upcallset; /* socket upcall is set up */ uint32_t xp_snd_cnt; /* # of bytes to send to socket */ uint32_t xp_snt_cnt; /* # of bytes sent to socket */ + struct mtx xp_p2lock; #else int xp_fd; u_short xp_port; /* associated port number */ --- sys/rpc/svc_dg.c 2017-04-26 12:45:36.000000000 -0400 +++ sys/rpc/svc_dg.c 2017-05-13 08:15:45.085912000 -0400 @@ -118,6 +118,7 @@ svc_dg_create(SVCPOOL *pool, struct sock xprt = svc_xprt_alloc(); sx_init(&xprt->xp_lock, "xprt->xp_lock"); + mtx_init(&xprt->xp_p2lock, "xprt->xp_p2lock", NULL, MTX_DEF); xprt->xp_pool = pool; xprt->xp_socket = so; xprt->xp_p1 = NULL; @@ -276,6 +277,7 @@ svc_dg_destroy(SVCXPRT *xprt) SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); sx_destroy(&xprt->xp_lock); + mtx_destroy(&xprt->xp_p2lock); if (xprt->xp_socket) (void)soclose(xprt->xp_socket); --- sys/rpc/svc_vc.c 2017-04-26 12:45:36.000000000 -0400 +++ sys/rpc/svc_vc.c 2017-05-13 08:15:45.088245000 -0400 @@ -163,6 +163,7 @@ svc_vc_create(SVCPOOL *pool, struct sock xprt = svc_xprt_alloc(); sx_init(&xprt->xp_lock, "xprt->xp_lock"); + mtx_init(&xprt->xp_p2lock, "xprt->xp_p2lock", NULL, MTX_DEF); xprt->xp_pool = pool; xprt->xp_socket = so; xprt->xp_p1 = NULL; @@ -192,6 +193,7 @@ svc_vc_create(SVCPOOL *pool, struct sock cleanup_svc_vc_create: sx_destroy(&xprt->xp_lock); + mtx_destroy(&xprt->xp_p2lock); svc_xprt_free(xprt); return (NULL); @@ -239,6 +241,7 @@ svc_vc_create_conn(SVCPOOL *pool, struct xprt = svc_xprt_alloc(); sx_init(&xprt->xp_lock, "xprt->xp_lock"); + mtx_init(&xprt->xp_p2lock, "xprt->xp_p2lock", NULL, MTX_DEF); xprt->xp_pool = pool; xprt->xp_socket = so; xprt->xp_p1 = cd; @@ -280,6 +283,7 @@ svc_vc_create_conn(SVCPOOL *pool, struct return (xprt); cleanup_svc_vc_create: sx_destroy(&xprt->xp_lock); + mtx_destroy(&xprt->xp_p2lock); svc_xprt_free(xprt); mem_free(cd, sizeof(*cd)); @@ -300,6 +304,7 @@ svc_vc_create_backchannel(SVCPOOL *pool) xprt = svc_xprt_alloc(); sx_init(&xprt->xp_lock, "xprt->xp_lock"); + mtx_init(&xprt->xp_p2lock, "xprt->xp_p2lock", NULL, MTX_DEF); xprt->xp_pool = pool; xprt->xp_socket = NULL; xprt->xp_p1 = cd; @@ -659,6 +664,7 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_ms XDR xdrs; int error, rcvflag; uint32_t xid_plus_direction[2]; + CLIENT *cl; /* * Serialise access to the socket and our own record parsing @@ -682,10 +688,14 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_ms * The XID is in the first uint32_t of the reply * and the message direction is the second one. */ + mtx_lock(&xprt->xp_p2lock); if ((cd->mreq->m_len >= sizeof(xid_plus_direction) || m_length(cd->mreq, NULL) >= sizeof(xid_plus_direction)) && xprt->xp_p2 != NULL) { + cl = (CLIENT *)xprt->xp_p2; + CLNT_ACQUIRE(cl); + mtx_unlock(&xprt->xp_p2lock); m_copydata(cd->mreq, 0, sizeof(xid_plus_direction), (char *)xid_plus_direction); @@ -695,13 +705,15 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_ms ntohl(xid_plus_direction[1]); /* Check message direction. */ if (xid_plus_direction[1] == REPLY) { - clnt_bck_svccall(xprt->xp_p2, - cd->mreq, + clnt_bck_svccall(cl, cd->mreq, xid_plus_direction[0]); cd->mreq = NULL; + CLNT_RELEASE(cl); continue; } - } + CLNT_RELEASE(cl); + } else + mtx_unlock(&xprt->xp_p2lock); xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE); cd->mreq = NULL; @@ -794,27 +806,31 @@ svc_vc_backchannel_recv(SVCXPRT *xprt, s struct sockaddr **addrp, struct mbuf **mp) { struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1; + CLIENT *cl; struct ct_data *ct; struct mbuf *m; XDR xdrs; - sx_xlock(&xprt->xp_lock); - ct = (struct ct_data *)xprt->xp_p2; - if (ct == NULL) { - sx_xunlock(&xprt->xp_lock); + mtx_lock(&xprt->xp_p2lock); + cl = (CLIENT *)xprt->xp_p2; + if (cl == NULL) { + mtx_unlock(&xprt->xp_p2lock); return (FALSE); } + ct = (struct ct_data *)cl->cl_private; + CLNT_ACQUIRE(cl); + mtx_unlock(&xprt->xp_p2lock); mtx_lock(&ct->ct_lock); m = cd->mreq; if (m == NULL) { xprt_inactive_self(xprt); mtx_unlock(&ct->ct_lock); - sx_xunlock(&xprt->xp_lock); + CLNT_RELEASE(cl); return (FALSE); } cd->mreq = m->m_nextpkt; mtx_unlock(&ct->ct_lock); - sx_xunlock(&xprt->xp_lock); + CLNT_RELEASE(cl); xdrmbuf_create(&xdrs, m, XDR_DECODE); if (! xdr_callmsg(&xdrs, msg)) { @@ -892,6 +908,7 @@ svc_vc_backchannel_reply(SVCXPRT *xprt, struct mbuf *mrep; bool_t stat = TRUE; int error; + CLIENT *cl; /* * Leave space for record mark. @@ -921,14 +938,19 @@ svc_vc_backchannel_reply(SVCXPRT *xprt, *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) + mtx_lock(&xprt->xp_p2lock); + cl = (CLIENT *)xprt->xp_p2; + if (cl != NULL) { + CLNT_ACQUIRE(cl); + ct = (struct ct_data *)cl->cl_private; + mtx_unlock(&xprt->xp_p2lock); error = sosend(ct->ct_socket, NULL, NULL, mrep, NULL, 0, curthread); - else + CLNT_RELEASE(cl); + } else { + mtx_unlock(&xprt->xp_p2lock); error = EPIPE; - sx_xunlock(&xprt->xp_lock); + } if (!error) { stat = TRUE; }