@@ -84,7 +84,8 @@ static void rpcrdma_rep_destroy(struct rpcrdma_rep *rep);
84
84
static void rpcrdma_reps_unmap (struct rpcrdma_xprt * r_xprt );
85
85
static void rpcrdma_mrs_create (struct rpcrdma_xprt * r_xprt );
86
86
static void rpcrdma_mrs_destroy (struct rpcrdma_xprt * r_xprt );
87
- static int rpcrdma_ep_destroy (struct rpcrdma_ep * ep );
87
+ static void rpcrdma_ep_get (struct rpcrdma_ep * ep );
88
+ static int rpcrdma_ep_put (struct rpcrdma_ep * ep );
88
89
static struct rpcrdma_regbuf *
89
90
rpcrdma_regbuf_alloc (size_t size , enum dma_data_direction direction ,
90
91
gfp_t flags );
@@ -97,7 +98,8 @@ static void rpcrdma_regbuf_free(struct rpcrdma_regbuf *rb);
97
98
*/
98
99
static void rpcrdma_xprt_drain (struct rpcrdma_xprt * r_xprt )
99
100
{
100
- struct rdma_cm_id * id = r_xprt -> rx_ep -> re_id ;
101
+ struct rpcrdma_ep * ep = r_xprt -> rx_ep ;
102
+ struct rdma_cm_id * id = ep -> re_id ;
101
103
102
104
/* Flush Receives, then wait for deferred Reply work
103
105
* to complete.
@@ -108,6 +110,8 @@ static void rpcrdma_xprt_drain(struct rpcrdma_xprt *r_xprt)
108
110
* local invalidations.
109
111
*/
110
112
ib_drain_sq (id -> qp );
113
+
114
+ rpcrdma_ep_put (ep );
111
115
}
112
116
113
117
/**
@@ -126,23 +130,27 @@ static void rpcrdma_qp_event_handler(struct ib_event *event, void *context)
126
130
trace_xprtrdma_qp_event (ep , event );
127
131
}
128
132
133
+ /* Ensure xprt_force_disconnect() is invoked exactly once when a
134
+ * connection is closed or lost. (The important thing is it needs
135
+ * to be invoked "at least" once).
136
+ */
137
+ static void rpcrdma_force_disconnect (struct rpcrdma_ep * ep )
138
+ {
139
+ if (atomic_add_unless (& ep -> re_force_disconnect , 1 , 1 ))
140
+ xprt_force_disconnect (ep -> re_xprt );
141
+ }
142
+
129
143
/**
130
144
* rpcrdma_flush_disconnect - Disconnect on flushed completion
131
- * @cq: completion queue
145
+ * @r_xprt: transport to disconnect
132
146
* @wc: work completion entry
133
147
*
134
148
* Must be called in process context.
135
149
*/
136
- void rpcrdma_flush_disconnect (struct ib_cq * cq , struct ib_wc * wc )
150
+ void rpcrdma_flush_disconnect (struct rpcrdma_xprt * r_xprt , struct ib_wc * wc )
137
151
{
138
- struct rpcrdma_xprt * r_xprt = cq -> cq_context ;
139
- struct rpc_xprt * xprt = & r_xprt -> rx_xprt ;
140
-
141
- if (wc -> status != IB_WC_SUCCESS &&
142
- r_xprt -> rx_ep -> re_connect_status == 1 ) {
143
- r_xprt -> rx_ep -> re_connect_status = - ECONNABORTED ;
144
- xprt_force_disconnect (xprt );
145
- }
152
+ if (wc -> status != IB_WC_SUCCESS )
153
+ rpcrdma_force_disconnect (r_xprt -> rx_ep );
146
154
}
147
155
148
156
/**
@@ -156,11 +164,12 @@ static void rpcrdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
156
164
struct ib_cqe * cqe = wc -> wr_cqe ;
157
165
struct rpcrdma_sendctx * sc =
158
166
container_of (cqe , struct rpcrdma_sendctx , sc_cqe );
167
+ struct rpcrdma_xprt * r_xprt = cq -> cq_context ;
159
168
160
169
/* WARNING: Only wr_cqe and status are reliable at this point */
161
170
trace_xprtrdma_wc_send (sc , wc );
162
- rpcrdma_sendctx_put_locked (( struct rpcrdma_xprt * ) cq -> cq_context , sc );
163
- rpcrdma_flush_disconnect (cq , wc );
171
+ rpcrdma_sendctx_put_locked (r_xprt , sc );
172
+ rpcrdma_flush_disconnect (r_xprt , wc );
164
173
}
165
174
166
175
/**
@@ -195,7 +204,7 @@ static void rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
195
204
return ;
196
205
197
206
out_flushed :
198
- rpcrdma_flush_disconnect (cq , wc );
207
+ rpcrdma_flush_disconnect (r_xprt , wc );
199
208
rpcrdma_rep_destroy (rep );
200
209
}
201
210
@@ -239,7 +248,6 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
239
248
{
240
249
struct sockaddr * sap = (struct sockaddr * )& id -> route .addr .dst_addr ;
241
250
struct rpcrdma_ep * ep = id -> context ;
242
- struct rpc_xprt * xprt = ep -> re_xprt ;
243
251
244
252
might_sleep ();
245
253
@@ -263,10 +271,9 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
263
271
/* fall through */
264
272
case RDMA_CM_EVENT_ADDR_CHANGE :
265
273
ep -> re_connect_status = - ENODEV ;
266
- xprt_force_disconnect (xprt );
267
274
goto disconnected ;
268
275
case RDMA_CM_EVENT_ESTABLISHED :
269
- kref_get ( & ep -> re_kref );
276
+ rpcrdma_ep_get ( ep );
270
277
ep -> re_connect_status = 1 ;
271
278
rpcrdma_update_cm_private (ep , & event -> param .conn );
272
279
trace_xprtrdma_inline_thresh (ep );
@@ -288,8 +295,8 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
288
295
case RDMA_CM_EVENT_DISCONNECTED :
289
296
ep -> re_connect_status = - ECONNABORTED ;
290
297
disconnected :
291
- xprt_force_disconnect ( xprt );
292
- return rpcrdma_ep_destroy (ep );
298
+ rpcrdma_force_disconnect ( ep );
299
+ return rpcrdma_ep_put (ep );
293
300
default :
294
301
break ;
295
302
}
@@ -345,7 +352,7 @@ static struct rdma_cm_id *rpcrdma_create_id(struct rpcrdma_xprt *r_xprt,
345
352
return ERR_PTR (rc );
346
353
}
347
354
348
- static void rpcrdma_ep_put (struct kref * kref )
355
+ static void rpcrdma_ep_destroy (struct kref * kref )
349
356
{
350
357
struct rpcrdma_ep * ep = container_of (kref , struct rpcrdma_ep , re_kref );
351
358
@@ -369,13 +376,18 @@ static void rpcrdma_ep_put(struct kref *kref)
369
376
module_put (THIS_MODULE );
370
377
}
371
378
379
+ static noinline void rpcrdma_ep_get (struct rpcrdma_ep * ep )
380
+ {
381
+ kref_get (& ep -> re_kref );
382
+ }
383
+
372
384
/* Returns:
373
385
* %0 if @ep still has a positive kref count, or
374
386
* %1 if @ep was destroyed successfully.
375
387
*/
376
- static int rpcrdma_ep_destroy (struct rpcrdma_ep * ep )
388
+ static noinline int rpcrdma_ep_put (struct rpcrdma_ep * ep )
377
389
{
378
- return kref_put (& ep -> re_kref , rpcrdma_ep_put );
390
+ return kref_put (& ep -> re_kref , rpcrdma_ep_destroy );
379
391
}
380
392
381
393
static int rpcrdma_ep_create (struct rpcrdma_xprt * r_xprt )
@@ -492,7 +504,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
492
504
return 0 ;
493
505
494
506
out_destroy :
495
- rpcrdma_ep_destroy (ep );
507
+ rpcrdma_ep_put (ep );
496
508
rdma_destroy_id (id );
497
509
out_free :
498
510
kfree (ep );
@@ -519,10 +531,13 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
519
531
return rc ;
520
532
ep = r_xprt -> rx_ep ;
521
533
522
- ep -> re_connect_status = 0 ;
523
534
xprt_clear_connected (xprt );
524
-
525
535
rpcrdma_reset_cwnd (r_xprt );
536
+
537
+ /* Bump the ep's reference count while there are
538
+ * outstanding Receives.
539
+ */
540
+ rpcrdma_ep_get (ep );
526
541
rpcrdma_post_recvs (r_xprt , true);
527
542
528
543
rc = rpcrdma_sendctxs_create (r_xprt );
@@ -552,8 +567,6 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
552
567
rpcrdma_mrs_create (r_xprt );
553
568
554
569
out :
555
- if (rc )
556
- ep -> re_connect_status = rc ;
557
570
trace_xprtrdma_connect (r_xprt , rc );
558
571
return rc ;
559
572
}
@@ -587,7 +600,7 @@ void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt)
587
600
rpcrdma_mrs_destroy (r_xprt );
588
601
rpcrdma_sendctxs_destroy (r_xprt );
589
602
590
- if (rpcrdma_ep_destroy (ep ))
603
+ if (rpcrdma_ep_put (ep ))
591
604
rdma_destroy_id (id );
592
605
593
606
r_xprt -> rx_ep = NULL ;
0 commit comments