summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2010-03-09 14:14:51 -0600
committerGreg Kroah-Hartman <gregkh@suse.de>2010-04-26 07:47:47 -0700
commit0a5693e82c90479a012c903915fa970c7bf22593 (patch)
tree31673ab9dd0c09b1e633f0b4b34196541537d23c /drivers/scsi
parent14d209ccb3a6eb7916f1d282e586afe8fd01b1dd (diff)
downloadkernel-crypto-0a5693e82c90479a012c903915fa970c7bf22593.tar.gz
kernel-crypto-0a5693e82c90479a012c903915fa970c7bf22593.tar.xz
kernel-crypto-0a5693e82c90479a012c903915fa970c7bf22593.zip
libiscsi: Fix recovery slowdown regression
commit 4ae0a6c15efcc37e94e3f30e3533bdec03c53126 upstream. 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> Signed-off-by: James Bottomley <James.Bottomley@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@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 c28a712fd4d..e6b67f2d322 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -3027,14 +3027,15 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
session->state = ISCSI_STATE_TERMINATE;
else if (conn->stop_stage != STOP_CONN_RECOVER)
session->state = ISCSI_STATE_IN_RECOVERY;
+
+ old_stop_stage = conn->stop_stage;
+ conn->stop_stage = flag;
spin_unlock_bh(&session->lock);
del_timer_sync(&conn->transport_timer);
iscsi_suspend_tx(conn);
spin_lock_bh(&session->lock);
- old_stop_stage = conn->stop_stage;
- conn->stop_stage = flag;
conn->c_stage = ISCSI_CONN_STOPPED;
spin_unlock_bh(&session->lock);