Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19e2090f authored by Sagi Grimberg's avatar Sagi Grimberg Committed by Nicholas Bellinger
Browse files

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: default avatarSagi Grimberg <sagig@mellanox.com>
Cc: <stable@vger.kernel.org> # v3.10+
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 2371e5da
Loading
Loading
Loading
Loading
+19 −12
Original line number Diff line number Diff line
@@ -141,12 +141,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);
	if (ret) {
		pr_err("rdma_create_qp failed for cma_id %d\n", ret);
		return ret;
		goto err;
	}
	isert_conn->conn_qp = cma_id->qp;
	pr_debug("rdma_create_qp() returned success >>>>>>>>>>>>>>>>>>>>>>>>>.\n");

	return 0;
err:
	mutex_lock(&device_list_mutex);
	device->cq_active_qps[min_index]--;
	mutex_unlock(&device_list_mutex);

	return ret;
}

static void
@@ -602,7 +608,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
	spin_lock_init(&isert_conn->conn_lock);
	INIT_LIST_HEAD(&isert_conn->conn_fr_pool);

	cma_id->context = isert_conn;
	isert_conn->conn_cm_id = cma_id;

	isert_conn->login_buf = kzalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
@@ -734,18 +739,20 @@ isert_connect_release(struct isert_conn *isert_conn)
	if (device && device->use_fastreg)
		isert_conn_free_fastreg_pool(isert_conn);

	isert_free_rx_descriptors(isert_conn);
	rdma_destroy_id(isert_conn->conn_cm_id);

	if (isert_conn->conn_qp) {
		cq_index = ((struct isert_cq_desc *)
			isert_conn->conn_qp->recv_cq->cq_context)->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]--;
		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);

	ib_dereg_mr(isert_conn->conn_mr);
	ib_dealloc_pd(isert_conn->conn_pd);

@@ -768,7 +775,7 @@ isert_connect_release(struct isert_conn *isert_conn)
static void
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);

@@ -846,16 +853,16 @@ isert_conn_terminate(struct isert_conn *isert_conn)
static int
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;

	if (!cma_id->qp) {
		struct isert_np *isert_np = cma_id->context;

	if (isert_np->np_cm_id == cma_id) {
		isert_np->np_cm_id = NULL;
		return -1;
	}

	isert_conn = (struct isert_conn *)cma_id->context;
	isert_conn = cma_id->qp->qp_context;

	mutex_lock(&isert_conn->conn_mutex);
	isert_conn_terminate(isert_conn);
@@ -870,7 +877,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id)
static void
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);
}