aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2014-12-02 09:57:26 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-12-13 02:17:28 -0500
commit19e2090fb246ca21b3e569ead51a6a7a1748eadd (patch)
tree96acf88598b75b91c467e084f2fd7cdece8c274b /drivers/infiniband
parent2371e5da8cfe91443339b54444dec6254fdd6dfc (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/infiniband')
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c31
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;
150err:
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
152static void 158static 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)
768static void 775static void
769isert_connected_handler(struct rdma_cm_id *cma_id) 776isert_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)
846static int 853static int
847isert_disconnected_handler(struct rdma_cm_id *cma_id) 854isert_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)
870static void 877static void
871isert_connect_error(struct rdma_cm_id *cma_id) 878isert_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}