From 097f5151cb9b9b250f6bb44f7b9b0129d177e9c4 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 16 Aug 2009 13:27:01 +0000 Subject: [PATCH] Refinements for SRPT command processing state management. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1059 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- srpt/src/ib_srpt.c | 61 ++++++++++++++++++++++++++++++---------------- srpt/src/ib_srpt.h | 15 ++++++++---- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 0b8d1d3f3..de7b1b18e 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -226,7 +226,8 @@ static void srpt_qp_event(struct ib_event *event, void *ctx) case IB_EVENT_QP_LAST_WQE_REACHED: if (srpt_test_and_set_channel_state(ch, RDMA_CHANNEL_LIVE, RDMA_CHANNEL_DISCONNECTING)) { - TRACE_DBG("%s", "Disconnecting channel."); + printk(KERN_INFO PFX "disconnected session %s.\n", + ch->sess_name); ib_send_cm_dreq(ch->cm_id, NULL, 0); } break; @@ -881,6 +882,7 @@ static void srpt_abort_scst_cmd(struct srpt_device *sdev, { struct srpt_ioctx *ioctx; scst_data_direction dir; + enum srpt_command_state orig_ioctx_state; ioctx = scst_cmd_get_tgt_priv(scmnd); BUG_ON(!ioctx); @@ -891,7 +893,7 @@ static void srpt_abort_scst_cmd(struct srpt_device *sdev, scst_cmd_get_sg_cnt(scmnd), scst_to_tgt_dma_dir(dir)); -#if 1 +#ifdef CONFIG_SCST_EXTRACHECKS switch (scmnd->state) { case SCST_CMD_STATE_DATA_WAIT: WARN_ON(ioctx->state != SRPT_STATE_NEED_DATA); @@ -905,7 +907,12 @@ static void srpt_abort_scst_cmd(struct srpt_device *sdev, } #endif - if (ioctx->state == SRPT_STATE_NEED_DATA) { + orig_ioctx_state = ioctx->state; + ioctx->state = SRPT_STATE_ABORTED; + + if (orig_ioctx_state == SRPT_STATE_NEED_DATA) { + WARN_ON(scst_cmd_get_data_direction(ioctx->scmnd) + == SCST_DATA_READ); scst_rx_data(scmnd, tell_initiator ? SCST_RX_STATUS_ERROR : SCST_RX_STATUS_ERROR_FATAL, @@ -913,12 +920,8 @@ static void srpt_abort_scst_cmd(struct srpt_device *sdev, goto out; } else if (ioctx->state == SRPT_STATE_PROCESSED) ; - else { - printk(KERN_ERR PFX - "unexpected cmd state %d (SCST) %d (SRPT)\n", - scmnd->state, ioctx->state); + else WARN_ON("unexpected cmd state"); - } } scst_set_delivery_status(scmnd, SCST_CMD_DELIVERY_FAILED); @@ -964,17 +967,28 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, srpt_reset_ioctx(ch, ioctx); } +/** Process an RDMA completion notification. */ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx) { if (!ioctx->scmnd) { + WARN_ON("ERROR: ioctx->scmnd == NULL"); srpt_reset_ioctx(ch, ioctx); return; } - if (scst_cmd_get_data_direction(ioctx->scmnd) == SCST_DATA_WRITE) + /* + * If an RDMA completion notification has been received for a write + * command, tell SCST that processing can continue by calling + * scst_rx_data(). + */ + if (ioctx->state == SRPT_STATE_NEED_DATA) { + WARN_ON(scst_cmd_get_data_direction(ioctx->scmnd) + == SCST_DATA_READ); + ioctx->state = SRPT_STATE_DATA_IN; scst_rx_data(ioctx->scmnd, SCST_RX_STATUS_SUCCESS, - scst_estimate_context()); + scst_estimate_context()); + } } /** @@ -1077,7 +1091,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx) struct scst_cmd *scmnd; struct srp_cmd *srp_cmd; struct srp_rsp *srp_rsp; - scst_data_direction dir = SCST_DATA_NONE; + scst_data_direction dir; int indirect_desc = 0; int ret; unsigned long flags; @@ -1085,6 +1099,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx) srp_cmd = ioctx->buf; srp_rsp = ioctx->buf; + dir = SCST_DATA_NONE; if (srp_cmd->buf_fmt) { ret = srpt_get_desc_tbl(ioctx, srp_cmd, &indirect_desc); if (ret) { @@ -1101,14 +1116,18 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx) goto err; } + /* + * The lower four bits of the buffer format field contain the + * DATA-IN buffer descriptor format, and the highest four bits + * contain the DATA-OUT buffer descriptor format. + */ if (srp_cmd->buf_fmt & 0xf) + /* DATA-IN: transfer data from target to initiator. */ dir = SCST_DATA_READ; else if (srp_cmd->buf_fmt >> 4) + /* DATA-OUT: transfer data from initiator to target. */ dir = SCST_DATA_WRITE; - else - dir = SCST_DATA_NONE; - } else - dir = SCST_DATA_NONE; + } scmnd = scst_rx_cmd(ch->scst_sess, (u8 *) &srp_cmd->lun, sizeof srp_cmd->lun, srp_cmd->cdb, 16, @@ -2223,7 +2242,7 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx, } /* - * Start data reception. Must not block. + * Start data transfer between initiator and target. Must not block. */ static int srpt_xfer_data(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx, struct scst_cmd *scmnd) @@ -2254,8 +2273,8 @@ out: } /* - * Called by the SCST core to inform ib_srpt that data reception should start. - * Must not block. + * Called by the SCST core to inform ib_srpt that data reception from the + * initiator should start (SCST_DATA_WRITE). Must not block. */ static int srpt_rdy_to_xfer(struct scst_cmd *scmnd) { @@ -2300,6 +2319,8 @@ static int srpt_xmit_response(struct scst_cmd *scmnd) tag = scst_cmd_get_tag(scmnd); + ioctx->state = SRPT_STATE_PROCESSED; + if (ch->state != RDMA_CHANNEL_LIVE) { printk(KERN_ERR PFX "%s: tag= %lld channel in bad state %d\n", @@ -2352,7 +2373,7 @@ static int srpt_xmit_response(struct scst_cmd *scmnd) srp_rsp->status = status; - /* transfer read data if any */ + /* For read commands, transfer the data to the initiator. */ if (dir == SCST_DATA_READ && scst_cmd_get_resp_data_len(scmnd)) { ret = srpt_xfer_data(ch, ioctx, scmnd); if (ret != SCST_TGT_RES_SUCCESS) { @@ -2363,8 +2384,6 @@ static int srpt_xmit_response(struct scst_cmd *scmnd) } } - ioctx->state = SRPT_STATE_PROCESSED; - if (srpt_post_send(ch, ioctx, sizeof *srp_rsp + be32_to_cpu(srp_rsp->sense_data_len))) { diff --git a/srpt/src/ib_srpt.h b/srpt/src/ib_srpt.h index ae349cf19..cdc4ce013 100644 --- a/srpt/src/ib_srpt.h +++ b/srpt/src/ib_srpt.h @@ -108,11 +108,16 @@ struct rdma_iu { /* Command states. */ enum srpt_command_state { - SRPT_STATE_NEW = 0, /* New command being processed. */ - SRPT_STATE_PROCESSED = 1, /* Processing finished. */ - SRPT_STATE_NEED_DATA = 2, /* Data needed to continue. */ - SRPT_STATE_DATA_IN = 3, /* Data arrived and being processed. */ - SRPT_STATE_ABORTED = 4, /* Command aborted. */ + /* New command arrived and is being processed. */ + SRPT_STATE_NEW = 0, + /* Processing a write or bidir command and waiting for data arrival. */ + SRPT_STATE_NEED_DATA = 1, + /* Data for the write or bidir command arrived and is being processed.*/ + SRPT_STATE_DATA_IN = 2, + /* Command processing finished. */ + SRPT_STATE_PROCESSED = 3, + /* Command processing has been aborted. */ + SRPT_STATE_ABORTED = 4, }; /* SRPT I/O context: SRPT-private data associated with a struct scst_cmd. */