aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTom Talpey <talpey@netapp.com>2008-10-09 15:01:00 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-10-10 15:11:40 -0400
commitfee08caf943e8ed3446ce42fa085b5e7e5f08d92 (patch)
tree21419677bd5210c7a9068b698c23e52cd385f530 /net
parentad0e9e01da4ece70ff524b49c77c5e850d5dd53e (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')
-rw-r--r--net/sunrpc/xprtrdma/verbs.c20
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;
566out2: 566out2:
567 rdma_destroy_id(ia->ri_id); 567 rdma_destroy_id(ia->ri_id);
568 ia->ri_id = NULL;
568out1: 569out1:
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)