From 175463ca84e66b3b4e641fbf803512609f0848ef Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 27 Aug 2015 17:53:32 +0000 Subject: [PATCH] isert-scst: Fix race condition between login request and scst teardown flow On scst teardown we call rdma_disconnect() on all connections. this moves the qps to error state and flushes all the wc, including the drain wc which will results in kref_put of the connection. In a race condition with the connection request, we might be only in the init stage of the ref, and calling kref_put will result in refcount 0 and freeing the connection while establishing it. Call the first kref_get before rdma_accept() to prevent this race. Signed-off-by: Ariel Nahum Signed-off-by: Yan Burman git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6486 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/isert-scst/iser_rdma.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/iscsi-scst/kernel/isert-scst/iser_rdma.c b/iscsi-scst/kernel/isert-scst/iser_rdma.c index 2bfc53cd4..d5fc4a7d3 100644 --- a/iscsi-scst/kernel/isert-scst/iser_rdma.c +++ b/iscsi-scst/kernel/isert-scst/iser_rdma.c @@ -1345,6 +1345,8 @@ static int isert_cm_conn_req_handler(struct rdma_cm_id *cm_id, tgt_conn_param.private_data = &cm_hdr; cm_hdr.flags = ISER_ZBVA_NOT_SUPPORTED | ISER_SEND_W_INV_NOT_SUPPORTED; + kref_get(&isert_conn->kref); + err = rdma_accept(cm_id, &tgt_conn_param); if (unlikely(err)) { pr_err("Failed to accept conn request, err:%d\n", err); @@ -1422,7 +1424,6 @@ static int isert_cm_connect_handler(struct rdma_cm_id *cm_id, if (unlikely(ret)) goto out; - kref_get(&isert_conn->kref); kref_get(&isert_conn->kref); /* notify upper layer */ ret = isert_conn_established(&isert_conn->iscsi, @@ -1592,6 +1593,12 @@ static int isert_cm_evt_handler(struct rdma_cm_id *cm_id, isert_conn = cm_id->qp->qp_context; set_bit(ISERT_CONNECTION_ABORTED, &isert_conn->flags); + /* + * reaching here must be with the isert_conn refcount of 2, + * one from the init and one from the connect request, + * thus it is safe to deref directly before the sched_conn_closed + */ + isert_conn_free(isert_conn); isert_sched_conn_closed(isert_conn); err = 0; }