[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>
This commit is contained in:
parent
62288f105b
commit
387f96b4d9
@ -366,6 +366,12 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
|
|||||||
goto qc_fail_command;
|
goto qc_fail_command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Close window on fcport/rport state-transitioning. */
|
||||||
|
if (!*(fc_port_t **)rport->dd_data) {
|
||||||
|
cmd->result = DID_IMM_RETRY << 16;
|
||||||
|
goto qc_fail_command;
|
||||||
|
}
|
||||||
|
|
||||||
if (atomic_read(&fcport->state) != FCS_ONLINE) {
|
if (atomic_read(&fcport->state) != FCS_ONLINE) {
|
||||||
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
|
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
|
||||||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
|
atomic_read(&ha->loop_state) == LOOP_DEAD) {
|
||||||
@ -421,6 +427,12 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
|
|||||||
goto qc24_fail_command;
|
goto qc24_fail_command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Close window on fcport/rport state-transitioning. */
|
||||||
|
if (!*(fc_port_t **)rport->dd_data) {
|
||||||
|
cmd->result = DID_IMM_RETRY << 16;
|
||||||
|
goto qc24_fail_command;
|
||||||
|
}
|
||||||
|
|
||||||
if (atomic_read(&fcport->state) != FCS_ONLINE) {
|
if (atomic_read(&fcport->state) != FCS_ONLINE) {
|
||||||
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
|
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
|
||||||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
|
atomic_read(&ha->loop_state) == LOOP_DEAD) {
|
||||||
@ -1675,11 +1687,13 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
|
|||||||
spin_lock_irqsave(&fcport->rport_lock, flags);
|
spin_lock_irqsave(&fcport->rport_lock, flags);
|
||||||
fcport->drport = rport;
|
fcport->drport = rport;
|
||||||
fcport->rport = NULL;
|
fcport->rport = NULL;
|
||||||
|
*(fc_port_t **)rport->dd_data = NULL;
|
||||||
spin_unlock_irqrestore(&fcport->rport_lock, flags);
|
spin_unlock_irqrestore(&fcport->rport_lock, flags);
|
||||||
set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
|
set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
|
||||||
} else {
|
} else {
|
||||||
spin_lock_irqsave(&fcport->rport_lock, flags);
|
spin_lock_irqsave(&fcport->rport_lock, flags);
|
||||||
fcport->rport = NULL;
|
fcport->rport = NULL;
|
||||||
|
*(fc_port_t **)rport->dd_data = NULL;
|
||||||
spin_unlock_irqrestore(&fcport->rport_lock, flags);
|
spin_unlock_irqrestore(&fcport->rport_lock, flags);
|
||||||
fc_remote_port_delete(rport);
|
fc_remote_port_delete(rport);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user