diff mbox series

[14/18] scsi: target: Don't set CMD_T_FABRIC_STOP for aborted tasks

Message ID 20230309223312.94595-15-michael.christie@oracle.com (mailing list archive)
State Superseded
Headers show
Series target: TMF and recovery fixes | expand

Commit Message

Mike Christie March 9, 2023, 10:33 p.m. UTC
We don't want to set CMD_T_FABRIC_STOP on commands with CMD_T_ABORTED
set, because we can end up with hangs where:

1. __transport_wait_for_tasks sets CMD_T_FABRIC_STOP but because
CMD_T_ABORTED is set we hit the:

        if (fabric_stop && *aborted)
                return false;

and wait in transport_generic_free_cmd's aborted wait on the free_compl.

2. transport_cmd_check_stop_to_fabric sees CMD_T_FABRIC_STOP set and
does the complete_all call on the t_transport_stop_comp and returns.

3. We are now hung because we are waiting on the free_compl which won't
happen because transport_cmd_check_stop_to_fabric completed the
transport completion and didn't do the check_stop_free call which
normally drops the refcount which is needed for the free_compl to get
waken up.

This patch has us either set the CMD_T_FABRIC_STOP bit and wait on
t_transport_stop_comp, or set the CMD_T_ABORTED and wait on
free_compl completion.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
---
 drivers/target/target_core_transport.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 3c732b1b5389..1e42fd3ac8a8 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -3245,11 +3245,14 @@  __transport_wait_for_tasks(struct se_cmd *cmd, bool fabric_stop,
 {
 	lockdep_assert_held(&cmd->t_state_lock);
 
-	if (fabric_stop)
-		cmd->transport_state |= CMD_T_FABRIC_STOP;
-
 	if (cmd->transport_state & CMD_T_ABORTED)
 		*aborted = true;
+	/*
+	 * We can be either CMD_T_FABRIC_STOP and wait below or CMD_T_ABORTED
+	 * and return early below and wait in transport_generic_free_cmd.
+	 */
+	if (fabric_stop && !*aborted)
+		cmd->transport_state |= CMD_T_FABRIC_STOP;
 
 	if (cmd->transport_state & CMD_T_TAS)
 		*tas = true;