diff options
author | andrew.vasquez@qlogic.com <andrew.vasquez@qlogic.com> | 2006-02-07 11:45:45 -0500 |
---|---|---|
committer | <jejb@mulgrave.il.steeleye.com> | 2006-02-07 11:53:56 -0500 |
commit | 387f96b4d9391bf3ce6928fb9cd90c9c7df37291 (patch) | |
tree | b2c1af3552d6cd98d67913be741f50a5d76cd9a2 /drivers/scsi | |
parent | 62288f105b3cad0b8643526d2a41b5503d0a1476 (diff) |
[PATCH] qla2xxx: Close window on race between rport removal and fcport transition.
Fcport visibility is recognized during interrupt time, but,
rport removal can only occur during a process
(sleeping)-context. Return a DID_IMM_RETRY status for
commands submitted within this window to insure I/Os do not
prematurely run-out of retries.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 495ccbc7f8cb..9b5a10ac3e25 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -366,6 +366,12 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
366 | goto qc_fail_command; | 366 | goto qc_fail_command; |
367 | } | 367 | } |
368 | 368 | ||
369 | /* Close window on fcport/rport state-transitioning. */ | ||
370 | if (!*(fc_port_t **)rport->dd_data) { | ||
371 | cmd->result = DID_IMM_RETRY << 16; | ||
372 | goto qc_fail_command; | ||
373 | } | ||
374 | |||
369 | if (atomic_read(&fcport->state) != FCS_ONLINE) { | 375 | if (atomic_read(&fcport->state) != FCS_ONLINE) { |
370 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || | 376 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || |
371 | atomic_read(&ha->loop_state) == LOOP_DEAD) { | 377 | atomic_read(&ha->loop_state) == LOOP_DEAD) { |
@@ -421,6 +427,12 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
421 | goto qc24_fail_command; | 427 | goto qc24_fail_command; |
422 | } | 428 | } |
423 | 429 | ||
430 | /* Close window on fcport/rport state-transitioning. */ | ||
431 | if (!*(fc_port_t **)rport->dd_data) { | ||
432 | cmd->result = DID_IMM_RETRY << 16; | ||
433 | goto qc24_fail_command; | ||
434 | } | ||
435 | |||
424 | if (atomic_read(&fcport->state) != FCS_ONLINE) { | 436 | if (atomic_read(&fcport->state) != FCS_ONLINE) { |
425 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || | 437 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || |
426 | atomic_read(&ha->loop_state) == LOOP_DEAD) { | 438 | atomic_read(&ha->loop_state) == LOOP_DEAD) { |
@@ -1675,11 +1687,13 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, | |||
1675 | spin_lock_irqsave(&fcport->rport_lock, flags); | 1687 | spin_lock_irqsave(&fcport->rport_lock, flags); |
1676 | fcport->drport = rport; | 1688 | fcport->drport = rport; |
1677 | fcport->rport = NULL; | 1689 | fcport->rport = NULL; |
1690 | *(fc_port_t **)rport->dd_data = NULL; | ||
1678 | spin_unlock_irqrestore(&fcport->rport_lock, flags); | 1691 | spin_unlock_irqrestore(&fcport->rport_lock, flags); |
1679 | set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); | 1692 | set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); |
1680 | } else { | 1693 | } else { |
1681 | spin_lock_irqsave(&fcport->rport_lock, flags); | 1694 | spin_lock_irqsave(&fcport->rport_lock, flags); |
1682 | fcport->rport = NULL; | 1695 | fcport->rport = NULL; |
1696 | *(fc_port_t **)rport->dd_data = NULL; | ||
1683 | spin_unlock_irqrestore(&fcport->rport_lock, flags); | 1697 | spin_unlock_irqrestore(&fcport->rport_lock, flags); |
1684 | fc_remote_port_delete(rport); | 1698 | fc_remote_port_delete(rport); |
1685 | } | 1699 | } |