Skip to content

Commit d6ccebf

Browse files
chuckleveramschuma-ntap
authored andcommitted
xprtrdma: Disconnect on flushed completion
Completion errors after a disconnect often occur much sooner than a CM_DISCONNECT event. Use this to try to detect connection loss more quickly. Note that other kernel ULPs do take care to disconnect explicitly when a WR is flushed. Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 897b7be commit d6ccebf

File tree

4 files changed

+47
-18
lines changed

4 files changed

+47
-18
lines changed

include/trace/events/rpcrdma.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ DECLARE_EVENT_CLASS(xprtrdma_connect_class,
109109
__assign_str(port, rpcrdma_portstr(r_xprt));
110110
),
111111

112-
TP_printk("peer=[%s]:%s r_xprt=%p: rc=%d connect status=%d",
112+
TP_printk("peer=[%s]:%s r_xprt=%p: rc=%d connection status=%d",
113113
__get_str(addr), __get_str(port), __entry->r_xprt,
114114
__entry->rc, __entry->connect_status
115115
)
@@ -411,6 +411,7 @@ TRACE_EVENT(xprtrdma_inline_thresh,
411411

412412
DEFINE_CONN_EVENT(connect);
413413
DEFINE_CONN_EVENT(disconnect);
414+
DEFINE_CONN_EVENT(flush_dct);
414415

415416
DEFINE_RXPRT_EVENT(xprtrdma_create);
416417
DEFINE_RXPRT_EVENT(xprtrdma_op_destroy);

net/sunrpc/xprtrdma/frwr_ops.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,8 @@ struct rpcrdma_mr_seg *frwr_map(struct rpcrdma_xprt *r_xprt,
358358

359359
/**
360360
* frwr_wc_fastreg - Invoked by RDMA provider for a flushed FastReg WC
361-
* @cq: completion queue (ignored)
362-
* @wc: completed WR
361+
* @cq: completion queue
362+
* @wc: WCE for a completed FastReg WR
363363
*
364364
*/
365365
static void frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc)
@@ -371,6 +371,8 @@ static void frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc)
371371
/* WARNING: Only wr_cqe and status are reliable at this point */
372372
trace_xprtrdma_wc_fastreg(wc, frwr);
373373
/* The MR will get recycled when the associated req is retransmitted */
374+
375+
rpcrdma_flush_disconnect(cq, wc);
374376
}
375377

376378
/**
@@ -441,8 +443,8 @@ static void __frwr_release_mr(struct ib_wc *wc, struct rpcrdma_mr *mr)
441443

442444
/**
443445
* frwr_wc_localinv - Invoked by RDMA provider for a LOCAL_INV WC
444-
* @cq: completion queue (ignored)
445-
* @wc: completed WR
446+
* @cq: completion queue
447+
* @wc: WCE for a completed LocalInv WR
446448
*
447449
*/
448450
static void frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc)
@@ -455,12 +457,14 @@ static void frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc)
455457
/* WARNING: Only wr_cqe and status are reliable at this point */
456458
trace_xprtrdma_wc_li(wc, frwr);
457459
__frwr_release_mr(wc, mr);
460+
461+
rpcrdma_flush_disconnect(cq, wc);
458462
}
459463

460464
/**
461465
* frwr_wc_localinv_wake - Invoked by RDMA provider for a LOCAL_INV WC
462-
* @cq: completion queue (ignored)
463-
* @wc: completed WR
466+
* @cq: completion queue
467+
* @wc: WCE for a completed LocalInv WR
464468
*
465469
* Awaken anyone waiting for an MR to finish being fenced.
466470
*/
@@ -475,6 +479,8 @@ static void frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc)
475479
trace_xprtrdma_wc_li_wake(wc, frwr);
476480
__frwr_release_mr(wc, mr);
477481
complete(&frwr->fr_linv_done);
482+
483+
rpcrdma_flush_disconnect(cq, wc);
478484
}
479485

480486
/**
@@ -562,8 +568,8 @@ void frwr_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
562568

563569
/**
564570
* frwr_wc_localinv_done - Invoked by RDMA provider for a signaled LOCAL_INV WC
565-
* @cq: completion queue (ignored)
566-
* @wc: completed WR
571+
* @cq: completion queue
572+
* @wc: WCE for a completed LocalInv WR
567573
*
568574
*/
569575
static void frwr_wc_localinv_done(struct ib_cq *cq, struct ib_wc *wc)
@@ -581,6 +587,8 @@ static void frwr_wc_localinv_done(struct ib_cq *cq, struct ib_wc *wc)
581587
/* Ensure @rep is generated before __frwr_release_mr */
582588
smp_rmb();
583589
rpcrdma_complete_rqst(rep);
590+
591+
rpcrdma_flush_disconnect(cq, wc);
584592
}
585593

586594
/**

net/sunrpc/xprtrdma/verbs.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,32 @@ rpcrdma_qp_event_handler(struct ib_event *event, void *context)
128128
trace_xprtrdma_qp_event(r_xprt, event);
129129
}
130130

131+
/**
132+
* rpcrdma_flush_disconnect - Disconnect on flushed completion
133+
* @cq: completion queue
134+
* @wc: work completion entry
135+
*
136+
* Must be called in process context.
137+
*/
138+
void rpcrdma_flush_disconnect(struct ib_cq *cq, struct ib_wc *wc)
139+
{
140+
struct rpcrdma_xprt *r_xprt = cq->cq_context;
141+
struct rpc_xprt *xprt = &r_xprt->rx_xprt;
142+
143+
if (wc->status != IB_WC_SUCCESS && r_xprt->rx_ep.rep_connected == 1) {
144+
r_xprt->rx_ep.rep_connected = -ECONNABORTED;
145+
trace_xprtrdma_flush_dct(r_xprt, wc->status);
146+
xprt_force_disconnect(xprt);
147+
}
148+
}
149+
131150
/**
132151
* rpcrdma_wc_send - Invoked by RDMA provider for each polled Send WC
133152
* @cq: completion queue
134-
* @wc: completed WR
153+
* @wc: WCE for a completed Send WR
135154
*
136155
*/
137-
static void
138-
rpcrdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
156+
static void rpcrdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
139157
{
140158
struct ib_cqe *cqe = wc->wr_cqe;
141159
struct rpcrdma_sendctx *sc =
@@ -144,21 +162,21 @@ rpcrdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
144162
/* WARNING: Only wr_cqe and status are reliable at this point */
145163
trace_xprtrdma_wc_send(sc, wc);
146164
rpcrdma_sendctx_put_locked((struct rpcrdma_xprt *)cq->cq_context, sc);
165+
rpcrdma_flush_disconnect(cq, wc);
147166
}
148167

149168
/**
150169
* rpcrdma_wc_receive - Invoked by RDMA provider for each polled Receive WC
151-
* @cq: completion queue (ignored)
152-
* @wc: completed WR
170+
* @cq: completion queue
171+
* @wc: WCE for a completed Receive WR
153172
*
154173
*/
155-
static void
156-
rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
174+
static void rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
157175
{
158176
struct ib_cqe *cqe = wc->wr_cqe;
159177
struct rpcrdma_rep *rep = container_of(cqe, struct rpcrdma_rep,
160178
rr_cqe);
161-
struct rpcrdma_xprt *r_xprt = rep->rr_rxprt;
179+
struct rpcrdma_xprt *r_xprt = cq->cq_context;
162180

163181
/* WARNING: Only wr_cqe and status are reliable at this point */
164182
trace_xprtrdma_wc_receive(wc);
@@ -179,6 +197,7 @@ rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
179197
return;
180198

181199
out_flushed:
200+
rpcrdma_flush_disconnect(cq, wc);
182201
rpcrdma_rep_destroy(rep);
183202
}
184203

@@ -395,7 +414,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
395414
goto out_destroy;
396415
}
397416

398-
ep->rep_attr.recv_cq = ib_alloc_cq_any(id->device, NULL,
417+
ep->rep_attr.recv_cq = ib_alloc_cq_any(id->device, r_xprt,
399418
ep->rep_attr.cap.max_recv_wr,
400419
IB_POLL_WORKQUEUE);
401420
if (IS_ERR(ep->rep_attr.recv_cq)) {

net/sunrpc/xprtrdma/xprt_rdma.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ extern unsigned int xprt_rdma_memreg_strategy;
452452
/*
453453
* Endpoint calls - xprtrdma/verbs.c
454454
*/
455+
void rpcrdma_flush_disconnect(struct ib_cq *cq, struct ib_wc *wc);
455456
int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt);
456457
void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt);
457458

0 commit comments

Comments
 (0)