diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2010-07-22 07:29:49 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-28 10:06:06 -0400 |
commit | c01be6dcb2b5cce4feaf48035be6395e5cd7d47c (patch) | |
tree | b3080a6410e46a6c84bb6315bd56cc9fe085d874 /drivers/scsi | |
parent | fe4f0bdeea788a8ac049c097895cb2e4044f18b1 (diff) |
[SCSI] iscsi_transport: wait on session in error handler path
wait for session to come online in eh_device_reset_handler
and eh_target_reset_handler
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: Ravi Anand <ravi.anand@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 11 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 32 |
2 files changed, 42 insertions, 1 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 821384147a41..5529b2a39741 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -2020,6 +2020,11 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
2020 | if (!ddb_entry) | 2020 | if (!ddb_entry) |
2021 | return ret; | 2021 | return ret; |
2022 | 2022 | ||
2023 | ret = iscsi_block_scsi_eh(cmd); | ||
2024 | if (ret) | ||
2025 | return ret; | ||
2026 | ret = FAILED; | ||
2027 | |||
2023 | ql4_printk(KERN_INFO, ha, | 2028 | ql4_printk(KERN_INFO, ha, |
2024 | "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no, | 2029 | "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no, |
2025 | cmd->device->channel, cmd->device->id, cmd->device->lun); | 2030 | cmd->device->channel, cmd->device->id, cmd->device->lun); |
@@ -2072,11 +2077,15 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) | |||
2072 | { | 2077 | { |
2073 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); | 2078 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); |
2074 | struct ddb_entry *ddb_entry = cmd->device->hostdata; | 2079 | struct ddb_entry *ddb_entry = cmd->device->hostdata; |
2075 | int stat; | 2080 | int stat, ret; |
2076 | 2081 | ||
2077 | if (!ddb_entry) | 2082 | if (!ddb_entry) |
2078 | return FAILED; | 2083 | return FAILED; |
2079 | 2084 | ||
2085 | ret = iscsi_block_scsi_eh(cmd); | ||
2086 | if (ret) | ||
2087 | return ret; | ||
2088 | |||
2080 | starget_printk(KERN_INFO, scsi_target(cmd->device), | 2089 | starget_printk(KERN_INFO, scsi_target(cmd->device), |
2081 | "WARM TARGET RESET ISSUED.\n"); | 2090 | "WARM TARGET RESET ISSUED.\n"); |
2082 | 2091 | ||
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index d4b96623aa59..e84026def1f4 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <scsi/scsi_transport.h> | 30 | #include <scsi/scsi_transport.h> |
31 | #include <scsi/scsi_transport_iscsi.h> | 31 | #include <scsi/scsi_transport_iscsi.h> |
32 | #include <scsi/iscsi_if.h> | 32 | #include <scsi/iscsi_if.h> |
33 | #include <scsi/scsi_cmnd.h> | ||
33 | 34 | ||
34 | #define ISCSI_SESSION_ATTRS 23 | 35 | #define ISCSI_SESSION_ATTRS 23 |
35 | #define ISCSI_CONN_ATTRS 13 | 36 | #define ISCSI_CONN_ATTRS 13 |
@@ -534,6 +535,37 @@ static void iscsi_scan_session(struct work_struct *work) | |||
534 | atomic_dec(&ihost->nr_scans); | 535 | atomic_dec(&ihost->nr_scans); |
535 | } | 536 | } |
536 | 537 | ||
538 | /** | ||
539 | * iscsi_block_scsi_eh - block scsi eh until session state has transistioned | ||
540 | * cmd: scsi cmd passed to scsi eh handler | ||
541 | * | ||
542 | * If the session is down this function will wait for the recovery | ||
543 | * timer to fire or for the session to be logged back in. If the | ||
544 | * recovery timer fires then FAST_IO_FAIL is returned. The caller | ||
545 | * should pass this error value to the scsi eh. | ||
546 | */ | ||
547 | int iscsi_block_scsi_eh(struct scsi_cmnd *cmd) | ||
548 | { | ||
549 | struct iscsi_cls_session *session = | ||
550 | starget_to_session(scsi_target(cmd->device)); | ||
551 | unsigned long flags; | ||
552 | int ret = 0; | ||
553 | |||
554 | spin_lock_irqsave(&session->lock, flags); | ||
555 | while (session->state != ISCSI_SESSION_LOGGED_IN) { | ||
556 | if (session->state == ISCSI_SESSION_FREE) { | ||
557 | ret = FAST_IO_FAIL; | ||
558 | break; | ||
559 | } | ||
560 | spin_unlock_irqrestore(&session->lock, flags); | ||
561 | msleep(1000); | ||
562 | spin_lock_irqsave(&session->lock, flags); | ||
563 | } | ||
564 | spin_unlock_irqrestore(&session->lock, flags); | ||
565 | return ret; | ||
566 | } | ||
567 | EXPORT_SYMBOL_GPL(iscsi_block_scsi_eh); | ||
568 | |||
537 | static void session_recovery_timedout(struct work_struct *work) | 569 | static void session_recovery_timedout(struct work_struct *work) |
538 | { | 570 | { |
539 | struct iscsi_cls_session *session = | 571 | struct iscsi_cls_session *session = |