[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>

authored by andrew.vasquez@qlogic.com and committed by 387f96b4 62288f10

+14
+14
drivers/scsi/qla2xxx/qla_os.c
··· 366 goto qc_fail_command; 367 } 368 369 if (atomic_read(&fcport->state) != FCS_ONLINE) { 370 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || 371 atomic_read(&ha->loop_state) == LOOP_DEAD) { ··· 424 rval = fc_remote_port_chkready(rport); 425 if (rval) { 426 cmd->result = rval; 427 goto qc24_fail_command; 428 } 429 ··· 1687 spin_lock_irqsave(&fcport->rport_lock, flags); 1688 fcport->drport = rport; 1689 fcport->rport = NULL; 1690 spin_unlock_irqrestore(&fcport->rport_lock, flags); 1691 set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); 1692 } else { 1693 spin_lock_irqsave(&fcport->rport_lock, flags); 1694 fcport->rport = NULL; 1695 spin_unlock_irqrestore(&fcport->rport_lock, flags); 1696 fc_remote_port_delete(rport); 1697 }
··· 366 goto qc_fail_command; 367 } 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 + 375 if (atomic_read(&fcport->state) != FCS_ONLINE) { 376 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || 377 atomic_read(&ha->loop_state) == LOOP_DEAD) { ··· 418 rval = fc_remote_port_chkready(rport); 419 if (rval) { 420 cmd->result = rval; 421 + goto qc24_fail_command; 422 + } 423 + 424 + /* Close window on fcport/rport state-transitioning. */ 425 + if (!*(fc_port_t **)rport->dd_data) { 426 + cmd->result = DID_IMM_RETRY << 16; 427 goto qc24_fail_command; 428 } 429 ··· 1675 spin_lock_irqsave(&fcport->rport_lock, flags); 1676 fcport->drport = rport; 1677 fcport->rport = NULL; 1678 + *(fc_port_t **)rport->dd_data = NULL; 1679 spin_unlock_irqrestore(&fcport->rport_lock, flags); 1680 set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); 1681 } else { 1682 spin_lock_irqsave(&fcport->rport_lock, flags); 1683 fcport->rport = NULL; 1684 + *(fc_port_t **)rport->dd_data = NULL; 1685 spin_unlock_irqrestore(&fcport->rport_lock, flags); 1686 fc_remote_port_delete(rport); 1687 }