From 58eb630bd09596274ba826dc8f068924cdfc2b99 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 31 Jul 2009 11:40:10 +0000 Subject: [PATCH] Fixed the issue that 'rmmod ib_srpt' with ongoing SRP I/O could trigger a deadlock. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@998 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- srpt/src/ib_srpt.c | 66 ++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 0b51eef72..e5305a42b 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -804,11 +804,36 @@ static void srpt_reset_ioctx(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx) atomic_inc(&ch->req_lim_delta); } +static void srpt_abort_scst_cmd(struct srpt_device *sdev, + struct scst_cmd *scmnd, + bool tell_initiator) +{ + scst_data_direction dir; + + dir = scst_cmd_get_data_direction(scmnd); + if (dir != SCST_DATA_NONE) { + dma_unmap_sg(sdev->device->dma_device, + scst_cmd_get_sg(scmnd), + scst_cmd_get_sg_cnt(scmnd), + scst_to_tgt_dma_dir(dir)); + + if (scmnd->state == SCST_CMD_STATE_DATA_WAIT) + scst_rx_data(scmnd, + tell_initiator ? SCST_RX_STATUS_ERROR + : SCST_RX_STATUS_ERROR_FATAL, + SCST_CONTEXT_THREAD); + else if (scmnd->state == SCST_CMD_STATE_XMIT_WAIT) + ; + } + + scst_set_delivery_status(scmnd, SCST_CMD_DELIVERY_FAILED); + scst_tgt_cmd_done(scmnd, scst_estimate_context()); +} + static void srpt_handle_err_comp(struct srpt_rdma_ch *ch, struct ib_wc *wc) { struct srpt_ioctx *ioctx; struct srpt_device *sdev = ch->sport->sdev; - scst_data_direction dir = SCST_DATA_NONE; if (wc->wr_id & SRPT_OP_RECV) { ioctx = sdev->ioctx_ring[wc->wr_id & ~SRPT_OP_RECV]; @@ -816,29 +841,9 @@ static void srpt_handle_err_comp(struct srpt_rdma_ch *ch, struct ib_wc *wc) } else { ioctx = sdev->ioctx_ring[wc->wr_id]; - if (ioctx->scmnd) { - struct scst_cmd *scmnd = ioctx->scmnd; - - dir = scst_cmd_get_data_direction(scmnd); - - if (dir == SCST_DATA_NONE) - scst_tgt_cmd_done(scmnd, - scst_estimate_context()); - else { - dma_unmap_sg(sdev->device->dma_device, - scst_cmd_get_sg(scmnd), - scst_cmd_get_sg_cnt(scmnd), - scst_to_tgt_dma_dir(dir)); - - if (scmnd->state == SCST_CMD_STATE_DATA_WAIT) - scst_rx_data(scmnd, - SCST_RX_STATUS_ERROR, - SCST_CONTEXT_THREAD); - else if (scmnd->state == SCST_CMD_STATE_XMIT_WAIT) - scst_tgt_cmd_done(scmnd, - scst_estimate_context()); - } - } else + if (ioctx->scmnd) + srpt_abort_scst_cmd(sdev, ioctx->scmnd, true); + else srpt_reset_ioctx(ch, ioctx); } } @@ -1347,6 +1352,7 @@ static struct srpt_rdma_ch *srpt_find_channel(struct ib_cm_id *cm_id) return NULL; } +/** Release all resources associated with the specified RDMA channel. */ static int srpt_release_channel(struct srpt_rdma_ch *ch, int destroy_cmid) { TRACE_ENTRY(); @@ -1373,11 +1379,19 @@ static int srpt_release_channel(struct srpt_rdma_ch *ch, int destroy_cmid) __func__, ch->scst_sess, ch->sess_name, ch->active_scmnd_cnt); + spin_lock_irq(&ch->spinlock); list_for_each_entry_safe(ioctx, ioctx_tmp, &ch->active_scmnd_list, scmnd_list) { - list_del(&ioctx->scmnd_list); - ch->active_scmnd_cnt--; + spin_unlock_irq(&ch->spinlock); + + if (ioctx->scmnd) + srpt_abort_scst_cmd(ch->sport->sdev, + ioctx->scmnd, true); + + spin_lock_irq(&ch->spinlock); } + WARN_ON(ch->active_scmnd_cnt != 0); + spin_unlock_irq(&ch->spinlock); scst_unregister_session(ch->scst_sess, 0, NULL); ch->scst_sess = NULL;