target: Fix regression bug with handling of zero-length data CDBs
authorNicholas Bellinger <nab@linux-iscsi.org>
Fri, 17 Aug 2012 00:06:41 +0000 (17:06 -0700)
committerNicholas Bellinger <nab@linux-iscsi.org>
Sat, 18 Aug 2012 00:24:11 +0000 (17:24 -0700)
This patch fixes a regression bug with the handling of zero-length
data CDBs within transport_generic_new_cmd() code.  The bug was introduced
with the following commit as part of the single task conversion work:

  commit 4101f0a89d4eb13f04cb0344d59a335b862ca5f9
  Author: Christoph Hellwig <hch@infradead.org>
  Date:   Tue Apr 24 00:25:03 2012 -0400

      target: always allocate a single task

where the zero-length check for SCF_SCSI_DATA_SG_IO_CDB was incorrectly
changed to SCF_SCSI_CONTROL_SG_IO_CDB because of the seperate comment
in transport_generic_new_cmd() wrt to control CDBs zero-length handling
introduced in:

  commit 91ec1d3535b2acf12c599045cc19ad9be3c6a47b
  Author: Nicholas Bellinger <nab@linux-iscsi.org>
  Date:   Fri Jan 13 12:01:34 2012 -0800

      target: Add workaround for zero-length control CDB handling

So go ahead and change transport_generic_new_cmd() to handle control+data
zero-length CDBs in the same manner for this special case.

Tested with iscsi-target + loopback fabric port LUNs on 3.6-rc0 code.

This patch will also need to be picked up for 3.5-stable.

(hch: Add proper comment in transport_generic_new_cmd)

Cc: Christoph Hellwig <hch@lst.de>
Cc: Roland Dreier <roland@purestorage.com>
Cc: Andy Grover <agrover@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/target_core_transport.c

index a7589cc..ea9a3d2 100644 (file)
@@ -2323,9 +2323,12 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
                if (ret < 0)
                        goto out_fail;
        }
-
-       /* Workaround for handling zero-length control CDBs */
-       if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->data_length) {
+       /*
+        * If this command doesn't have any payload and we don't have to call
+        * into the fabric for data transfers, go ahead and complete it right
+        * away.
+        */
+       if (!cmd->data_length) {
                spin_lock_irq(&cmd->t_state_lock);
                cmd->t_state = TRANSPORT_COMPLETE;
                cmd->transport_state |= CMD_T_ACTIVE;