From 0ddfd33bdaa435fd38df5b91a923d365e9eb4ca4 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 27 Sep 2011 18:29:20 +0000 Subject: [PATCH] ib_srpt: Avoid that the cleanup code invoked after rejecting a new initiator connection triggers a race condition (Merge r3877 from trunk). git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.1.0.x@3881 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- srpt/src/ib_srpt.c | 53 ++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 98cf65bf5..22520d1b8 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -2136,21 +2136,6 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) if (ret) goto err_destroy_qp; - if (thread == MODE_IB_COMPLETION_IN_THREAD) { - TRACE_DBG("creating IB completion thread for session %s", - ch->sess_name); - - ch->thread = kthread_run(srpt_compl_thread, ch, - "ib_srpt_compl"); - if (IS_ERR(ch->thread)) { - PRINT_ERROR("failed to create kernel thread %ld", - PTR_ERR(ch->thread)); - ch->thread = NULL; - goto err_destroy_qp; - } - } else - ib_req_notify_cq(ch->cq, IB_CQ_NEXT_COMP); - out: kfree(qp_init); return ret; @@ -2569,9 +2554,28 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, rej->reason = __constant_cpu_to_be32( SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); TRACE_DBG("%s", "Failed to create SCST session"); - goto release_channel; + goto destroy_ib; } + spin_lock_irq(&sdev->spinlock); + list_add_tail(&ch->list, &sdev->rch_list); + spin_unlock_irq(&sdev->spinlock); + + if (thread == MODE_IB_COMPLETION_IN_THREAD) { + TRACE_DBG("creating IB completion thread for session %s", + ch->sess_name); + + ch->thread = kthread_run(srpt_compl_thread, ch, + "ib_srpt_compl"); + if (IS_ERR(ch->thread)) { + PRINT_ERROR("failed to create kernel thread %ld", + PTR_ERR(ch->thread)); + ch->thread = NULL; + goto unreg_sess; + } + } else + ib_req_notify_cq(ch->cq, IB_CQ_NEXT_COMP); + TRACE_DBG("Establish connection sess=%p name=%s cm_id=%p", ch->scst_sess, ch->sess_name, ch->cm_id); @@ -2605,14 +2609,21 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, goto release_channel; } - spin_lock_irq(&sdev->spinlock); - list_add_tail(&ch->list, &sdev->rch_list); - spin_unlock_irq(&sdev->spinlock); - goto out; release_channel: - atomic_set(&ch->state, CH_DISCONNECTING); + srpt_close_ch(ch); + /* + * Tell the caller not to free cm_id since srpt_free_ch() will do that. + */ + ret = 0; + goto out; + +unreg_sess: + spin_lock_irq(&sdev->spinlock); + list_del(&ch->list); + spin_unlock_irq(&sdev->spinlock); + scst_unregister_session(ch->scst_sess, false, NULL); ch->scst_sess = NULL;