Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

target: Fix ordered task CHECK_CONDITION early exception handling

If a Simple command is sent with a failure, target_setup_cmd_from_cdb
returns with TCM_UNSUPPORTED_SCSI_OPCODE or TCM_INVALID_CDB_FIELD.

So in the cases where target_setup_cmd_from_cdb returns an error, we
never get far enough to call target_execute_cmd to increment simple_cmds.
Since simple_cmds isn't incremented, the result of the failure from
target_setup_cmd_from_cdb causes transport_generic_request_failure to
decrement simple_cmds, due to call to transport_complete_task_attr.

With this dev->simple_cmds or dev->dev_ordered_sync is now -1, not 0.
So when a subsequent command with an Ordered Task is sent, it causes
a hang, since dev->simple_cmds is at -1.

Tested-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Tested-by: Michael Cyr <mikecyr@linux.vnet.ibm.com>
Signed-off-by: Michael Cyr <mikecyr@linux.vnet.ibm.com>
Cc: stable@vger.kernel.org # 4.4+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

+7 -1
+6 -1
drivers/target/target_core_transport.c
··· 1827 1827 if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) 1828 1828 return false; 1829 1829 1830 + cmd->se_cmd_flags |= SCF_TASK_ATTR_SET; 1831 + 1830 1832 /* 1831 1833 * Check for the existence of HEAD_OF_QUEUE, and if true return 1 1832 1834 * to allow the passed struct se_cmd list of tasks to the front of the list. ··· 1951 1949 if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) 1952 1950 return; 1953 1951 1952 + if (!(cmd->se_cmd_flags & SCF_TASK_ATTR_SET)) 1953 + goto restart; 1954 + 1954 1955 if (cmd->sam_task_attr == TCM_SIMPLE_TAG) { 1955 1956 atomic_dec_mb(&dev->simple_cmds); 1956 1957 dev->dev_cur_ordered_id++; ··· 1970 1965 pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n", 1971 1966 dev->dev_cur_ordered_id); 1972 1967 } 1973 - 1968 + restart: 1974 1969 target_restart_delayed_cmds(dev); 1975 1970 } 1976 1971
+1
include/target/target_core_base.h
··· 142 142 SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = 0x00200000, 143 143 SCF_ACK_KREF = 0x00400000, 144 144 SCF_USE_CPUID = 0x00800000, 145 + SCF_TASK_ATTR_SET = 0x01000000, 145 146 }; 146 147 147 148 /*