From 5b77c89fbde588ed80c55f4b7bb787e3bcb7f5fb Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Thu, 14 Jan 2010 13:14:30 +0000 Subject: [PATCH] Patch from Gilad H with improvements fixing the following scenario: 1. Commands start going to the init_cmd_list probably because SCST was suspended 2. A command is now waiting in the init_cmd_list, it was not yet completely initialized (more impotently cmd->dev == NULL) 3. A clear task set for the same lun arrives from a different initiator 4. The command is marked as aborted from other initiator and released from the init list. 5. The command gets to the PRE_XMIT_RESPONSE state, since it was aborted the scst_xmit_process_aborted_cmd is called. 6. At this stage since the command is marked as aborted by other initiator the scst checks for the device TAS flag (cmd->dev->tas) however cmd->dev is NULL and we crash on Null pointer de-referencing. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1466 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 6 ++++++ scst/src/scst_lib.c | 3 ++- scst/src/scst_targ.c | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 5c2be594d..a4609e1a7 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -445,6 +445,12 @@ enum scst_exec_context { /* Set if the cmd is dead and can be destroyed at any time */ #define SCST_CMD_CAN_BE_DESTROYED 3 +/* + * Set if the cmd's device has TAS flag set. Used only when aborted by + * other initiator. + */ +#define SCST_CMD_DEVICE_TAS 4 + /************************************************************* ** Tgt_dev's async. flags (tgt_dev_flags) *************************************************************/ diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 1d392fd4f..774d26010 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -5736,7 +5736,8 @@ void scst_xmit_process_aborted_cmd(struct scst_cmd *cmd) goto out; } - if (cmd->dev->tas) { + /* For not yet inited commands cmd->dev can be NULL here */ + if (test_bit(SCST_CMD_DEVICE_TAS, &cmd->cmd_flags)) { TRACE_MGMT_DBG("Flag ABORTED OTHER set for cmd %p " "(tag %llu), returning TASK ABORTED ", cmd, (long long unsigned int)cmd->tag); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index c37268d0f..7ae1dfa36 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -4063,9 +4063,25 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd, spin_lock_irqsave(&other_ini_lock, flags); if (other_ini) { + struct scst_device *dev = NULL; + /* Might be necessary if command aborted several times */ if (!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) set_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags); + + /* Necessary for scst_xmit_process_aborted_cmd */ + if (cmd->dev != NULL) + dev = cmd->dev; + else if ((mcmd != NULL) && (mcmd->mcmd_tgt_dev != NULL)) + dev = mcmd->mcmd_tgt_dev->dev; + + if (dev != NULL) { + if (dev->tas) + set_bit(SCST_CMD_DEVICE_TAS, &cmd->cmd_flags); + } else + PRINT_WARNING("Abort cmd %p from other initiator, but " + "neither cmd, nor mcmd %p have tgt_dev set, so " + "TAS information can be lost", cmd, mcmd); } else { /* Might be necessary if command aborted several times */ clear_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);