Critical fix:
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 10 Apr 2008 10:57:30 +0000 (10:57 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Thu, 10 Apr 2008 10:57:30 +0000 (10:57 +0000)
 - Fixes hang on HEAD OF QUEUE commands under high load

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@333 d57e44dd-8a1f-0410-8b47-8ef2f437770f

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

index 121fc6a..e6577b4 100644 (file)
@@ -1082,9 +1082,12 @@ struct scst_cmd
         */
        unsigned int preprocessing_only:1;
 
-       /* Set if scst_cmd_set_sn() was called */
+       /* Set if cmd's SN was set */
        unsigned int sn_set:1;
 
+       /* Set if hq_cmd_count was incremented */
+       unsigned int hq_cmd_inced:1;
+
        /*
         * Set if scst_cmd_init_stage1_done() called and the target wants
         * that the SN for the cmd won't be assigned until scst_restart_cmd()
index 39f4487..889f537 100644 (file)
@@ -3045,6 +3045,9 @@ void scst_on_hq_cmd_response(struct scst_cmd *cmd)
 
        TRACE_ENTRY();
 
+       if (!cmd->hq_cmd_inced)
+               goto out;
+
        spin_lock_irq(&tgt_dev->sn_lock);
        tgt_dev->hq_cmd_count--;
        spin_unlock_irq(&tgt_dev->sn_lock);
@@ -3059,6 +3062,7 @@ void scst_on_hq_cmd_response(struct scst_cmd *cmd)
        if (tgt_dev->hq_cmd_count == 0)
                scst_make_deferred_commands_active(tgt_dev, cmd);
 
+out:
        TRACE_EXIT();
        return;
 }
index 36c57e8..b0a4a5d 100644 (file)
@@ -2725,11 +2725,15 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
        struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
        unsigned long flags;
 
+       TRACE_ENTRY();
+
        if (scst_is_implicit_hq(cmd)) {
                TRACE(TRACE_SCSI|TRACE_SCSI_SERIALIZING, "Implicit HQ cmd %p", cmd);
                cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
        }
 
+       EXTRACHECKS_BUG_ON(cmd->sn_set || cmd->hq_cmd_inced);
+
        /* Optimized for lockless fast path */
 
        scst_check_debug_sn(cmd);
@@ -2817,6 +2821,7 @@ ordered:
                spin_lock_irqsave(&tgt_dev->sn_lock, flags);
                tgt_dev->hq_cmd_count++;
                spin_unlock_irqrestore(&tgt_dev->sn_lock, flags);
+               cmd->hq_cmd_inced = 1;
                goto out;
 
        default:
@@ -2833,6 +2838,7 @@ ordered:
        cmd->sn_set = 1;
 
 out:
+       TRACE_EXIT();
        return;
 }