diff options
author | Tom Tucker <tom@opengridcomputing.com> | 2008-05-01 12:13:50 -0400 |
---|---|---|
committer | Tom Tucker <tom@opengridcomputing.com> | 2008-05-19 08:33:56 -0400 |
commit | 1711386c62c97f7fb086a2247d44cdb1f8867640 (patch) | |
tree | 4f4f70ada8683fe1e8884493469355acd2633790 /net/sunrpc/xprtrdma | |
parent | 0905c0f0a2346516ecd12f0a4f33dca571b0dccd (diff) |
svcrdma: Move the QP and cm_id destruction to svc_rdma_free
Move the destruction of the QP and CM_ID to the free path so that the
QP cleanup code doesn't race with the dto_tasklet handling flushed WR.
The QP reference is not needed because we now have a reference for
every WR.
Also add a guard in the SQ and RQ completion handlers to ignore
calls generated by some providers when the QP is destroyed.
Signed-off-by: Tom Tucker <tom@opengridcomputing.com>
Diffstat (limited to 'net/sunrpc/xprtrdma')
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_transport.c | 40 |
1 files changed, 20 insertions, 20 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 31b1927b5ee6..b412a49c46fc 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -252,11 +252,15 @@ static void rq_comp_handler(struct ib_cq *cq, void *cq_context) | |||
252 | struct svcxprt_rdma *xprt = cq_context; | 252 | struct svcxprt_rdma *xprt = cq_context; |
253 | unsigned long flags; | 253 | unsigned long flags; |
254 | 254 | ||
255 | /* Guard against unconditional flush call for destroyed QP */ | ||
256 | if (atomic_read(&xprt->sc_xprt.xpt_ref.refcount)==0) | ||
257 | return; | ||
258 | |||
255 | /* | 259 | /* |
256 | * Set the bit regardless of whether or not it's on the list | 260 | * Set the bit regardless of whether or not it's on the list |
257 | * because it may be on the list already due to an SQ | 261 | * because it may be on the list already due to an SQ |
258 | * completion. | 262 | * completion. |
259 | */ | 263 | */ |
260 | set_bit(RDMAXPRT_RQ_PENDING, &xprt->sc_flags); | 264 | set_bit(RDMAXPRT_RQ_PENDING, &xprt->sc_flags); |
261 | 265 | ||
262 | /* | 266 | /* |
@@ -393,11 +397,15 @@ static void sq_comp_handler(struct ib_cq *cq, void *cq_context) | |||
393 | struct svcxprt_rdma *xprt = cq_context; | 397 | struct svcxprt_rdma *xprt = cq_context; |
394 | unsigned long flags; | 398 | unsigned long flags; |
395 | 399 | ||
400 | /* Guard against unconditional flush call for destroyed QP */ | ||
401 | if (atomic_read(&xprt->sc_xprt.xpt_ref.refcount)==0) | ||
402 | return; | ||
403 | |||
396 | /* | 404 | /* |
397 | * Set the bit regardless of whether or not it's on the list | 405 | * Set the bit regardless of whether or not it's on the list |
398 | * because it may be on the list already due to an RQ | 406 | * because it may be on the list already due to an RQ |
399 | * completion. | 407 | * completion. |
400 | */ | 408 | */ |
401 | set_bit(RDMAXPRT_SQ_PENDING, &xprt->sc_flags); | 409 | set_bit(RDMAXPRT_SQ_PENDING, &xprt->sc_flags); |
402 | 410 | ||
403 | /* | 411 | /* |
@@ -852,7 +860,6 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
852 | newxprt->sc_sq_depth = qp_attr.cap.max_send_wr; | 860 | newxprt->sc_sq_depth = qp_attr.cap.max_send_wr; |
853 | newxprt->sc_max_requests = qp_attr.cap.max_recv_wr; | 861 | newxprt->sc_max_requests = qp_attr.cap.max_recv_wr; |
854 | } | 862 | } |
855 | svc_xprt_get(&newxprt->sc_xprt); | ||
856 | newxprt->sc_qp = newxprt->sc_cm_id->qp; | 863 | newxprt->sc_qp = newxprt->sc_cm_id->qp; |
857 | 864 | ||
858 | /* Register all of physical memory */ | 865 | /* Register all of physical memory */ |
@@ -926,10 +933,8 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
926 | dprintk("svcrdma: failure accepting new connection rc=%d.\n", ret); | 933 | dprintk("svcrdma: failure accepting new connection rc=%d.\n", ret); |
927 | /* Take a reference in case the DTO handler runs */ | 934 | /* Take a reference in case the DTO handler runs */ |
928 | svc_xprt_get(&newxprt->sc_xprt); | 935 | svc_xprt_get(&newxprt->sc_xprt); |
929 | if (newxprt->sc_qp && !IS_ERR(newxprt->sc_qp)) { | 936 | if (newxprt->sc_qp && !IS_ERR(newxprt->sc_qp)) |
930 | ib_destroy_qp(newxprt->sc_qp); | 937 | ib_destroy_qp(newxprt->sc_qp); |
931 | svc_xprt_put(&newxprt->sc_xprt); | ||
932 | } | ||
933 | rdma_destroy_id(newxprt->sc_cm_id); | 938 | rdma_destroy_id(newxprt->sc_cm_id); |
934 | /* This call to put will destroy the transport */ | 939 | /* This call to put will destroy the transport */ |
935 | svc_xprt_put(&newxprt->sc_xprt); | 940 | svc_xprt_put(&newxprt->sc_xprt); |
@@ -941,10 +946,7 @@ static void svc_rdma_release_rqst(struct svc_rqst *rqstp) | |||
941 | } | 946 | } |
942 | 947 | ||
943 | /* | 948 | /* |
944 | * When connected, an svc_xprt has at least three references: | 949 | * When connected, an svc_xprt has at least two references: |
945 | * | ||
946 | * - A reference held by the QP. We still hold that here because this | ||
947 | * code deletes the QP and puts the reference. | ||
948 | * | 950 | * |
949 | * - A reference held by the cm_id between the ESTABLISHED and | 951 | * - A reference held by the cm_id between the ESTABLISHED and |
950 | * DISCONNECTED events. If the remote peer disconnected first, this | 952 | * DISCONNECTED events. If the remote peer disconnected first, this |
@@ -953,7 +955,7 @@ static void svc_rdma_release_rqst(struct svc_rqst *rqstp) | |||
953 | * - A reference held by the svc_recv code that called this function | 955 | * - A reference held by the svc_recv code that called this function |
954 | * as part of close processing. | 956 | * as part of close processing. |
955 | * | 957 | * |
956 | * At a minimum two references should still be held. | 958 | * At a minimum one references should still be held. |
957 | */ | 959 | */ |
958 | static void svc_rdma_detach(struct svc_xprt *xprt) | 960 | static void svc_rdma_detach(struct svc_xprt *xprt) |
959 | { | 961 | { |
@@ -963,15 +965,6 @@ static void svc_rdma_detach(struct svc_xprt *xprt) | |||
963 | 965 | ||
964 | /* Disconnect and flush posted WQE */ | 966 | /* Disconnect and flush posted WQE */ |
965 | rdma_disconnect(rdma->sc_cm_id); | 967 | rdma_disconnect(rdma->sc_cm_id); |
966 | |||
967 | /* Destroy the QP if present (not a listener) */ | ||
968 | if (rdma->sc_qp && !IS_ERR(rdma->sc_qp)) { | ||
969 | ib_destroy_qp(rdma->sc_qp); | ||
970 | svc_xprt_put(xprt); | ||
971 | } | ||
972 | |||
973 | /* Destroy the CM ID */ | ||
974 | rdma_destroy_id(rdma->sc_cm_id); | ||
975 | } | 968 | } |
976 | 969 | ||
977 | static void __svc_rdma_free(struct work_struct *work) | 970 | static void __svc_rdma_free(struct work_struct *work) |
@@ -983,6 +976,13 @@ static void __svc_rdma_free(struct work_struct *work) | |||
983 | /* We should only be called from kref_put */ | 976 | /* We should only be called from kref_put */ |
984 | BUG_ON(atomic_read(&rdma->sc_xprt.xpt_ref.refcount) != 0); | 977 | BUG_ON(atomic_read(&rdma->sc_xprt.xpt_ref.refcount) != 0); |
985 | 978 | ||
979 | /* Destroy the QP if present (not a listener) */ | ||
980 | if (rdma->sc_qp && !IS_ERR(rdma->sc_qp)) | ||
981 | ib_destroy_qp(rdma->sc_qp); | ||
982 | |||
983 | /* Destroy the CM ID */ | ||
984 | rdma_destroy_id(rdma->sc_cm_id); | ||
985 | |||
986 | if (rdma->sc_sq_cq && !IS_ERR(rdma->sc_sq_cq)) | 986 | if (rdma->sc_sq_cq && !IS_ERR(rdma->sc_sq_cq)) |
987 | ib_destroy_cq(rdma->sc_sq_cq); | 987 | ib_destroy_cq(rdma->sc_sq_cq); |
988 | 988 | ||