Skip to content

Commit 6294172

Browse files
Rafael David Tinocogregkh
authored andcommitted
scsi: libiscsi: Allow sd_shutdown on bad transport
[ Upstream commit d754941 ] If, for any reason, userland shuts down iscsi transport interfaces before proper logouts - like when logging in to LUNs manually, without logging out on server shutdown, or when automated scripts can't umount/logout from logged LUNs - kernel will hang forever on its sd_sync_cache() logic, after issuing the SYNCHRONIZE_CACHE cmd to all still existent paths. PID: 1 TASK: ffff8801a69b8000 CPU: 1 COMMAND: "systemd-shutdow" #0 [ffff8801a69c3a30] __schedule at ffffffff8183e9ee #1 [ffff8801a69c3a80] schedule at ffffffff8183f0d5 #2 [ffff8801a69c3a98] schedule_timeout at ffffffff81842199 #3 [ffff8801a69c3b40] io_schedule_timeout at ffffffff8183e604 #4 [ffff8801a69c3b70] wait_for_completion_io_timeout at ffffffff8183fc6c khadas#5 [ffff8801a69c3bd0] blk_execute_rq at ffffffff813cfe10 khadas#6 [ffff8801a69c3c88] scsi_execute at ffffffff815c3fc7 khadas#7 [ffff8801a69c3cc8] scsi_execute_req_flags at ffffffff815c60fe khadas#8 [ffff8801a69c3d30] sd_sync_cache at ffffffff815d37d7 khadas#9 [ffff8801a69c3da8] sd_shutdown at ffffffff815d3c3c This happens because iscsi_eh_cmd_timed_out(), the transport layer timeout helper, would tell the queue timeout function (scsi_times_out) to reset the request timer over and over, until the session state is back to logged in state. Unfortunately, during server shutdown, this might never happen again. Other option would be "not to handle" the issue in the transport layer. That would trigger the error handler logic, which would also need the session state to be logged in again. Best option, for such case, is to tell upper layers that the command was handled during the transport layer error handler helper, marking it as DID_NO_CONNECT, which will allow completion and inform about the problem. After the session was marked as ISCSI_STATE_FAILED, due to the first timeout during the server shutdown phase, all subsequent cmds will fail to be queued, allowing upper logic to fail faster. Signed-off-by: Rafael David Tinoco <rafael.tinoco@canonical.com> Reviewed-by: Lee Duncan <lduncan@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent a34ee45 commit 6294172

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

drivers/scsi/libiscsi.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,15 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
16951695
*/
16961696
switch (session->state) {
16971697
case ISCSI_STATE_FAILED:
1698+
/*
1699+
* cmds should fail during shutdown, if the session
1700+
* state is bad, allowing completion to happen
1701+
*/
1702+
if (unlikely(system_state != SYSTEM_RUNNING)) {
1703+
reason = FAILURE_SESSION_FAILED;
1704+
sc->result = DID_NO_CONNECT << 16;
1705+
break;
1706+
}
16981707
case ISCSI_STATE_IN_RECOVERY:
16991708
reason = FAILURE_SESSION_IN_RECOVERY;
17001709
sc->result = DID_IMM_RETRY << 16;
@@ -1979,6 +1988,19 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
19791988
}
19801989

19811990
if (session->state != ISCSI_STATE_LOGGED_IN) {
1991+
/*
1992+
* During shutdown, if session is prematurely disconnected,
1993+
* recovery won't happen and there will be hung cmds. Not
1994+
* handling cmds would trigger EH, also bad in this case.
1995+
* Instead, handle cmd, allow completion to happen and let
1996+
* upper layer to deal with the result.
1997+
*/
1998+
if (unlikely(system_state != SYSTEM_RUNNING)) {
1999+
sc->result = DID_NO_CONNECT << 16;
2000+
ISCSI_DBG_EH(session, "sc on shutdown, handled\n");
2001+
rc = BLK_EH_HANDLED;
2002+
goto done;
2003+
}
19822004
/*
19832005
* We are probably in the middle of iscsi recovery so let
19842006
* that complete and handle the error.
@@ -2083,7 +2105,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
20832105
task->last_timeout = jiffies;
20842106
spin_unlock(&session->frwd_lock);
20852107
ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
2086-
"timer reset" : "nh");
2108+
"timer reset" : "shutdown or nh");
20872109
return rc;
20882110
}
20892111

0 commit comments

Comments
 (0)