Convert the I/O context state from an atomic variable into a regular variable protected by a spinlock. Modify srpt_test_and_set_cmd_state() such that it returns a boolean instead of a state.
Signed-off-by: Bart Van Assche <[email protected]> --- drivers/scst/srpt/ib_srpt.c | 96 +++++++++++++++++++++++++++--------------- drivers/scst/srpt/ib_srpt.h | 3 +- 2 files changed, 64 insertions(+), 35 deletions(-) diff --git a/drivers/scst/srpt/ib_srpt.c b/drivers/scst/srpt/ib_srpt.c index 4c9c700..5dc072e 100644 --- a/drivers/scst/srpt/ib_srpt.c +++ b/drivers/scst/srpt/ib_srpt.c @@ -722,9 +722,15 @@ static void srpt_free_ioctx_ring(struct srpt_ioctx **ioctx_ring, */ static enum srpt_command_state srpt_get_cmd_state(struct srpt_send_ioctx *ioctx) { + enum srpt_command_state state; + unsigned long flags; + BUG_ON(!ioctx); - return atomic_read(&ioctx->state); + spin_lock_irqsave(&ioctx->spinlock, flags); + state = ioctx->state; + spin_unlock_irqrestore(&ioctx->spinlock, flags); + return state; } /** @@ -738,13 +744,15 @@ static enum srpt_command_state srpt_set_cmd_state(struct srpt_send_ioctx *ioctx, enum srpt_command_state new) { enum srpt_command_state previous; + unsigned long flags; BUG_ON(!ioctx); - do { - previous = atomic_read(&ioctx->state); - } while (previous != SRPT_STATE_DONE - && atomic_cmpxchg(&ioctx->state, previous, new) != previous); + spin_lock_irqsave(&ioctx->spinlock, flags); + previous = ioctx->state; + if (previous != SRPT_STATE_DONE) + ioctx->state = new; + spin_unlock_irqrestore(&ioctx->spinlock, flags); return previous; } @@ -754,18 +762,25 @@ static enum srpt_command_state srpt_set_cmd_state(struct srpt_send_ioctx *ioctx, * @old: State to compare against. * @new: New state to be set if the current state matches 'old'. * - * Returns the previous command state. + * Returns true if and only if the previous command state was equal to 'old'. */ -static enum srpt_command_state -srpt_test_and_set_cmd_state(struct srpt_send_ioctx *ioctx, - enum srpt_command_state old, - enum srpt_command_state new) +static bool srpt_test_and_set_cmd_state(struct srpt_send_ioctx *ioctx, + enum srpt_command_state old, + enum srpt_command_state new) { + enum srpt_command_state previous; + unsigned long flags; + WARN_ON(!ioctx); WARN_ON(old == SRPT_STATE_DONE); WARN_ON(new == SRPT_STATE_NEW); - return atomic_cmpxchg(&ioctx->state, old, new); + spin_lock_irqsave(&ioctx->spinlock, flags); + previous = ioctx->state; + if (previous == old) + ioctx->state = new; + spin_unlock_irqrestore(&ioctx->spinlock, flags); + return previous == old; } /** @@ -1052,7 +1067,8 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) return ioctx; BUG_ON(ioctx->ch != ch); - atomic_set(&ioctx->state, SRPT_STATE_NEW); + spin_lock_init(&ioctx->spinlock); + ioctx->state = SRPT_STATE_NEW; ioctx->n_rbuf = 0; ioctx->rbufs = NULL; ioctx->n_rdma = 0; @@ -1108,6 +1124,7 @@ static void srpt_abort_scst_cmd(struct srpt_send_ioctx *ioctx, { struct scst_cmd *scmnd; enum srpt_command_state state; + unsigned long flags; BUG_ON(!ioctx); @@ -1118,16 +1135,22 @@ static void srpt_abort_scst_cmd(struct srpt_send_ioctx *ioctx, * ensures that srpt_xmit_response() will call this function a second * time. */ - state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA, - SRPT_STATE_DATA_IN); - if (state != SRPT_STATE_NEED_DATA) { - state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_DATA_IN, - SRPT_STATE_DONE); - if (state != SRPT_STATE_DATA_IN) { - state = srpt_test_and_set_cmd_state(ioctx, - SRPT_STATE_CMD_RSP_SENT, SRPT_STATE_DONE); - } + + spin_lock_irqsave(&ioctx->spinlock, flags); + state = ioctx->state; + switch (state) { + case SRPT_STATE_NEED_DATA: + ioctx->state = SRPT_STATE_DATA_IN; + break; + case SRPT_STATE_DATA_IN: + case SRPT_STATE_CMD_RSP_SENT: + ioctx->state = SRPT_STATE_DONE; + break; + default: + break; } + spin_unlock_irqrestore(&ioctx->spinlock, flags); + if (state == SRPT_STATE_DONE) goto out; @@ -1263,7 +1286,6 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch, struct srpt_send_ioctx *ioctx, enum scst_exec_context context) { - enum srpt_command_state state; struct scst_cmd *scmnd; EXTRACHECKS_WARN_ON(ioctx->n_rdma <= 0); @@ -1271,14 +1293,13 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch, scmnd = ioctx->scmnd; if (scmnd) { - state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA, - SRPT_STATE_DATA_IN); - if (state == SRPT_STATE_NEED_DATA) + if (srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA, + SRPT_STATE_DATA_IN)) scst_rx_data(ioctx->scmnd, SCST_RX_STATUS_SUCCESS, context); else PRINT_ERROR("%s[%d]: wrong state = %d", __func__, - __LINE__, state); + __LINE__, srpt_get_cmd_state(ioctx)); } else PRINT_ERROR("%s[%d]: scmnd == NULL", __func__, __LINE__); } @@ -2986,6 +3007,7 @@ static int srpt_xmit_response(struct scst_cmd *scmnd) struct srpt_rdma_ch *ch; struct srpt_send_ioctx *ioctx; enum srpt_command_state state; + unsigned long flags; int ret; scst_data_direction dir; int resp_len; @@ -2998,15 +3020,21 @@ static int srpt_xmit_response(struct scst_cmd *scmnd) ch = scst_sess_get_tgt_priv(scst_cmd_get_session(scmnd)); BUG_ON(!ch); - state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEW, - SRPT_STATE_CMD_RSP_SENT); - if (state != SRPT_STATE_NEW) { - state = srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_DATA_IN, - SRPT_STATE_CMD_RSP_SENT); - if (state != SRPT_STATE_DATA_IN) - PRINT_ERROR("Unexpected command state %d", - srpt_get_cmd_state(ioctx)); + spin_lock_irqsave(&ioctx->spinlock, flags); + state = ioctx->state; + switch (state) { + case SRPT_STATE_NEW: + ioctx->state = SRPT_STATE_CMD_RSP_SENT; + case SRPT_STATE_DATA_IN: + ioctx->state = SRPT_STATE_CMD_RSP_SENT; + break; + default: + PRINT_ERROR("Unexpected command state %d", + srpt_get_cmd_state(ioctx)); + break; } + spin_unlock_irqrestore(&ioctx->spinlock, flags); + if (unlikely(scst_cmd_aborted(scmnd))) { atomic_inc(&ch->req_lim_delta); diff --git a/drivers/scst/srpt/ib_srpt.h b/drivers/scst/srpt/ib_srpt.h index 3e893d9..b8f14d4 100644 --- a/drivers/scst/srpt/ib_srpt.h +++ b/drivers/scst/srpt/ib_srpt.h @@ -209,7 +209,8 @@ struct srpt_send_ioctx { struct scst_cmd *scmnd; scst_data_direction dir; - atomic_t state; + spinlock_t spinlock; + enum srpt_command_state state; }; /** -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
