scsi: target: iscsit: Fix TAS handling during conn cleanup
authorMike Christie <michael.christie@oracle.com>
Sun, 19 Mar 2023 01:56:19 +0000 (20:56 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 May 2023 14:03:19 +0000 (23:03 +0900)
[ Upstream commit cc79da306ebb2edb700c3816b90219223182ac3c ]

Fix a bug added in commit f36199355c64 ("scsi: target: iscsi: Fix cmd abort
fabric stop race").

If CMD_T_TAS is set on the se_cmd we must call iscsit_free_cmd() to do the
last put on the cmd and free it, because the connection is down and we will
not up sending the response and doing the put from the normal I/O
path.

Add a check for CMD_T_TAS in iscsit_release_commands_from_conn() so we now
detect this case and run iscsit_free_cmd().

Fixes: f36199355c64 ("scsi: target: iscsi: Fix cmd abort fabric stop race")
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Link: https://lore.kernel.org/r/20230319015620.96006-9-michael.christie@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/target/iscsi/iscsi_target.c

index 83b0071..3f7a9f7 100644 (file)
@@ -4220,9 +4220,12 @@ static void iscsit_release_commands_from_conn(struct iscsit_conn *conn)
        list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
                struct se_cmd *se_cmd = &cmd->se_cmd;
 
-               if (se_cmd->se_tfo != NULL) {
-                       spin_lock_irq(&se_cmd->t_state_lock);
-                       if (se_cmd->transport_state & CMD_T_ABORTED) {
+               if (!se_cmd->se_tfo)
+                       continue;
+
+               spin_lock_irq(&se_cmd->t_state_lock);
+               if (se_cmd->transport_state & CMD_T_ABORTED) {
+                       if (!(se_cmd->transport_state & CMD_T_TAS))
                                /*
                                 * LIO's abort path owns the cleanup for this,
                                 * so put it back on the list and let
@@ -4230,11 +4233,10 @@ static void iscsit_release_commands_from_conn(struct iscsit_conn *conn)
                                 */
                                list_move_tail(&cmd->i_conn_node,
                                               &conn->conn_cmd_list);
-                       } else {
-                               se_cmd->transport_state |= CMD_T_FABRIC_STOP;
-                       }
-                       spin_unlock_irq(&se_cmd->t_state_lock);
+               } else {
+                       se_cmd->transport_state |= CMD_T_FABRIC_STOP;
                }
+               spin_unlock_irq(&se_cmd->t_state_lock);
        }
        spin_unlock_bh(&conn->cmd_lock);