diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2014-11-08 20:14:45 -0500 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2014-11-25 13:39:20 -0500 |
commit | 5c166bef4fa138da45d756dc77a8cb29fced1714 (patch) | |
tree | 82c3e8832fdfa1ab5f9193d14146466f49ccc4e5 | |
parent | f1a03b76fecdb23983e2ad7e817e98d093ece9f7 (diff) |
xprtrdma: Re-write rpcrdma_flush_cqs()
Currently rpcrdma_flush_cqs() attempts to avoid code duplication,
and simply invokes rpcrdma_recvcq_upcall and rpcrdma_sendcq_upcall.
1. rpcrdma_flush_cqs() can run concurrently with provider upcalls.
Both flush_cqs() and the upcalls were invoking ib_poll_cq() in
different threads using the same wc buffers (ep->rep_recv_wcs
and ep->rep_send_wcs), added by commit 1c00dd077654 ("xprtrmda:
Reduce calls to ib_poll_cq() in completion handlers").
During transport disconnect processing, this sometimes resulted
in the same reply getting added to the rpcrdma_tasklets_g list
more than once, which corrupted the list.
2. The upcall functions drain only a limited number of CQEs,
thanks to the poll budget added by commit 8301a2c047cc
("xprtrdma: Limit work done by completion handler").
Fixes: a7bc211ac926 ("xprtrdma: On disconnect, don't ignore ... ")
BugLink: https://bugzilla.linux-nfs.org/show_bug.cgi?id=276
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 478b2fda83a6..e6ac9643fe56 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -317,8 +317,15 @@ rpcrdma_recvcq_upcall(struct ib_cq *cq, void *cq_context) | |||
317 | static void | 317 | static void |
318 | rpcrdma_flush_cqs(struct rpcrdma_ep *ep) | 318 | rpcrdma_flush_cqs(struct rpcrdma_ep *ep) |
319 | { | 319 | { |
320 | rpcrdma_recvcq_upcall(ep->rep_attr.recv_cq, ep); | 320 | struct ib_wc wc; |
321 | rpcrdma_sendcq_upcall(ep->rep_attr.send_cq, ep); | 321 | LIST_HEAD(sched_list); |
322 | |||
323 | while (ib_poll_cq(ep->rep_attr.recv_cq, 1, &wc) > 0) | ||
324 | rpcrdma_recvcq_process_wc(&wc, &sched_list); | ||
325 | if (!list_empty(&sched_list)) | ||
326 | rpcrdma_schedule_tasklet(&sched_list); | ||
327 | while (ib_poll_cq(ep->rep_attr.send_cq, 1, &wc) > 0) | ||
328 | rpcrdma_sendcq_process_wc(&wc); | ||
322 | } | 329 | } |
323 | 330 | ||
324 | #ifdef RPC_DEBUG | 331 | #ifdef RPC_DEBUG |