diff options
author | Tom Talpey <talpey@netapp.com> | 2008-10-09 15:01:00 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-10-10 15:11:40 -0400 |
commit | fee08caf943e8ed3446ce42fa085b5e7e5f08d92 (patch) | |
tree | 21419677bd5210c7a9068b698c23e52cd385f530 /net/sunrpc | |
parent | ad0e9e01da4ece70ff524b49c77c5e850d5dd53e (diff) |
RPC/RDMA: avoid an oops due to disconnect racing with async upcalls.
RDMA disconnects yield an upcall from the RDMA connection manager,
which can race with rpc transport close, e.g. on ^C of a mount.
Ensure any rdma cm_id and qp are fully destroyed before continuing.
Signed-off-by: Tom Talpey <talpey@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index e3fe9054fef6..d94f379f36d7 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -565,6 +565,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) | |||
565 | return 0; | 565 | return 0; |
566 | out2: | 566 | out2: |
567 | rdma_destroy_id(ia->ri_id); | 567 | rdma_destroy_id(ia->ri_id); |
568 | ia->ri_id = NULL; | ||
568 | out1: | 569 | out1: |
569 | return rc; | 570 | return rc; |
570 | } | 571 | } |
@@ -585,15 +586,17 @@ rpcrdma_ia_close(struct rpcrdma_ia *ia) | |||
585 | dprintk("RPC: %s: ib_dereg_mr returned %i\n", | 586 | dprintk("RPC: %s: ib_dereg_mr returned %i\n", |
586 | __func__, rc); | 587 | __func__, rc); |
587 | } | 588 | } |
588 | if (ia->ri_id != NULL && !IS_ERR(ia->ri_id) && ia->ri_id->qp) | 589 | if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) { |
589 | rdma_destroy_qp(ia->ri_id); | 590 | if (ia->ri_id->qp) |
591 | rdma_destroy_qp(ia->ri_id); | ||
592 | rdma_destroy_id(ia->ri_id); | ||
593 | ia->ri_id = NULL; | ||
594 | } | ||
590 | if (ia->ri_pd != NULL && !IS_ERR(ia->ri_pd)) { | 595 | if (ia->ri_pd != NULL && !IS_ERR(ia->ri_pd)) { |
591 | rc = ib_dealloc_pd(ia->ri_pd); | 596 | rc = ib_dealloc_pd(ia->ri_pd); |
592 | dprintk("RPC: %s: ib_dealloc_pd returned %i\n", | 597 | dprintk("RPC: %s: ib_dealloc_pd returned %i\n", |
593 | __func__, rc); | 598 | __func__, rc); |
594 | } | 599 | } |
595 | if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) | ||
596 | rdma_destroy_id(ia->ri_id); | ||
597 | } | 600 | } |
598 | 601 | ||
599 | /* | 602 | /* |
@@ -751,21 +754,16 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | |||
751 | if (rc) | 754 | if (rc) |
752 | dprintk("RPC: %s: rpcrdma_ep_disconnect" | 755 | dprintk("RPC: %s: rpcrdma_ep_disconnect" |
753 | " returned %i\n", __func__, rc); | 756 | " returned %i\n", __func__, rc); |
757 | rdma_destroy_qp(ia->ri_id); | ||
758 | ia->ri_id->qp = NULL; | ||
754 | } | 759 | } |
755 | 760 | ||
756 | ep->rep_func = NULL; | ||
757 | |||
758 | /* padding - could be done in rpcrdma_buffer_destroy... */ | 761 | /* padding - could be done in rpcrdma_buffer_destroy... */ |
759 | if (ep->rep_pad_mr) { | 762 | if (ep->rep_pad_mr) { |
760 | rpcrdma_deregister_internal(ia, ep->rep_pad_mr, &ep->rep_pad); | 763 | rpcrdma_deregister_internal(ia, ep->rep_pad_mr, &ep->rep_pad); |
761 | ep->rep_pad_mr = NULL; | 764 | ep->rep_pad_mr = NULL; |
762 | } | 765 | } |
763 | 766 | ||
764 | if (ia->ri_id->qp) { | ||
765 | rdma_destroy_qp(ia->ri_id); | ||
766 | ia->ri_id->qp = NULL; | ||
767 | } | ||
768 | |||
769 | rpcrdma_clean_cq(ep->rep_cq); | 767 | rpcrdma_clean_cq(ep->rep_cq); |
770 | rc = ib_destroy_cq(ep->rep_cq); | 768 | rc = ib_destroy_cq(ep->rep_cq); |
771 | if (rc) | 769 | if (rc) |