Skip to content

Commit 85cd8e2

Browse files
chuckleveramschuma-ntap
authored andcommitted
xprtrdma: Invoke rpcrdma_ep_create() in the connect worker
Refactor rpcrdma_ep_create(), rpcrdma_ep_disconnect(), and rpcrdma_ep_destroy(). rpcrdma_ep_create will be invoked at connect time instead of at transport set-up time. It will be responsible for allocating per- connection resources. In this patch it allocates the CQs and creates a QP. More to come. rpcrdma_ep_destroy() is the inverse functionality that is invoked at disconnect time. It will be responsible for releasing the CQs and QP. These changes should be safe to do because both connect and disconnect is guaranteed to be serialized by the transport send lock. This takes us another step closer to resolving the address and route only at connect time so that connection failover to another device will work correctly. Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 62a8950 commit 85cd8e2

File tree

3 files changed

+56
-103
lines changed

3 files changed

+56
-103
lines changed

net/sunrpc/xprtrdma/transport.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ xprt_rdma_destroy(struct rpc_xprt *xprt)
284284

285285
cancel_delayed_work_sync(&r_xprt->rx_connect_worker);
286286

287-
rpcrdma_ep_destroy(r_xprt);
287+
rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia);
288288
rpcrdma_buffer_destroy(&r_xprt->rx_buf);
289289
rpcrdma_ia_close(&r_xprt->rx_ia);
290290

@@ -351,13 +351,9 @@ xprt_setup_rdma(struct xprt_create *args)
351351
if (rc)
352352
goto out1;
353353

354-
rc = rpcrdma_ep_create(new_xprt);
355-
if (rc)
356-
goto out2;
357-
358354
rc = rpcrdma_buffer_create(new_xprt);
359355
if (rc)
360-
goto out3;
356+
goto out2;
361357

362358
if (!try_module_get(THIS_MODULE))
363359
goto out4;
@@ -375,8 +371,6 @@ xprt_setup_rdma(struct xprt_create *args)
375371
out4:
376372
rpcrdma_buffer_destroy(&new_xprt->rx_buf);
377373
rc = -ENODEV;
378-
out3:
379-
rpcrdma_ep_destroy(new_xprt);
380374
out2:
381375
rpcrdma_ia_close(&new_xprt->rx_ia);
382376
out1:

net/sunrpc/xprtrdma/verbs.c

Lines changed: 54 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ static void rpcrdma_rep_destroy(struct rpcrdma_rep *rep);
8484
static void rpcrdma_reps_unmap(struct rpcrdma_xprt *r_xprt);
8585
static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
8686
static void rpcrdma_mrs_destroy(struct rpcrdma_xprt *r_xprt);
87+
static void rpcrdma_ep_destroy(struct rpcrdma_xprt *r_xprt);
8788
static struct rpcrdma_regbuf *
8889
rpcrdma_regbuf_alloc(size_t size, enum dma_data_direction direction,
8990
gfp_t flags);
@@ -391,32 +392,17 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
391392
{
392393
struct rpcrdma_xprt *r_xprt = container_of(ia, struct rpcrdma_xprt,
393394
rx_ia);
394-
struct rpcrdma_ep *ep = &r_xprt->rx_ep;
395395

396-
/* This is similar to rpcrdma_ep_destroy, but:
397-
* - Don't cancel the connect worker.
398-
* - Don't call rpcrdma_ep_disconnect, which waits
399-
* for another conn upcall, which will deadlock.
400-
* - rdma_disconnect is unneeded, the underlying
401-
* connection is already gone.
402-
*/
403-
if (ia->ri_id->qp) {
396+
if (ia->ri_id->qp)
404397
rpcrdma_xprt_drain(r_xprt);
405-
rdma_destroy_qp(ia->ri_id);
406-
ia->ri_id->qp = NULL;
407-
}
408-
ib_free_cq(ep->rep_attr.recv_cq);
409-
ep->rep_attr.recv_cq = NULL;
410-
ib_free_cq(ep->rep_attr.send_cq);
411-
ep->rep_attr.send_cq = NULL;
412398

413-
/* The ULP is responsible for ensuring all DMA
414-
* mappings and MRs are gone.
415-
*/
416399
rpcrdma_reps_unmap(r_xprt);
417400
rpcrdma_reqs_reset(r_xprt);
418401
rpcrdma_mrs_destroy(r_xprt);
419402
rpcrdma_sendctxs_destroy(r_xprt);
403+
404+
rpcrdma_ep_destroy(r_xprt);
405+
420406
ib_dealloc_pd(ia->ri_pd);
421407
ia->ri_pd = NULL;
422408

@@ -434,11 +420,8 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
434420
void
435421
rpcrdma_ia_close(struct rpcrdma_ia *ia)
436422
{
437-
if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) {
438-
if (ia->ri_id->qp)
439-
rdma_destroy_qp(ia->ri_id);
423+
if (ia->ri_id && !IS_ERR(ia->ri_id))
440424
rdma_destroy_id(ia->ri_id);
441-
}
442425
ia->ri_id = NULL;
443426

444427
/* If the pd is still busy, xprtrdma missed freeing a resource */
@@ -447,25 +430,19 @@ rpcrdma_ia_close(struct rpcrdma_ia *ia)
447430
ia->ri_pd = NULL;
448431
}
449432

450-
/**
451-
* rpcrdma_ep_create - Create unconnected endpoint
452-
* @r_xprt: transport to instantiate
453-
*
454-
* Returns zero on success, or a negative errno.
455-
*/
456-
int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
433+
static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt,
434+
struct rdma_cm_id *id)
457435
{
458436
struct rpcrdma_ep *ep = &r_xprt->rx_ep;
459437
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
460438
struct rpcrdma_connect_private *pmsg = &ep->rep_cm_private;
461-
struct ib_cq *sendcq, *recvcq;
462439
int rc;
463440

464441
ep->rep_max_requests = r_xprt->rx_xprt.max_reqs;
465442
ep->rep_inline_send = xprt_rdma_max_inline_write;
466443
ep->rep_inline_recv = xprt_rdma_max_inline_read;
467444

468-
rc = frwr_query_device(r_xprt, ia->ri_id->device);
445+
rc = frwr_query_device(r_xprt, id->device);
469446
if (rc)
470447
return rc;
471448
r_xprt->rx_buf.rb_max_requests = cpu_to_be32(ep->rep_max_requests);
@@ -491,25 +468,22 @@ int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
491468
init_waitqueue_head(&ep->rep_connect_wait);
492469
ep->rep_receive_count = 0;
493470

494-
sendcq = ib_alloc_cq_any(ia->ri_id->device, r_xprt,
495-
ep->rep_attr.cap.max_send_wr + 1,
496-
IB_POLL_WORKQUEUE);
497-
if (IS_ERR(sendcq)) {
498-
rc = PTR_ERR(sendcq);
499-
goto out1;
471+
ep->rep_attr.send_cq = ib_alloc_cq_any(id->device, r_xprt,
472+
ep->rep_attr.cap.max_send_wr,
473+
IB_POLL_WORKQUEUE);
474+
if (IS_ERR(ep->rep_attr.send_cq)) {
475+
rc = PTR_ERR(ep->rep_attr.send_cq);
476+
goto out_destroy;
500477
}
501478

502-
recvcq = ib_alloc_cq_any(ia->ri_id->device, NULL,
503-
ep->rep_attr.cap.max_recv_wr + 1,
504-
IB_POLL_WORKQUEUE);
505-
if (IS_ERR(recvcq)) {
506-
rc = PTR_ERR(recvcq);
507-
goto out2;
479+
ep->rep_attr.recv_cq = ib_alloc_cq_any(id->device, NULL,
480+
ep->rep_attr.cap.max_recv_wr,
481+
IB_POLL_WORKQUEUE);
482+
if (IS_ERR(ep->rep_attr.recv_cq)) {
483+
rc = PTR_ERR(ep->rep_attr.recv_cq);
484+
goto out_destroy;
508485
}
509486

510-
ep->rep_attr.send_cq = sendcq;
511-
ep->rep_attr.recv_cq = recvcq;
512-
513487
/* Initialize cma parameters */
514488
memset(&ep->rep_remote_cma, 0, sizeof(ep->rep_remote_cma));
515489

@@ -525,7 +499,7 @@ int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
525499
/* Client offers RDMA Read but does not initiate */
526500
ep->rep_remote_cma.initiator_depth = 0;
527501
ep->rep_remote_cma.responder_resources =
528-
min_t(int, U8_MAX, ia->ri_id->device->attrs.max_qp_rd_atom);
502+
min_t(int, U8_MAX, id->device->attrs.max_qp_rd_atom);
529503

530504
/* Limit transport retries so client can detect server
531505
* GID changes quickly. RPC layer handles re-establishing
@@ -540,45 +514,41 @@ int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
540514
ep->rep_remote_cma.flow_control = 0;
541515
ep->rep_remote_cma.rnr_retry_count = 0;
542516

517+
rc = rdma_create_qp(id, ia->ri_pd, &ep->rep_attr);
518+
if (rc)
519+
goto out_destroy;
543520
return 0;
544521

545-
out2:
546-
ib_free_cq(sendcq);
547-
out1:
522+
out_destroy:
523+
rpcrdma_ep_destroy(r_xprt);
548524
return rc;
549525
}
550526

551-
/**
552-
* rpcrdma_ep_destroy - Disconnect and destroy endpoint.
553-
* @r_xprt: transport instance to shut down
554-
*
555-
*/
556-
void rpcrdma_ep_destroy(struct rpcrdma_xprt *r_xprt)
527+
static void rpcrdma_ep_destroy(struct rpcrdma_xprt *r_xprt)
557528
{
558529
struct rpcrdma_ep *ep = &r_xprt->rx_ep;
559530
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
560531

561532
if (ia->ri_id && ia->ri_id->qp) {
562-
rpcrdma_ep_disconnect(ep, ia);
563533
rdma_destroy_qp(ia->ri_id);
564534
ia->ri_id->qp = NULL;
565535
}
566536

567537
if (ep->rep_attr.recv_cq)
568538
ib_free_cq(ep->rep_attr.recv_cq);
539+
ep->rep_attr.recv_cq = NULL;
569540
if (ep->rep_attr.send_cq)
570541
ib_free_cq(ep->rep_attr.send_cq);
542+
ep->rep_attr.send_cq = NULL;
571543
}
572544

573545
/* Re-establish a connection after a device removal event.
574546
* Unlike a normal reconnection, a fresh PD and a new set
575547
* of MRs and buffers is needed.
576548
*/
577-
static int rpcrdma_ep_recreate_xprt(struct rpcrdma_xprt *r_xprt,
578-
struct ib_qp_init_attr *qp_init_attr)
549+
static int rpcrdma_ep_recreate_xprt(struct rpcrdma_xprt *r_xprt)
579550
{
580551
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
581-
struct rpcrdma_ep *ep = &r_xprt->rx_ep;
582552
int rc, err;
583553

584554
trace_xprtrdma_reinsert(r_xprt);
@@ -587,39 +557,24 @@ static int rpcrdma_ep_recreate_xprt(struct rpcrdma_xprt *r_xprt,
587557
if (rpcrdma_ia_open(r_xprt))
588558
goto out1;
589559

590-
rc = -ENOMEM;
591-
err = rpcrdma_ep_create(r_xprt);
592-
if (err) {
593-
pr_err("rpcrdma: rpcrdma_ep_create returned %d\n", err);
594-
goto out2;
595-
}
596-
memcpy(qp_init_attr, &ep->rep_attr, sizeof(*qp_init_attr));
597-
598560
rc = -ENETUNREACH;
599-
err = rdma_create_qp(ia->ri_id, ia->ri_pd, qp_init_attr);
600-
if (err) {
601-
pr_err("rpcrdma: rdma_create_qp returned %d\n", err);
602-
goto out3;
603-
}
561+
err = rpcrdma_ep_create(r_xprt, ia->ri_id);
562+
if (err)
563+
goto out2;
604564
return 0;
605565

606-
out3:
607-
rpcrdma_ep_destroy(r_xprt);
608566
out2:
609567
rpcrdma_ia_close(ia);
610568
out1:
611569
return rc;
612570
}
613571

614-
static int rpcrdma_ep_reconnect(struct rpcrdma_xprt *r_xprt,
615-
struct ib_qp_init_attr *qp_init_attr)
572+
static int rpcrdma_ep_reconnect(struct rpcrdma_xprt *r_xprt)
616573
{
617574
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
618575
struct rdma_cm_id *id, *old;
619576
int err, rc;
620577

621-
rpcrdma_ep_disconnect(&r_xprt->rx_ep, ia);
622-
623578
rc = -EHOSTUNREACH;
624579
id = rpcrdma_create_id(r_xprt, ia);
625580
if (IS_ERR(id))
@@ -640,15 +595,14 @@ static int rpcrdma_ep_reconnect(struct rpcrdma_xprt *r_xprt,
640595
goto out_destroy;
641596
}
642597

643-
err = rdma_create_qp(id, ia->ri_pd, qp_init_attr);
598+
err = rpcrdma_ep_create(r_xprt, id);
644599
if (err)
645600
goto out_destroy;
646601

647-
/* Atomically replace the transport's ID and QP. */
602+
/* Atomically replace the transport's ID. */
648603
rc = 0;
649604
old = ia->ri_id;
650605
ia->ri_id = id;
651-
rdma_destroy_qp(old);
652606

653607
out_destroy:
654608
rdma_destroy_id(old);
@@ -665,26 +619,25 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
665619
struct rpcrdma_xprt *r_xprt = container_of(ia, struct rpcrdma_xprt,
666620
rx_ia);
667621
struct rpc_xprt *xprt = &r_xprt->rx_xprt;
668-
struct ib_qp_init_attr qp_init_attr;
669622
int rc;
670623

671624
retry:
672-
memcpy(&qp_init_attr, &ep->rep_attr, sizeof(qp_init_attr));
673625
switch (ep->rep_connected) {
674626
case 0:
675-
rc = rdma_create_qp(ia->ri_id, ia->ri_pd, &qp_init_attr);
676-
if (rc) {
677-
rc = -ENETUNREACH;
627+
rc = -ENETUNREACH;
628+
if (rpcrdma_ep_create(r_xprt, ia->ri_id))
678629
goto out_noupdate;
679-
}
680630
break;
681631
case -ENODEV:
682-
rc = rpcrdma_ep_recreate_xprt(r_xprt, &qp_init_attr);
632+
rc = rpcrdma_ep_recreate_xprt(r_xprt);
683633
if (rc)
684634
goto out_noupdate;
685635
break;
636+
case 1:
637+
rpcrdma_ep_disconnect(ep, ia);
638+
/* fall through */
686639
default:
687-
rc = rpcrdma_ep_reconnect(r_xprt, &qp_init_attr);
640+
rc = rpcrdma_ep_reconnect(r_xprt);
688641
if (rc)
689642
goto out;
690643
}
@@ -742,21 +695,29 @@ rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
742695
{
743696
struct rpcrdma_xprt *r_xprt = container_of(ep, struct rpcrdma_xprt,
744697
rx_ep);
698+
struct rdma_cm_id *id = ia->ri_id;
745699
int rc;
746700

701+
if (!id)
702+
goto out;
703+
747704
/* returns without wait if ID is not connected */
748-
rc = rdma_disconnect(ia->ri_id);
705+
rc = rdma_disconnect(id);
749706
if (!rc)
750707
wait_event_interruptible(ep->rep_connect_wait,
751708
ep->rep_connected != 1);
752709
else
753710
ep->rep_connected = rc;
754711
trace_xprtrdma_disconnect(r_xprt, rc);
755712

756-
rpcrdma_xprt_drain(r_xprt);
713+
if (id->qp)
714+
rpcrdma_xprt_drain(r_xprt);
715+
out:
757716
rpcrdma_reqs_reset(r_xprt);
758717
rpcrdma_mrs_destroy(r_xprt);
759718
rpcrdma_sendctxs_destroy(r_xprt);
719+
720+
rpcrdma_ep_destroy(r_xprt);
760721
}
761722

762723
/* Fixed-size circular FIFO queue. This implementation is wait-free and

net/sunrpc/xprtrdma/xprt_rdma.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,6 @@ void rpcrdma_ia_close(struct rpcrdma_ia *);
464464
/*
465465
* Endpoint calls - xprtrdma/verbs.c
466466
*/
467-
int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt);
468-
void rpcrdma_ep_destroy(struct rpcrdma_xprt *r_xprt);
469467
int rpcrdma_ep_connect(struct rpcrdma_ep *, struct rpcrdma_ia *);
470468
void rpcrdma_ep_disconnect(struct rpcrdma_ep *, struct rpcrdma_ia *);
471469

0 commit comments

Comments
 (0)