diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2007-12-13 13:43:28 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:28:31 -0500 |
commit | bc436b278776d22eb10e7e75bf3e5257d14550a9 (patch) | |
tree | 98e3862e44333ef124becb957a0d0cd88ba24ed9 /drivers | |
parent | d8bf541e657824cb03effd726ac96e2f4dcf58a5 (diff) |
[SCSI] libiscsi: grab eh_mutex during host reset
I thought we may not need the eh mutex during host reset, but that is wrong
with the new shutdown code. When start_session_recovery sets the state to
terminate then drops the session lock. The scsi eh thread could then grab the
session lock see that we are terminating and then return failed to scsi-ml.
scsi-ml's eh then owns the command and will do whatever it wants
with it. But then the iscsi eh thread could grab the session lock
and want to complete the scsi commands that we in the LLD, but
it no longer owns them and kaboom.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/libiscsi.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index b7a2b9ad3a97..441e351b4456 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -1079,17 +1079,19 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc) | |||
1079 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); | 1079 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); |
1080 | struct iscsi_conn *conn = session->leadconn; | 1080 | struct iscsi_conn *conn = session->leadconn; |
1081 | 1081 | ||
1082 | mutex_lock(&session->eh_mutex); | ||
1082 | spin_lock_bh(&session->lock); | 1083 | spin_lock_bh(&session->lock); |
1083 | if (session->state == ISCSI_STATE_TERMINATE) { | 1084 | if (session->state == ISCSI_STATE_TERMINATE) { |
1084 | failed: | 1085 | failed: |
1085 | debug_scsi("failing host reset: session terminated " | 1086 | debug_scsi("failing host reset: session terminated " |
1086 | "[CID %d age %d]\n", conn->id, session->age); | 1087 | "[CID %d age %d]\n", conn->id, session->age); |
1087 | spin_unlock_bh(&session->lock); | 1088 | spin_unlock_bh(&session->lock); |
1089 | mutex_unlock(&session->eh_mutex); | ||
1088 | return FAILED; | 1090 | return FAILED; |
1089 | } | 1091 | } |
1090 | 1092 | ||
1091 | spin_unlock_bh(&session->lock); | 1093 | spin_unlock_bh(&session->lock); |
1092 | 1094 | mutex_unlock(&session->eh_mutex); | |
1093 | /* | 1095 | /* |
1094 | * we drop the lock here but the leadconn cannot be destoyed while | 1096 | * we drop the lock here but the leadconn cannot be destoyed while |
1095 | * we are in the scsi eh | 1097 | * we are in the scsi eh |
@@ -1104,13 +1106,14 @@ failed: | |||
1104 | if (signal_pending(current)) | 1106 | if (signal_pending(current)) |
1105 | flush_signals(current); | 1107 | flush_signals(current); |
1106 | 1108 | ||
1109 | mutex_lock(&session->eh_mutex); | ||
1107 | spin_lock_bh(&session->lock); | 1110 | spin_lock_bh(&session->lock); |
1108 | if (session->state == ISCSI_STATE_LOGGED_IN) | 1111 | if (session->state == ISCSI_STATE_LOGGED_IN) |
1109 | printk(KERN_INFO "iscsi: host reset succeeded\n"); | 1112 | printk(KERN_INFO "iscsi: host reset succeeded\n"); |
1110 | else | 1113 | else |
1111 | goto failed; | 1114 | goto failed; |
1112 | spin_unlock_bh(&session->lock); | 1115 | spin_unlock_bh(&session->lock); |
1113 | 1116 | mutex_unlock(&session->eh_mutex); | |
1114 | return SUCCESS; | 1117 | return SUCCESS; |
1115 | } | 1118 | } |
1116 | EXPORT_SYMBOL_GPL(iscsi_eh_host_reset); | 1119 | EXPORT_SYMBOL_GPL(iscsi_eh_host_reset); |