summaryrefslogtreecommitdiff
path: root/drivers/target/target_core_transport.c
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2018-11-27 15:52:02 -0800
committerMartin K. Petersen <martin.petersen@oracle.com>2018-12-07 21:22:15 -0500
commitaaa00cc93c1d0fd2693a76ea2ba375ea1ac1a7f3 (patch)
treeda0d9fadd963839970a2526474aa4ce6c473d37e /drivers/target/target_core_transport.c
parentfbbd49235590ca759aada500b5a935e06b7f6708 (diff)
scsi: target/core: Fix TAS handling for aborted commands
The TASK ABORTED STATUS (TAS) bit is defined as follows in SAM: "TASK_ABORTED: this status shall be returned if a command is aborted by a command or task management function on another I_T nexus and the control mode page TAS bit is set to one". TAS handling is spread over the target core and the iSCSI target driver. If a LUN RESET is received, the target core will send the TASK_ABORTED response for all commands for which such a response has to be sent. If an ABORT TASK is received, only the iSCSI target driver will send the TASK_ABORTED response for the commands for which that response has to be sent. That is a bug since all target drivers have to honor the TAS bit. Fix this by moving the code that handles TAS from the iSCSI target driver into the target core. Additionally, if a command has been aborted, instead of sending the TASK_ABORTED status from the context that processes the SCSI command send it from the context of the ABORT TMF. The core_tmr_abort_task() change in this patch causes the CMD_T_TAS flag to be set if a TASK_ABORTED status has to be sent back to the initiator that submitted the command. If that flag has been set transport_cmd_finish_abort() will send the TASK_ABORTED response. Cc: Nicholas Bellinger <nab@linux-iscsi.org> Cc: Mike Christie <mchristi@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Cc: David Disseldorp <ddiss@suse.de> Cc: Hannes Reinecke <hare@suse.de> Signed-off-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/target/target_core_transport.c')
-rw-r--r--drivers/target/target_core_transport.c55
1 files changed, 2 insertions, 53 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 868ee9c28c9a..32457fd7a736 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1805,7 +1805,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
if (cmd->transport_complete_callback)
cmd->transport_complete_callback(cmd, false, NULL);
- if (transport_check_aborted_status(cmd, 1))
+ if (cmd->transport_state & CMD_T_ABORTED)
return;
switch (sense_reason) {
@@ -2012,8 +2012,6 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
return true;
}
-static int __transport_check_aborted_status(struct se_cmd *, int);
-
void target_execute_cmd(struct se_cmd *cmd)
{
/*
@@ -2023,7 +2021,7 @@ void target_execute_cmd(struct se_cmd *cmd)
* If the received CDB has already been aborted stop processing it here.
*/
spin_lock_irq(&cmd->t_state_lock);
- if (__transport_check_aborted_status(cmd, 1)) {
+ if (cmd->transport_state & CMD_T_ABORTED) {
spin_unlock_irq(&cmd->t_state_lock);
return;
}
@@ -3237,55 +3235,6 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
}
EXPORT_SYMBOL(transport_send_check_condition_and_sense);
-static int __transport_check_aborted_status(struct se_cmd *cmd, int send_status)
- __releases(&cmd->t_state_lock)
- __acquires(&cmd->t_state_lock)
-{
- int ret;
-
- assert_spin_locked(&cmd->t_state_lock);
- WARN_ON_ONCE(!irqs_disabled());
-
- if (!(cmd->transport_state & CMD_T_ABORTED))
- return 0;
- /*
- * If cmd has been aborted but either no status is to be sent or it has
- * already been sent, just return
- */
- if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS)) {
- if (send_status)
- cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS;
- return 1;
- }
-
- pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB:"
- " 0x%02x ITT: 0x%08llx\n", cmd->t_task_cdb[0], cmd->tag);
-
- cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS;
- cmd->scsi_status = SAM_STAT_TASK_ABORTED;
- trace_target_cmd_complete(cmd);
-
- spin_unlock_irq(&cmd->t_state_lock);
- ret = cmd->se_tfo->queue_status(cmd);
- if (ret)
- transport_handle_queue_full(cmd, cmd->se_dev, ret, false);
- spin_lock_irq(&cmd->t_state_lock);
-
- return 1;
-}
-
-int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
-{
- int ret;
-
- spin_lock_irq(&cmd->t_state_lock);
- ret = __transport_check_aborted_status(cmd, send_status);
- spin_unlock_irq(&cmd->t_state_lock);
-
- return ret;
-}
-EXPORT_SYMBOL(transport_check_aborted_status);
-
void transport_send_task_abort(struct se_cmd *cmd)
{
unsigned long flags;