aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2010-03-09 15:14:51 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-03-27 15:02:48 -0400
commit4ae0a6c15efcc37e94e3f30e3533bdec03c53126 (patch)
treedf66736300cb0b7eb41622bb19fc57fd553caf57 /drivers/scsi
parentb72c40949b0f04728f2993a1434598d3bad094ea (diff)
[SCSI] libiscsi: Fix recovery slowdown regression
We could be failing/stopping a connection due to libiscsi starting recovery/cleanup, but the xmit path or scsi eh thread path could be dropping the connection at the same time. As a result the session->state gets set to failed instead of in recovery. We end up not blocking the session and so the replacement timeout never gets started and we only end up failing the IO when scsi_softirq_done sees that the cmd has been running for (cmd->allowed + 1) * rq->timeout secs. We used to fail the IO right away so users are seeing a long delay when using dm-multipath. This problem was added in 2.6.28. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Cc: stable@kernel.org Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libiscsi.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 685eaec53218..7688b8f83e98 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -3087,14 +3087,15 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
3087 session->state = ISCSI_STATE_TERMINATE; 3087 session->state = ISCSI_STATE_TERMINATE;
3088 else if (conn->stop_stage != STOP_CONN_RECOVER) 3088 else if (conn->stop_stage != STOP_CONN_RECOVER)
3089 session->state = ISCSI_STATE_IN_RECOVERY; 3089 session->state = ISCSI_STATE_IN_RECOVERY;
3090
3091 old_stop_stage = conn->stop_stage;
3092 conn->stop_stage = flag;
3090 spin_unlock_bh(&session->lock); 3093 spin_unlock_bh(&session->lock);
3091 3094
3092 del_timer_sync(&conn->transport_timer); 3095 del_timer_sync(&conn->transport_timer);
3093 iscsi_suspend_tx(conn); 3096 iscsi_suspend_tx(conn);
3094 3097
3095 spin_lock_bh(&session->lock); 3098 spin_lock_bh(&session->lock);
3096 old_stop_stage = conn->stop_stage;
3097 conn->stop_stage = flag;
3098 conn->c_stage = ISCSI_CONN_STOPPED; 3099 conn->c_stage = ISCSI_CONN_STOPPED;
3099 spin_unlock_bh(&session->lock); 3100 spin_unlock_bh(&session->lock);
3100 3101