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 commit1c00dd0776
("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 commit8301a2c047
("xprtrdma: Limit work done by completion handler"). Fixes:a7bc211ac9
("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>
This commit is contained in:
parent
f1a03b76fe
commit
5c166bef4f
1 changed files with 9 additions and 2 deletions
|
@ -317,8 +317,15 @@ rpcrdma_recvcq_upcall(struct ib_cq *cq, void *cq_context)
|
||||||
static void
|
static void
|
||||||
rpcrdma_flush_cqs(struct rpcrdma_ep *ep)
|
rpcrdma_flush_cqs(struct rpcrdma_ep *ep)
|
||||||
{
|
{
|
||||||
rpcrdma_recvcq_upcall(ep->rep_attr.recv_cq, ep);
|
struct ib_wc wc;
|
||||||
rpcrdma_sendcq_upcall(ep->rep_attr.send_cq, ep);
|
LIST_HEAD(sched_list);
|
||||||
|
|
||||||
|
while (ib_poll_cq(ep->rep_attr.recv_cq, 1, &wc) > 0)
|
||||||
|
rpcrdma_recvcq_process_wc(&wc, &sched_list);
|
||||||
|
if (!list_empty(&sched_list))
|
||||||
|
rpcrdma_schedule_tasklet(&sched_list);
|
||||||
|
while (ib_poll_cq(ep->rep_attr.send_cq, 1, &wc) > 0)
|
||||||
|
rpcrdma_sendcq_process_wc(&wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RPC_DEBUG
|
#ifdef RPC_DEBUG
|
||||||
|
|
Loading…
Add table
Reference in a new issue