aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Leung <amleung21@yahoo.com>2014-03-22 01:20:41 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2014-04-07 04:48:50 -0400
commit68259b5aac13a57cba797b9605ed9812158f0e72 (patch)
tree914de31ac9381cb8a1f591af859ab91adaeee4db
parentf46d6a8a01d6bbd83a97140f30a72a89b038807b (diff)
target: Fix Task Aborted Status (TAS) handling
This patch addresses three of long standing issues wrt to Task Aborted Status (TAS) handling. The first is the incorrect assumption in core_tmr_handle_tas_abort() that TASK_ABORTED status is sent for the task referenced by TMR ABORT_TASK, and sending TASK_ABORTED status for TMR LUN_RESET on the same nexus the LUN_RESET was received. The second is to ensure the lun reference count is dropped within transport_cmd_finish_abort() by calling transport_lun_remove_cmd() before invoking transport_cmd_check_stop_to_fabric(). The last is to fix the delayed TAS handling to allow outstanding WRITEs to complete before sending the TASK_ABORTED status. This includes changing transport_check_aborted_status() to avoid processing when SCF_SEND_DELAYED_TAS has not be set, and updating transport_send_task_abort() to drop the SCF_SENT_DELAYED_TAS check. Signed-off-by: Alex Leung <amleung21@yahoo.com> Cc: Alex Leung <amleung21@yahoo.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_tmr.c18
-rw-r--r--drivers/target/target_core_transport.c14
-rw-r--r--include/target/target_core_base.h2
3 files changed, 18 insertions, 16 deletions
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index 70c638f730af..3f0338fff240 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -87,14 +87,17 @@ static void core_tmr_handle_tas_abort(
87 struct se_cmd *cmd, 87 struct se_cmd *cmd,
88 int tas) 88 int tas)
89{ 89{
90 bool remove = true;
90 /* 91 /*
91 * TASK ABORTED status (TAS) bit support 92 * TASK ABORTED status (TAS) bit support
92 */ 93 */
93 if ((tmr_nacl && 94 if ((tmr_nacl &&
94 (tmr_nacl == cmd->se_sess->se_node_acl)) || tas) 95 (tmr_nacl != cmd->se_sess->se_node_acl)) && tas) {
96 remove = false;
95 transport_send_task_abort(cmd); 97 transport_send_task_abort(cmd);
98 }
96 99
97 transport_cmd_finish_abort(cmd, 0); 100 transport_cmd_finish_abort(cmd, remove);
98} 101}
99 102
100static int target_check_cdb_and_preempt(struct list_head *list, 103static int target_check_cdb_and_preempt(struct list_head *list,
@@ -150,18 +153,9 @@ void core_tmr_abort_task(
150 153
151 cancel_work_sync(&se_cmd->work); 154 cancel_work_sync(&se_cmd->work);
152 transport_wait_for_tasks(se_cmd); 155 transport_wait_for_tasks(se_cmd);
153 /*
154 * Now send SAM_STAT_TASK_ABORTED status for the referenced
155 * se_cmd descriptor..
156 */
157 transport_send_task_abort(se_cmd);
158 /*
159 * Also deal with possible extra acknowledge reference..
160 */
161 if (se_cmd->se_cmd_flags & SCF_ACK_KREF)
162 target_put_sess_cmd(se_sess, se_cmd);
163 156
164 target_put_sess_cmd(se_sess, se_cmd); 157 target_put_sess_cmd(se_sess, se_cmd);
158 transport_cmd_finish_abort(se_cmd, true);
165 159
166 printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" 160 printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
167 " ref_tag: %d\n", ref_tag); 161 " ref_tag: %d\n", ref_tag);
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 0a359fa82bd3..51a375453d9b 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -603,6 +603,9 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd)
603 603
604void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) 604void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
605{ 605{
606 if (cmd->se_cmd_flags & SCF_SE_LUN_CMD)
607 transport_lun_remove_cmd(cmd);
608
606 if (transport_cmd_check_stop_to_fabric(cmd)) 609 if (transport_cmd_check_stop_to_fabric(cmd))
607 return; 610 return;
608 if (remove) 611 if (remove)
@@ -2784,13 +2787,17 @@ int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
2784 if (!(cmd->transport_state & CMD_T_ABORTED)) 2787 if (!(cmd->transport_state & CMD_T_ABORTED))
2785 return 0; 2788 return 0;
2786 2789
2787 if (!send_status || (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS)) 2790 /*
2791 * If cmd has been aborted but either no status is to be sent or it has
2792 * already been sent, just return
2793 */
2794 if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS))
2788 return 1; 2795 return 1;
2789 2796
2790 pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08x\n", 2797 pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08x\n",
2791 cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); 2798 cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd));
2792 2799
2793 cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS; 2800 cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS;
2794 cmd->scsi_status = SAM_STAT_TASK_ABORTED; 2801 cmd->scsi_status = SAM_STAT_TASK_ABORTED;
2795 trace_target_cmd_complete(cmd); 2802 trace_target_cmd_complete(cmd);
2796 cmd->se_tfo->queue_status(cmd); 2803 cmd->se_tfo->queue_status(cmd);
@@ -2804,7 +2811,7 @@ void transport_send_task_abort(struct se_cmd *cmd)
2804 unsigned long flags; 2811 unsigned long flags;
2805 2812
2806 spin_lock_irqsave(&cmd->t_state_lock, flags); 2813 spin_lock_irqsave(&cmd->t_state_lock, flags);
2807 if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION | SCF_SENT_DELAYED_TAS)) { 2814 if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION)) {
2808 spin_unlock_irqrestore(&cmd->t_state_lock, flags); 2815 spin_unlock_irqrestore(&cmd->t_state_lock, flags);
2809 return; 2816 return;
2810 } 2817 }
@@ -2819,6 +2826,7 @@ void transport_send_task_abort(struct se_cmd *cmd)
2819 if (cmd->data_direction == DMA_TO_DEVICE) { 2826 if (cmd->data_direction == DMA_TO_DEVICE) {
2820 if (cmd->se_tfo->write_pending_status(cmd) != 0) { 2827 if (cmd->se_tfo->write_pending_status(cmd) != 0) {
2821 cmd->transport_state |= CMD_T_ABORTED; 2828 cmd->transport_state |= CMD_T_ABORTED;
2829 cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS;
2822 smp_mb__after_atomic_inc(); 2830 smp_mb__after_atomic_inc();
2823 return; 2831 return;
2824 } 2832 }
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index f13fd09d91dc..ec3e3a3ff4f6 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -162,7 +162,7 @@ enum se_cmd_flags_table {
162 SCF_SENT_CHECK_CONDITION = 0x00000800, 162 SCF_SENT_CHECK_CONDITION = 0x00000800,
163 SCF_OVERFLOW_BIT = 0x00001000, 163 SCF_OVERFLOW_BIT = 0x00001000,
164 SCF_UNDERFLOW_BIT = 0x00002000, 164 SCF_UNDERFLOW_BIT = 0x00002000,
165 SCF_SENT_DELAYED_TAS = 0x00004000, 165 SCF_SEND_DELAYED_TAS = 0x00004000,
166 SCF_ALUA_NON_OPTIMIZED = 0x00008000, 166 SCF_ALUA_NON_OPTIMIZED = 0x00008000,
167 SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000, 167 SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000,
168 SCF_ACK_KREF = 0x00040000, 168 SCF_ACK_KREF = 0x00040000,