Patch from Gilad H <gilad.public2@gmail.com> with improvements fixing the following...
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 14 Jan 2010 13:14:30 +0000 (13:14 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 14 Jan 2010 13:14:30 +0000 (13:14 +0000)
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: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1466 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scst/include/scst.h
scst/src/scst_lib.c
scst/src/scst_targ.c

index 5c2be59..a4609e1 100644 (file)
@@ -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)
  *************************************************************/
index 1d392fd..774d260 100644 (file)
@@ -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);
index c37268d..7ae1dfa 100644 (file)
@@ -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);