Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68259b5a authored by Alex Leung's avatar Alex Leung Committed by Nicholas Bellinger
Browse files

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: default avatarAlex Leung <amleung21@yahoo.com>
Cc: Alex Leung <amleung21@yahoo.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent f46d6a8a
Loading
Loading
Loading
Loading
+6 −12
Original line number Diff line number Diff line
@@ -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);
+11 −3
Original line number Diff line number Diff line
@@ -603,6 +603,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)
@@ -2784,13 +2787,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);
@@ -2804,7 +2811,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;
	}
@@ -2819,6 +2826,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;
		}
+1 −1
Original line number Diff line number Diff line
@@ -162,7 +162,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,