From 5b26b06791d41e3081d83956830ca543e0c8f4f2 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Thu, 16 Aug 2012 19:52:32 +0000 Subject: [PATCH] We need to abort internal commands as well. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4470 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/scst_lib.c | 24 ++++++++++++++++++++++++ scst/src/scst_priv.h | 1 + scst/src/scst_targ.c | 17 ++++++----------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 96192e64c..47bace07c 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -4473,6 +4473,7 @@ static struct scst_cmd *scst_create_prepare_internal_cmd( struct scst_cmd *res; int rc; gfp_t gfp_mask = scst_cmd_atomic(orig_cmd) ? GFP_ATOMIC : GFP_KERNEL; + unsigned long flags; TRACE_ENTRY(); @@ -4494,6 +4495,17 @@ static struct scst_cmd *scst_create_prepare_internal_cmd( res->queue_type = queue_type; res->data_direction = SCST_DATA_UNKNOWN; + /* + * We need to keep it here to be able to abort during TM processing. + * They should be aborted to (1) speed up TM processing and (2) to + * guarantee that after a TM command finished the affected device(s) + * is/are in a quiescent state with all affected commands finished and + * others - blocked. + */ + spin_lock_irqsave(&res->sess->sess_list_lock, flags); + list_add_tail(&res->sess_cmd_list_entry, &res->sess->sess_cmd_list); + spin_unlock_irqrestore(&res->sess->sess_list_lock, flags); + scst_sess_get(res->sess); if (res->tgt_dev != NULL) res->cpu_cmd_counter = scst_get(); @@ -4926,6 +4938,7 @@ EXPORT_SYMBOL_GPL(scst_write_same); int scst_finish_internal_cmd(struct scst_cmd *cmd) { int res; + unsigned long flags; TRACE_ENTRY(); @@ -4938,6 +4951,17 @@ int scst_finish_internal_cmd(struct scst_cmd *cmd) goto out; } + spin_lock_irqsave(&cmd->sess->sess_list_lock, flags); + list_del(&cmd->sess_cmd_list_entry); + cmd->done = 1; + cmd->finished = 1; + spin_unlock_irqrestore(&cmd->sess->sess_list_lock, flags); + + if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) { + scst_done_cmd_mgmt(cmd); + scst_finish_cmd_mgmt(cmd); + } + if (cmd->cdb[0] == REQUEST_SENSE) scst_complete_request_sense(cmd); else { diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index af18bbd4d..e60d5ba50 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -394,6 +394,7 @@ uint64_t scst_unpack_lun(const uint8_t *lun, int len); struct scst_mgmt_cmd *scst_alloc_mgmt_cmd(gfp_t gfp_mask); void scst_free_mgmt_cmd(struct scst_mgmt_cmd *mcmd); void scst_done_cmd_mgmt(struct scst_cmd *cmd); +void scst_finish_cmd_mgmt(struct scst_cmd *cmd); static inline void scst_devt_cleanup(struct scst_dev_type *devt) { } diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 52c085993..6cd1ec4ca 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -45,7 +45,6 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd); static int __scst_init_cmd(struct scst_cmd *cmd); -static void scst_finish_cmd_mgmt(struct scst_cmd *cmd); static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag, bool to_abort); static void scst_process_redirect_cmd(struct scst_cmd *cmd, @@ -4703,7 +4702,7 @@ void scst_async_mcmd_completed(struct scst_mgmt_cmd *mcmd, int status) EXPORT_SYMBOL_GPL(scst_async_mcmd_completed); /* No locks */ -static void scst_finish_cmd_mgmt(struct scst_cmd *cmd) +void scst_finish_cmd_mgmt(struct scst_cmd *cmd) { struct scst_mgmt_cmd_stub *mstb, *t; bool wake = false; @@ -4846,9 +4845,6 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd, */ smp_mb__after_set_bit(); - if (cmd->internal) - goto out; - if (cmd->tgt_dev == NULL) { spin_lock_irqsave(&scst_init_lock, flags); scst_init_poll_cnt++; @@ -4909,12 +4905,12 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd, "sn %u) being executed/xmitted (state %d, " "op %x, proc time %ld sec., timeout %d sec.), " "deferring ABORT (cmd_done_wait_count %d, " - "cmd_finish_wait_count %d)", cmd, + "cmd_finish_wait_count %d, internal %d)", cmd, (long long unsigned int)cmd->tag, cmd->sn, cmd->state, cmd->cdb[0], (long)(jiffies - cmd->start_time) / HZ, cmd->timeout / HZ, mcmd->cmd_done_wait_count, - mcmd->cmd_finish_wait_count); + mcmd->cmd_finish_wait_count, cmd->internal); /* * cmd can't die here or sess_list_lock already taken * and cmd is in the sess list @@ -4926,14 +4922,13 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd, mempool_free(mstb, scst_mgmt_stub_mempool); } - if (cmd->tgtt->on_abort_cmd) + if (!cmd->internal && cmd->tgtt->on_abort_cmd) cmd->tgtt->on_abort_cmd(cmd); } unlock: spin_unlock_irqrestore(&scst_mcmd_lock, flags); -out: tm_dbg_release_cmd(cmd); TRACE_EXIT(); @@ -6894,7 +6889,7 @@ static struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess, list_for_each_entry(cmd, &sess->sess_cmd_list, sess_cmd_list_entry) { - if (cmd->tag == tag) { + if ((cmd->tag == tag) && likely(!cmd->internal)) { /* * We must not count done commands, because * they were submitted for transmission. @@ -6965,7 +6960,7 @@ struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data, */ if (cmd->done) continue; - if (cmp_fn(cmd, data)) + if (cmp_fn(cmd, data) && likely(!cmd->internal)) goto out_unlock; }