Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964896AbcCIXp6 (ORCPT ); Wed, 9 Mar 2016 18:45:58 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:40733 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934416AbcCIXQ3 (ORCPT ); Wed, 9 Mar 2016 18:16:29 -0500 From: Kamal Mostafa To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, kernel-team@lists.ubuntu.com Cc: Alex Leung , Nicholas Bellinger , Kamal Mostafa Subject: [PATCH 3.13.y-ckt 041/138] target: Fix Task Aborted Status (TAS) handling Date: Wed, 9 Mar 2016 15:12:48 -0800 Message-Id: <1457565265-15195-42-git-send-email-kamal@canonical.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1457565265-15195-1-git-send-email-kamal@canonical.com> References: <1457565265-15195-1-git-send-email-kamal@canonical.com> X-Extended-Stable: 3.13 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5338 Lines: 147 3.13.11-ckt36 -stable review patch. If anyone has any objections, please let me know. ---8<------------------------------------------------------------ From: Alex Leung [ Upstream commit 68259b5aac13a57cba797b9605ed9812158f0e72 ] 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 Cc: Alex Leung Signed-off-by: Nicholas Bellinger Signed-off-by: Kamal Mostafa --- drivers/target/target_core_tmr.c | 18 ++++++------------ drivers/target/target_core_transport.c | 14 +++++++++++--- include/target/target_core_base.h | 2 +- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 70c638f..3f0338f 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( struct se_cmd *cmd, int tas) { + bool remove = true; /* * TASK ABORTED status (TAS) bit support */ if ((tmr_nacl && - (tmr_nacl == cmd->se_sess->se_node_acl)) || tas) + (tmr_nacl != cmd->se_sess->se_node_acl)) && tas) { + remove = false; transport_send_task_abort(cmd); + } - transport_cmd_finish_abort(cmd, 0); + transport_cmd_finish_abort(cmd, remove); } static int target_check_cdb_and_preempt(struct list_head *list, @@ -150,18 +153,9 @@ void core_tmr_abort_task( cancel_work_sync(&se_cmd->work); transport_wait_for_tasks(se_cmd); - /* - * Now send SAM_STAT_TASK_ABORTED status for the referenced - * se_cmd descriptor.. - */ - transport_send_task_abort(se_cmd); - /* - * Also deal with possible extra acknowledge reference.. - */ - if (se_cmd->se_cmd_flags & SCF_ACK_KREF) - target_put_sess_cmd(se_sess, se_cmd); target_put_sess_cmd(se_sess, se_cmd); + transport_cmd_finish_abort(se_cmd, true); printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" " ref_tag: %d\n", ref_tag); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 7458b13..28f4c67 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -577,6 +577,9 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) { + if (cmd->se_cmd_flags & SCF_SE_LUN_CMD) + transport_lun_remove_cmd(cmd); + if (transport_cmd_check_stop_to_fabric(cmd)) return; if (remove) @@ -2741,13 +2744,17 @@ int transport_check_aborted_status(struct se_cmd *cmd, int send_status) if (!(cmd->transport_state & CMD_T_ABORTED)) return 0; - if (!send_status || (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS)) + /* + * 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)) return 1; pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08x\n", cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); - cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS; + cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS; cmd->scsi_status = SAM_STAT_TASK_ABORTED; trace_target_cmd_complete(cmd); cmd->se_tfo->queue_status(cmd); @@ -2761,7 +2768,7 @@ void transport_send_task_abort(struct se_cmd *cmd) unsigned long flags; spin_lock_irqsave(&cmd->t_state_lock, flags); - if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION | SCF_SENT_DELAYED_TAS)) { + if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION)) { spin_unlock_irqrestore(&cmd->t_state_lock, flags); return; } @@ -2776,6 +2783,7 @@ void transport_send_task_abort(struct se_cmd *cmd) if (cmd->data_direction == DMA_TO_DEVICE) { if (cmd->se_tfo->write_pending_status(cmd) != 0) { cmd->transport_state |= CMD_T_ABORTED; + cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS; smp_mb__after_atomic_inc(); return; } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 9c12091..db8628c 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -159,7 +159,7 @@ enum se_cmd_flags_table { SCF_SENT_CHECK_CONDITION = 0x00000800, SCF_OVERFLOW_BIT = 0x00001000, SCF_UNDERFLOW_BIT = 0x00002000, - SCF_SENT_DELAYED_TAS = 0x00004000, + SCF_SEND_DELAYED_TAS = 0x00004000, SCF_ALUA_NON_OPTIMIZED = 0x00008000, SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000, SCF_ACK_KREF = 0x00040000, -- 2.7.0