Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

svcrdma: Enqueue after setting XPT_CLOSE in completion handlers

I noticed the server was sometimes not closing the connection after
a flushed Send. For example, if the client responds with an RNR NAK
to a Reply from the server, that client might be deadlocked, and
thus wouldn't send any more traffic. Thus the server wouldn't have
any opportunity to notice the XPT_CLOSE bit has been set.

Enqueue the transport so that svcxprt notices the bit even if there
is no more transport activity after a flushed completion, QP access
error, or device removal event.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-By: Devesh Sharma <devesh.sharma@broadcom.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

authored by

Chuck Lever and committed by
J. Bruce Fields
77a08867 7e981a8a

+8 -3
+8 -3
net/sunrpc/xprtrdma/svc_rdma_transport.c
··· 290 290 ib_event_msg(event->event), event->event, 291 291 event->element.qp); 292 292 set_bit(XPT_CLOSE, &xprt->xpt_flags); 293 + svc_xprt_enqueue(xprt); 293 294 break; 294 295 } 295 296 } ··· 323 322 set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags); 324 323 if (test_bit(RDMAXPRT_CONN_PENDING, &xprt->sc_flags)) 325 324 goto out; 326 - svc_xprt_enqueue(&xprt->sc_xprt); 327 - goto out; 325 + goto out_enqueue; 328 326 329 327 flushed: 330 328 if (wc->status != IB_WC_WR_FLUSH_ERR) ··· 333 333 set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); 334 334 svc_rdma_put_context(ctxt, 1); 335 335 336 + out_enqueue: 337 + svc_xprt_enqueue(&xprt->sc_xprt); 336 338 out: 337 339 svc_xprt_put(&xprt->sc_xprt); 338 340 } ··· 360 358 361 359 if (unlikely(wc->status != IB_WC_SUCCESS)) { 362 360 set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); 361 + svc_xprt_enqueue(&xprt->sc_xprt); 363 362 if (wc->status != IB_WC_WR_FLUSH_ERR) 364 363 pr_err("svcrdma: Send: %s (%u/0x%x)\n", 365 364 ib_wc_status_msg(wc->status), ··· 572 569 case RDMA_CM_EVENT_DEVICE_REMOVAL: 573 570 dprintk("svcrdma: Device removal xprt=%p, cm_id=%p\n", 574 571 xprt, cma_id); 575 - if (xprt) 572 + if (xprt) { 576 573 set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); 574 + svc_xprt_enqueue(&xprt->sc_xprt); 575 + } 577 576 break; 578 577 579 578 default: