@@ -109,7 +109,7 @@ static int target_check_cdb_and_preempt(struct list_head *list,
return 1;
}
-static bool __target_check_io_state(struct se_cmd *se_cmd,
+static bool __target_check_io_state(struct se_cmd *se_cmd, u32 ignore_state,
struct se_session *tmr_sess, int tas)
{
struct se_session *sess = se_cmd->se_sess;
@@ -117,19 +117,32 @@ static bool __target_check_io_state(struct se_cmd *se_cmd,
assert_spin_locked(&sess->sess_cmd_lock);
WARN_ON_ONCE(!irqs_disabled());
/*
- * If command already reached CMD_T_COMPLETE state within
- * target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown,
- * this se_cmd has been passed to fabric driver and will
- * not be aborted.
+ * For ABORT_TASK, if command already reached CMD_T_COMPLETE
+ * state within target_complete_cmd() or CMD_T_FABRIC_STOP
+ * due to shutdown, this se_cmd has been passed to fabric
+ * driver and will not be aborted.
+ *
+ * For LUN_RESET, check for CMD_T_FABRIC_STOP to determine
+ * if se_cmd is being stopped due to session shutdown and
+ * abort should be avoided. Otherwise, se_cmd->state_list
+ * will have already been removed from se_device->state_list
+ * via target_remove_from_state_list() from within
+ * transport_cmd_check_stop_to_fabric() code.
+ *
+ * Once fabric hand-off is complete and CMD_T_ACTIVE is
+ * cleared by transport_cmd_check_stop_to_fabric(), there
+ * no need to check additional transport_state when called
+ * for LUN_RESET via core_tmr_drain_state_list().
*
* Otherwise, obtain a local se_cmd->cmd_kref now for TMR
* ABORT_TASK + LUN_RESET for CMD_T_ABORTED processing as
* long as se_cmd->cmd_kref is still active unless zero.
*/
spin_lock(&se_cmd->t_state_lock);
- if (se_cmd->transport_state & (CMD_T_COMPLETE | CMD_T_FABRIC_STOP)) {
+ if (se_cmd->transport_state & (ignore_state)) {
pr_debug("Attempted to abort io tag: %llu already complete or"
- " fabric stop, skipping\n", se_cmd->tag);
+ " fabric stop 0x%08x, skipping\n", se_cmd->tag,
+ ignore_state);
spin_unlock(&se_cmd->t_state_lock);
return false;
}
@@ -175,7 +188,8 @@ void core_tmr_abort_task(
printk("ABORT_TASK: Found referenced %s task_tag: %llu\n",
se_cmd->se_tfo->get_fabric_name(), ref_tag);
- if (!__target_check_io_state(se_cmd, se_sess, 0))
+ if (!__target_check_io_state(se_cmd, CMD_T_COMPLETE|CMD_T_FABRIC_STOP,
+ se_sess, 0))
continue;
list_del_init(&se_cmd->se_cmd_list);
@@ -341,7 +355,7 @@ static void core_tmr_drain_state_list(
continue;
spin_lock(&sess->sess_cmd_lock);
- rc = __target_check_io_state(cmd, tmr_sess, tas);
+ rc = __target_check_io_state(cmd, CMD_T_FABRIC_STOP, tmr_sess, tas);
spin_unlock(&sess->sess_cmd_lock);
if (!rc)
continue;
@@ -617,8 +617,9 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
* Determine if frontend context caller is requesting the stopping of
* this command for frontend exceptions.
*/
- if (cmd->transport_state & CMD_T_STOP) {
- pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08llx\n",
+ if (cmd->transport_state & (CMD_T_ABORTED | CMD_T_STOP)) {
+
+ pr_debug("%s:%d CMD_T_ABORTED|CMD_T_STOP for ITT: 0x%08llx\n",
__func__, __LINE__, cmd->tag);
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@@ -2082,6 +2083,10 @@ static void target_complete_ok_work(struct work_struct *work)
*/
if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) {
WARN_ON(!cmd->scsi_status);
+
+ if (cmd->transport_state & CMD_T_ABORTED)
+ goto queue_out;
+
ret = transport_send_check_condition_and_sense(
cmd, 0, 1);
if (ret == -EAGAIN || ret == -ENOMEM)
@@ -2108,6 +2113,9 @@ static void target_complete_ok_work(struct work_struct *work)
return;
} else if (rc) {
+ if (cmd->transport_state & CMD_T_ABORTED)
+ goto queue_out;
+
ret = transport_send_check_condition_and_sense(cmd,
rc, 0);
if (ret == -EAGAIN || ret == -ENOMEM)
@@ -2120,6 +2128,9 @@ static void target_complete_ok_work(struct work_struct *work)
}
queue_rsp:
+ if (cmd->transport_state & CMD_T_ABORTED)
+ goto queue_out;
+
switch (cmd->data_direction) {
case DMA_FROM_DEVICE:
if (cmd->scsi_status)
@@ -2174,6 +2185,7 @@ static void target_complete_ok_work(struct work_struct *work)
break;
}
+queue_out:
transport_lun_remove_cmd(cmd);
transport_cmd_check_stop_to_fabric(cmd);
return;