diff options
author | Sagi Grimberg <sagig@mellanox.com> | 2014-12-02 09:57:26 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-12-13 02:17:28 -0500 |
commit | 19e2090fb246ca21b3e569ead51a6a7a1748eadd (patch) | |
tree | 96acf88598b75b91c467e084f2fd7cdece8c274b /drivers | |
parent | 2371e5da8cfe91443339b54444dec6254fdd6dfc (diff) |
iser-target: Fix connected_handler + teardown flow race
Take isert_conn pointer from cm_id->qp->qp_context. This
will allow us to know that the cm_id context is always
the network portal. This will make the cm_id event check
(connection or network portal) more reliable.
In order to avoid a NULL dereference in cma_id->qp->qp_context
we destroy the qp after we destroy the cm_id (and make the
dereference safe). session stablishment/teardown sequences
can happen in parallel, we should take into account that
connected_handler might race with connection teardown flow.
Also, protect isert_conn->conn_device->active_qps decrement
within the error patch during QP creation failure and the
normal teardown path in isert_connect_release().
Squashed:
iser-target: Decrement completion context active_qps in error flow
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Cc: <stable@vger.kernel.org> # v3.10+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/ulp/isert/ib_isert.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index a0fd77bf8f88..054fa425d09e 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c | |||
@@ -141,12 +141,18 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id, | |||
141 | ret = rdma_create_qp(cma_id, isert_conn->conn_pd, &attr); | 141 | ret = rdma_create_qp(cma_id, isert_conn->conn_pd, &attr); |
142 | if (ret) { | 142 | if (ret) { |
143 | pr_err("rdma_create_qp failed for cma_id %d\n", ret); | 143 | pr_err("rdma_create_qp failed for cma_id %d\n", ret); |
144 | return ret; | 144 | goto err; |
145 | } | 145 | } |
146 | isert_conn->conn_qp = cma_id->qp; | 146 | isert_conn->conn_qp = cma_id->qp; |
147 | pr_debug("rdma_create_qp() returned success >>>>>>>>>>>>>>>>>>>>>>>>>.\n"); | 147 | pr_debug("rdma_create_qp() returned success >>>>>>>>>>>>>>>>>>>>>>>>>.\n"); |
148 | 148 | ||
149 | return 0; | 149 | return 0; |
150 | err: | ||
151 | mutex_lock(&device_list_mutex); | ||
152 | device->cq_active_qps[min_index]--; | ||
153 | mutex_unlock(&device_list_mutex); | ||
154 | |||
155 | return ret; | ||
150 | } | 156 | } |
151 | 157 | ||
152 | static void | 158 | static void |
@@ -602,7 +608,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) | |||
602 | spin_lock_init(&isert_conn->conn_lock); | 608 | spin_lock_init(&isert_conn->conn_lock); |
603 | INIT_LIST_HEAD(&isert_conn->conn_fr_pool); | 609 | INIT_LIST_HEAD(&isert_conn->conn_fr_pool); |
604 | 610 | ||
605 | cma_id->context = isert_conn; | ||
606 | isert_conn->conn_cm_id = cma_id; | 611 | isert_conn->conn_cm_id = cma_id; |
607 | 612 | ||
608 | isert_conn->login_buf = kzalloc(ISCSI_DEF_MAX_RECV_SEG_LEN + | 613 | isert_conn->login_buf = kzalloc(ISCSI_DEF_MAX_RECV_SEG_LEN + |
@@ -734,18 +739,20 @@ isert_connect_release(struct isert_conn *isert_conn) | |||
734 | if (device && device->use_fastreg) | 739 | if (device && device->use_fastreg) |
735 | isert_conn_free_fastreg_pool(isert_conn); | 740 | isert_conn_free_fastreg_pool(isert_conn); |
736 | 741 | ||
742 | isert_free_rx_descriptors(isert_conn); | ||
743 | rdma_destroy_id(isert_conn->conn_cm_id); | ||
744 | |||
737 | if (isert_conn->conn_qp) { | 745 | if (isert_conn->conn_qp) { |
738 | cq_index = ((struct isert_cq_desc *) | 746 | cq_index = ((struct isert_cq_desc *) |
739 | isert_conn->conn_qp->recv_cq->cq_context)->cq_index; | 747 | isert_conn->conn_qp->recv_cq->cq_context)->cq_index; |
740 | pr_debug("isert_connect_release: cq_index: %d\n", cq_index); | 748 | pr_debug("isert_connect_release: cq_index: %d\n", cq_index); |
749 | mutex_lock(&device_list_mutex); | ||
741 | isert_conn->conn_device->cq_active_qps[cq_index]--; | 750 | isert_conn->conn_device->cq_active_qps[cq_index]--; |
751 | mutex_unlock(&device_list_mutex); | ||
742 | 752 | ||
743 | rdma_destroy_qp(isert_conn->conn_cm_id); | 753 | ib_destroy_qp(isert_conn->conn_qp); |
744 | } | 754 | } |
745 | 755 | ||
746 | isert_free_rx_descriptors(isert_conn); | ||
747 | rdma_destroy_id(isert_conn->conn_cm_id); | ||
748 | |||
749 | ib_dereg_mr(isert_conn->conn_mr); | 756 | ib_dereg_mr(isert_conn->conn_mr); |
750 | ib_dealloc_pd(isert_conn->conn_pd); | 757 | ib_dealloc_pd(isert_conn->conn_pd); |
751 | 758 | ||
@@ -768,7 +775,7 @@ isert_connect_release(struct isert_conn *isert_conn) | |||
768 | static void | 775 | static void |
769 | isert_connected_handler(struct rdma_cm_id *cma_id) | 776 | isert_connected_handler(struct rdma_cm_id *cma_id) |
770 | { | 777 | { |
771 | struct isert_conn *isert_conn = cma_id->context; | 778 | struct isert_conn *isert_conn = cma_id->qp->qp_context; |
772 | 779 | ||
773 | pr_info("conn %p\n", isert_conn); | 780 | pr_info("conn %p\n", isert_conn); |
774 | 781 | ||
@@ -846,16 +853,16 @@ isert_conn_terminate(struct isert_conn *isert_conn) | |||
846 | static int | 853 | static int |
847 | isert_disconnected_handler(struct rdma_cm_id *cma_id) | 854 | isert_disconnected_handler(struct rdma_cm_id *cma_id) |
848 | { | 855 | { |
856 | struct iscsi_np *np = cma_id->context; | ||
857 | struct isert_np *isert_np = np->np_context; | ||
849 | struct isert_conn *isert_conn; | 858 | struct isert_conn *isert_conn; |
850 | 859 | ||
851 | if (!cma_id->qp) { | 860 | if (isert_np->np_cm_id == cma_id) { |
852 | struct isert_np *isert_np = cma_id->context; | ||
853 | |||
854 | isert_np->np_cm_id = NULL; | 861 | isert_np->np_cm_id = NULL; |
855 | return -1; | 862 | return -1; |
856 | } | 863 | } |
857 | 864 | ||
858 | isert_conn = (struct isert_conn *)cma_id->context; | 865 | isert_conn = cma_id->qp->qp_context; |
859 | 866 | ||
860 | mutex_lock(&isert_conn->conn_mutex); | 867 | mutex_lock(&isert_conn->conn_mutex); |
861 | isert_conn_terminate(isert_conn); | 868 | isert_conn_terminate(isert_conn); |
@@ -870,7 +877,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id) | |||
870 | static void | 877 | static void |
871 | isert_connect_error(struct rdma_cm_id *cma_id) | 878 | isert_connect_error(struct rdma_cm_id *cma_id) |
872 | { | 879 | { |
873 | struct isert_conn *isert_conn = (struct isert_conn *)cma_id->context; | 880 | struct isert_conn *isert_conn = cma_id->qp->qp_context; |
874 | 881 | ||
875 | isert_put_conn(isert_conn); | 882 | isert_put_conn(isert_conn); |
876 | } | 883 | } |