From ea244c7da7047998e26a06280400d40ba5bf10ad Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Wed, 4 Mar 2009 18:33:50 +0000 Subject: [PATCH] Fexes for processing internal REQUEST SENSE with scst_user handler git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@688 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 7 +++-- scst/src/scst_lib.c | 61 ++++++++++++++++++++++++++------------------ scst/src/scst_priv.h | 2 +- scst/src/scst_targ.c | 25 +++++++++++++----- 4 files changed, 61 insertions(+), 34 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 2f274ee5b..24a510ff6 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -104,10 +104,13 @@ typedef _Bool bool; /* Target driver's xmit_response() is going to be called */ #define SCST_CMD_STATE_XMIT_RESP 12 -/* The cmd finished */ +/* Cmd finished */ #define SCST_CMD_STATE_FINISHED 13 -#define SCST_CMD_STATE_LAST_ACTIVE (SCST_CMD_STATE_FINISHED+100) +/* Internal cmd finished */ +#define SCST_CMD_STATE_FINISHED_INTERNAL 14 + +#define SCST_CMD_STATE_LAST_ACTIVE (SCST_CMD_STATE_FINISHED_INTERNAL+100) /* A cmd is created, but scst_cmd_init_done() not called */ #define SCST_CMD_STATE_INIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+1) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 0d8d37979..6c56c7c98 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -280,6 +280,7 @@ void scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd) case SCST_CMD_STATE_PRE_XMIT_RESP: case SCST_CMD_STATE_XMIT_RESP: case SCST_CMD_STATE_FINISHED: + case SCST_CMD_STATE_FINISHED_INTERNAL: case SCST_CMD_STATE_XMIT_WAIT: PRINT_CRIT_ERROR("Wrong cmd state %x (cmd %p, op %x)", cmd->state, cmd, cmd->cdb[0]); @@ -1042,6 +1043,10 @@ static struct scst_cmd *scst_create_prepare_internal_cmd( res->orig_cmd = orig_cmd; res->bufflen = bufsize; + scst_sess_get(res->sess); + if (res->tgt_dev != NULL) + __scst_get(0); + res->state = SCST_CMD_STATE_PRE_PARSE; out: @@ -1049,16 +1054,6 @@ out: return res; } -static void scst_free_internal_cmd(struct scst_cmd *cmd) -{ - TRACE_ENTRY(); - - __scst_cmd_put(cmd); - - TRACE_EXIT(); - return; -} - int scst_prepare_request_sense(struct scst_cmd *orig_cmd) { int res = 0; @@ -1088,11 +1083,11 @@ int scst_prepare_request_sense(struct scst_cmd *orig_cmd) rs_cmd->expected_values_set = 1; TRACE(TRACE_MGMT_MINOR, "Adding REQUEST SENSE cmd %p to head of active " - "cmd list ", rs_cmd); + "cmd list", rs_cmd); spin_lock_irq(&rs_cmd->cmd_lists->cmd_list_lock); list_add(&rs_cmd->cmd_list_entry, &rs_cmd->cmd_lists->active_cmd_list); - spin_unlock_irq(&rs_cmd->cmd_lists->cmd_list_lock); wake_up(&rs_cmd->cmd_lists->cmd_list_waitQ); + spin_unlock_irq(&rs_cmd->cmd_lists->cmd_list_lock); out: TRACE_EXIT_RES(res); @@ -1104,7 +1099,7 @@ out_error: #undef sbuf_size } -struct scst_cmd *scst_complete_request_sense(struct scst_cmd *req_cmd) +static void scst_complete_request_sense(struct scst_cmd *req_cmd) { struct scst_cmd *orig_cmd = req_cmd->orig_cmd; uint8_t *buf; @@ -1132,10 +1127,34 @@ struct scst_cmd *scst_complete_request_sense(struct scst_cmd *req_cmd) if (len > 0) scst_put_buf(req_cmd, buf); - scst_free_internal_cmd(req_cmd); + TRACE(TRACE_MGMT_MINOR, "Adding orig cmd %p to head of active " + "cmd list", orig_cmd); + spin_lock_irq(&orig_cmd->cmd_lists->cmd_list_lock); + list_add(&orig_cmd->cmd_list_entry, &orig_cmd->cmd_lists->active_cmd_list); + wake_up(&orig_cmd->cmd_lists->cmd_list_waitQ); + spin_unlock_irq(&orig_cmd->cmd_lists->cmd_list_lock); - TRACE_EXIT_HRES((unsigned long)orig_cmd); - return orig_cmd; + TRACE_EXIT(); + return; +} + +int scst_finish_internal_cmd(struct scst_cmd *cmd) +{ + int res; + + TRACE_ENTRY(); + + sBUG_ON(!cmd->internal); + + if (cmd->cdb[0] == REQUEST_SENSE) + scst_complete_request_sense(cmd); + + __scst_cmd_put(cmd); + + res = SCST_CMD_STATE_RES_CONT_NEXT; + + TRACE_EXIT_HRES(res); + return res; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) @@ -1515,13 +1534,6 @@ void scst_free_cmd(struct scst_cmd *cmd) if (!cmd->tgt_data_buf_alloced) scst_check_restore_sg_buff(cmd); - if (unlikely(cmd->internal)) { - if (cmd->bufflen > 0) - scst_release_space(cmd); - scst_destroy_cmd(cmd); - goto out; - } - if (cmd->tgtt->on_free_cmd != NULL) { TRACE_DBG("Calling target's on_free_cmd(%p)", cmd); cmd->tgtt->on_free_cmd(cmd); @@ -1549,7 +1561,7 @@ void scst_free_cmd(struct scst_cmd *cmd) if (likely(cmd->tgt_dev != NULL)) { #ifdef CONFIG_SCST_EXTRACHECKS - if (unlikely(!cmd->sent_for_exec)) { + if (unlikely(!cmd->sent_for_exec) && !cmd->internal) { PRINT_ERROR("Finishing not executed cmd %p (opcode " "%d, target %s, lun %lld, sn %ld, expected_sn %ld)", cmd, cmd->cdb[0], cmd->tgtt->name, @@ -1572,7 +1584,6 @@ void scst_free_cmd(struct scst_cmd *cmd) if (likely(destroy)) scst_destroy_put_cmd(cmd); -out: TRACE_EXIT(); return; } diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index 7141c5245..f9f365257 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -261,7 +261,7 @@ int scst_acg_add_name(struct scst_acg *acg, const char *name); int scst_acg_remove_name(struct scst_acg *acg, const char *name); int scst_prepare_request_sense(struct scst_cmd *orig_cmd); -struct scst_cmd *scst_complete_request_sense(struct scst_cmd *cmd); +int scst_finish_internal_cmd(struct scst_cmd *cmd); int scst_assign_dev_handler(struct scst_device *dev, struct scst_dev_type *handler); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 1e2196fc9..224e63581 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -645,6 +645,7 @@ set_res: case SCST_CMD_STATE_PRE_XMIT_RESP: case SCST_CMD_STATE_XMIT_RESP: case SCST_CMD_STATE_FINISHED: + case SCST_CMD_STATE_FINISHED_INTERNAL: cmd->state = state; res = SCST_CMD_STATE_RES_CONT_SAME; break; @@ -1374,7 +1375,8 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state, #ifdef CONFIG_SCST_EXTRACHECKS if ((next_state != SCST_CMD_STATE_PRE_DEV_DONE) && (next_state != SCST_CMD_STATE_PRE_XMIT_RESP) && - (next_state != SCST_CMD_STATE_FINISHED)) { + (next_state != SCST_CMD_STATE_FINISHED) && + (next_state != SCST_CMD_STATE_FINISHED_INTERNAL)) { PRINT_ERROR("%s() received invalid cmd state %d (opcode %d)", __func__, next_state, cmd->cdb[0]); scst_set_cmd_error(cmd, @@ -2587,10 +2589,9 @@ static void scst_inc_check_expected_sn(struct scst_cmd *cmd) scst_make_deferred_commands_active(cmd->tgt_dev); } -static int scst_dev_done(struct scst_cmd **pcmd) +static int scst_dev_done(struct scst_cmd *cmd) { int res = SCST_CMD_STATE_RES_CONT_SAME; - struct scst_cmd *cmd = *pcmd; int state; struct scst_device *dev = cmd->dev; @@ -2638,6 +2639,7 @@ static int scst_dev_done(struct scst_cmd **pcmd) case SCST_CMD_STATE_DEV_DONE: case SCST_CMD_STATE_XMIT_RESP: case SCST_CMD_STATE_FINISHED: + case SCST_CMD_STATE_FINISHED_INTERNAL: cmd->state = state; break; @@ -2673,8 +2675,8 @@ static int scst_dev_done(struct scst_cmd **pcmd) if (cmd->inc_expected_sn_on_done && cmd->sent_for_exec) scst_inc_check_expected_sn(cmd); - if (unlikely(cmd->cdb[0] == REQUEST_SENSE) && (cmd->internal)) - *pcmd = scst_complete_request_sense(cmd); + if (unlikely(cmd->internal)) + cmd->state = SCST_CMD_STATE_FINISHED_INTERNAL; out: TRACE_EXIT_HRES(res); @@ -2687,6 +2689,8 @@ static int scst_pre_xmit_response(struct scst_cmd *cmd) TRACE_ENTRY(); + EXTRACHECKS_BUG_ON(cmd->internal); + #ifdef CONFIG_SCST_DEBUG_TM if (cmd->tm_dbg_delayed && !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) { @@ -2792,6 +2796,8 @@ static int scst_xmit_response(struct scst_cmd *cmd) TRACE_ENTRY(); + EXTRACHECKS_BUG_ON(cmd->internal); + if (unlikely(!cmd->tgtt->xmit_response_atomic && scst_cmd_atomic(cmd))) { /* @@ -3402,7 +3408,7 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic) break; case SCST_CMD_STATE_DEV_DONE: - res = scst_dev_done(&cmd); + res = scst_dev_done(cmd); break; case SCST_CMD_STATE_PRE_XMIT_RESP: @@ -3421,6 +3427,12 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic) SCST_CMD_STATE_RES_NEED_THREAD); break; + case SCST_CMD_STATE_FINISHED_INTERNAL: + res = scst_finish_internal_cmd(cmd); + EXTRACHECKS_BUG_ON(res == + SCST_CMD_STATE_RES_NEED_THREAD); + break; + default: PRINT_CRIT_ERROR("cmd (%p) in state %d, but shouldn't " "be", cmd, cmd->state); @@ -3449,6 +3461,7 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic) case SCST_CMD_STATE_PRE_XMIT_RESP: case SCST_CMD_STATE_XMIT_RESP: case SCST_CMD_STATE_FINISHED: + case SCST_CMD_STATE_FINISHED_INTERNAL: TRACE_DBG("Adding cmd %p to head of active cmd list", cmd); list_add(&cmd->cmd_list_entry,