diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 9c50d2d9f27c..15a2fef51e38 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1696,6 +1696,15 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) */ switch (session->state) { case ISCSI_STATE_FAILED: + /* + * cmds should fail during shutdown, if the session + * state is bad, allowing completion to happen + */ + if (unlikely(system_state != SYSTEM_RUNNING)) { + reason = FAILURE_SESSION_FAILED; + sc->result = DID_NO_CONNECT << 16; + break; + } case ISCSI_STATE_IN_RECOVERY: reason = FAILURE_SESSION_IN_RECOVERY; sc->result = DID_IMM_RETRY << 16; @@ -1979,6 +1988,19 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) if (session->state != ISCSI_STATE_LOGGED_IN) { /* + * During shutdown, if session is prematurely disconnected, + * recovery won't happen and there will be hung cmds. Not + * handling cmds would trigger EH, also bad in this case. + * Instead, handle cmd, allow completion to happen and let + * upper layer to deal with the result. + */ + if (unlikely(system_state != SYSTEM_RUNNING)) { + sc->result = DID_NO_CONNECT << 16; + ISCSI_DBG_EH(session, "sc on shutdown, handled\n"); + rc = BLK_EH_HANDLED; + goto done; + } + /* * We are probably in the middle of iscsi recovery so let * that complete and handle the error. */ @@ -2082,7 +2104,7 @@ done: task->last_timeout = jiffies; spin_unlock(&session->frwd_lock); ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? - "timer reset" : "nh"); + "timer reset" : "shutdown or nh"); return rc; } EXPORT_SYMBOL_GPL(iscsi_eh_cmd_timed_out); @@ -2722,8 +2744,10 @@ static void iscsi_host_dec_session_cnt(struct Scsi_Host *shost) * @iscsit: iscsi transport template * @shost: scsi host * @cmds_max: session can queue + * @dd_size: private driver data size, added to session allocation size * @cmd_task_size: LLD task private data size * @initial_cmdsn: initial CmdSN + * @id: target ID to add to this session * * This can be used by software iscsi_transports that allocate * a session per scsi host. @@ -2951,7 +2975,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_setup); /** * iscsi_conn_teardown - teardown iscsi connection - * cls_conn: iscsi class connection + * @cls_conn: iscsi class connection * * TODO: we may need to make this into a two step process * like scsi-mls remove + put host |