Commit 057c1b28 authored by Sagi Grimberg's avatar Sagi Grimberg Committed by Jiri Slaby

iser-target: Fix connected_handler + teardown flow race

commit 19e2090f upstream.

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: default avatarSagi Grimberg <sagig@mellanox.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
parent a64969e4
...@@ -135,12 +135,18 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id) ...@@ -135,12 +135,18 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id)
ret = rdma_create_qp(cma_id, isert_conn->conn_pd, &attr); ret = rdma_create_qp(cma_id, isert_conn->conn_pd, &attr);
if (ret) { if (ret) {
pr_err("rdma_create_qp failed for cma_id %d\n", ret); pr_err("rdma_create_qp failed for cma_id %d\n", ret);
return ret; goto err;
} }
isert_conn->conn_qp = cma_id->qp; isert_conn->conn_qp = cma_id->qp;
pr_debug("rdma_create_qp() returned success >>>>>>>>>>>>>>>>>>>>>>>>>.\n"); pr_debug("rdma_create_qp() returned success >>>>>>>>>>>>>>>>>>>>>>>>>.\n");
return 0; return 0;
err:
mutex_lock(&device_list_mutex);
device->cq_active_qps[min_index]--;
mutex_unlock(&device_list_mutex);
return ret;
} }
static void static void
...@@ -531,7 +537,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -531,7 +537,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
spin_lock_init(&isert_conn->conn_lock); spin_lock_init(&isert_conn->conn_lock);
INIT_LIST_HEAD(&isert_conn->conn_frwr_pool); INIT_LIST_HEAD(&isert_conn->conn_frwr_pool);
cma_id->context = isert_conn;
isert_conn->conn_cm_id = cma_id; isert_conn->conn_cm_id = cma_id;
isert_conn->responder_resources = event->param.conn.responder_resources; isert_conn->responder_resources = event->param.conn.responder_resources;
isert_conn->initiator_depth = event->param.conn.initiator_depth; isert_conn->initiator_depth = event->param.conn.initiator_depth;
...@@ -635,18 +640,20 @@ isert_connect_release(struct isert_conn *isert_conn) ...@@ -635,18 +640,20 @@ isert_connect_release(struct isert_conn *isert_conn)
if (device && device->use_frwr) if (device && device->use_frwr)
isert_conn_free_frwr_pool(isert_conn); isert_conn_free_frwr_pool(isert_conn);
isert_free_rx_descriptors(isert_conn);
rdma_destroy_id(isert_conn->conn_cm_id);
if (isert_conn->conn_qp) { if (isert_conn->conn_qp) {
cq_index = ((struct isert_cq_desc *) cq_index = ((struct isert_cq_desc *)
isert_conn->conn_qp->recv_cq->cq_context)->cq_index; isert_conn->conn_qp->recv_cq->cq_context)->cq_index;
pr_debug("isert_connect_release: cq_index: %d\n", cq_index); pr_debug("isert_connect_release: cq_index: %d\n", cq_index);
mutex_lock(&device_list_mutex);
isert_conn->conn_device->cq_active_qps[cq_index]--; isert_conn->conn_device->cq_active_qps[cq_index]--;
mutex_unlock(&device_list_mutex);
rdma_destroy_qp(isert_conn->conn_cm_id); ib_destroy_qp(isert_conn->conn_qp);
} }
isert_free_rx_descriptors(isert_conn);
rdma_destroy_id(isert_conn->conn_cm_id);
if (isert_conn->login_buf) { if (isert_conn->login_buf) {
ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma, ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma,
ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE); ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE);
...@@ -666,7 +673,7 @@ isert_connect_release(struct isert_conn *isert_conn) ...@@ -666,7 +673,7 @@ isert_connect_release(struct isert_conn *isert_conn)
static void static void
isert_connected_handler(struct rdma_cm_id *cma_id) isert_connected_handler(struct rdma_cm_id *cma_id)
{ {
struct isert_conn *isert_conn = cma_id->context; struct isert_conn *isert_conn = cma_id->qp->qp_context;
pr_info("conn %p\n", isert_conn); pr_info("conn %p\n", isert_conn);
...@@ -744,16 +751,16 @@ isert_conn_terminate(struct isert_conn *isert_conn) ...@@ -744,16 +751,16 @@ isert_conn_terminate(struct isert_conn *isert_conn)
static int static int
isert_disconnected_handler(struct rdma_cm_id *cma_id) isert_disconnected_handler(struct rdma_cm_id *cma_id)
{ {
struct iscsi_np *np = cma_id->context;
struct isert_np *isert_np = np->np_context;
struct isert_conn *isert_conn; struct isert_conn *isert_conn;
if (!cma_id->qp) { if (isert_np->np_cm_id == cma_id) {
struct isert_np *isert_np = cma_id->context;
isert_np->np_cm_id = NULL; isert_np->np_cm_id = NULL;
return -1; return -1;
} }
isert_conn = (struct isert_conn *)cma_id->context; isert_conn = cma_id->qp->qp_context;
mutex_lock(&isert_conn->conn_mutex); mutex_lock(&isert_conn->conn_mutex);
isert_conn_terminate(isert_conn); isert_conn_terminate(isert_conn);
...@@ -768,7 +775,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id) ...@@ -768,7 +775,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id)
static void static void
isert_connect_error(struct rdma_cm_id *cma_id) isert_connect_error(struct rdma_cm_id *cma_id)
{ {
struct isert_conn *isert_conn = (struct isert_conn *)cma_id->context; struct isert_conn *isert_conn = cma_id->qp->qp_context;
isert_put_conn(isert_conn); isert_put_conn(isert_conn);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment