On 07/14/2015 10:00 PM, Himanshu Madhani wrote: > From: Roland Dreier <roland@xxxxxxxxxxxxxxx> > > To fix some issues talking to ESX, this patch modifies the qla2xxx driver > so that it never logs into remote ports. This has the side effect of > getting rid of the "rports" entirely, which means we never log out of > initiators and never tear down sessions when an initiator goes away. > > This is mostly OK, except that we can run into trouble if we have > initiator A assigned FC address X:Y:Z by the fabric talking to us, and > then initiator A goes away. Some time (could be a long time) later, > initiator B comes along and also gets FC address X:Y:Z (which is > available again, because initiator A is gone). If initiator B starts > talking to us, then we'll still have the session for initiator A, and > since we look up incoming IO based on the FC address X:Y:Z, initiator B > will end up using ACLs for initiator A. > > Fix this by: > > 1. Handling RSCN events somewhat differently; instead of completely > skipping the processing of fcports, we look through the list, and if > an fcport disappears, we tell the target code the tear down the > session and tell the HBA FW to release the N_Port handle. > > 2. Handling "port down" events by flushing all of our sessions. The > firmware was already releasing the N_Port handle but we want the > target code to drop all the sessions too. > > Cc: <stable@xxxxxxxxxxxxxxx> > Signed-off-by: Roland Dreier <roland@xxxxxxxxxxxxxxx> > Signed-off-by: Alexei Potashnik <alexei@xxxxxxxxxxxxxxx> > Acked-by: Quinn Tran <quinn.tran@xxxxxxxxxx> > Signed-off-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx> > --- > drivers/scsi/qla2xxx/qla_dbg.c | 2 +- > drivers/scsi/qla2xxx/qla_init.c | 137 ++++++++++++++++++++++++++++++------- > drivers/scsi/qla2xxx/qla_target.c | 9 ++- > 3 files changed, 117 insertions(+), 31 deletions(-) > > diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c > index 0e6ee3c..e9ae6b9 100644 > --- a/drivers/scsi/qla2xxx/qla_dbg.c > +++ b/drivers/scsi/qla2xxx/qla_dbg.c > @@ -68,7 +68,7 @@ > * | | | 0xd101-0xd1fe | > * | | | 0xd214-0xd2fe | > * | Target Mode | 0xe079 | | > - * | Target Mode Management | 0xf072 | 0xf002 | > + * | Target Mode Management | 0xf080 | 0xf002 | > * | | | 0xf046-0xf049 | > * | Target Mode Task Management | 0x1000b | | > * ---------------------------------------------------------------------- > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c > index 766fdfc..4895a4a 100644 > --- a/drivers/scsi/qla2xxx/qla_init.c > +++ b/drivers/scsi/qla2xxx/qla_init.c > @@ -3462,20 +3462,43 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) > if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) > continue; > > - if (fcport->scan_state == QLA_FCPORT_SCAN && > - atomic_read(&fcport->state) == FCS_ONLINE) { > - qla2x00_mark_device_lost(vha, fcport, > - ql2xplogiabsentdevice, 0); > - if (fcport->loop_id != FC_NO_LOOP_ID && > - (fcport->flags & FCF_FCP2_DEVICE) == 0 && > - fcport->port_type != FCT_INITIATOR && > - fcport->port_type != FCT_BROADCAST) { > - ha->isp_ops->fabric_logout(vha, > - fcport->loop_id, > - fcport->d_id.b.domain, > - fcport->d_id.b.area, > - fcport->d_id.b.al_pa); > - qla2x00_clear_loop_id(fcport); > + if (fcport->scan_state == QLA_FCPORT_SCAN) { > + if (qla_ini_mode_enabled(base_vha) && > + atomic_read(&fcport->state) == FCS_ONLINE) { > + qla2x00_mark_device_lost(vha, fcport, > + ql2xplogiabsentdevice, 0); > + if (fcport->loop_id != FC_NO_LOOP_ID && > + (fcport->flags & FCF_FCP2_DEVICE) == 0 && > + fcport->port_type != FCT_INITIATOR && > + fcport->port_type != FCT_BROADCAST) { > + ha->isp_ops->fabric_logout(vha, > + fcport->loop_id, > + fcport->d_id.b.domain, > + fcport->d_id.b.area, > + fcport->d_id.b.al_pa); > + qla2x00_clear_loop_id(fcport); > + } > + } else if (!qla_ini_mode_enabled(base_vha)) { > + /* > + * In target mode, explicitly kill > + * sessions and log out of devices > + * that are gone, so that we don't > + * end up with an initiator using the > + * wrong ACL (if the fabric recycles > + * an FC address and we have a stale > + * session around) and so that we don't > + * report initiators that are no longer > + * on the fabric. > + */ > + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077, > + "port gone, logging out/killing session: " > + "%8phC state 0x%x flags 0x%x fc4_type 0x%x " > + "scan_state %d\n", > + fcport->port_name, > + atomic_read(&fcport->state), > + fcport->flags, fcport->fc4_type, > + fcport->scan_state); > + qlt_fc_port_deleted(vha, fcport); > } > } > } > @@ -3496,6 +3519,28 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) > (fcport->flags & FCF_LOGIN_NEEDED) == 0) > continue; > > + /* > + * If we're not an initiator, skip looking for devices > + * and logging in. There's no reason for us to do it, > + * and it seems to actively cause problems in target > + * mode if we race with the initiator logging into us > + * (we might get the "port ID used" status back from > + * our login command and log out the initiator, which > + * seems to cause havoc). > + */ > + if (!qla_ini_mode_enabled(base_vha)) { > + if (fcport->scan_state == QLA_FCPORT_FOUND) { > + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078, > + "port %8phC state 0x%x flags 0x%x fc4_type 0x%x " > + "scan_state %d (initiator mode disabled; skipping " > + "login)\n", fcport->port_name, > + atomic_read(&fcport->state), > + fcport->flags, fcport->fc4_type, > + fcport->scan_state); > + } > + continue; > + } > + > if (fcport->loop_id == FC_NO_LOOP_ID) { > fcport->loop_id = next_loopid; > rval = qla2x00_find_new_loop_id( > @@ -3522,16 +3567,38 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) > test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) > break; > > - /* Find a new loop ID to use. */ > - fcport->loop_id = next_loopid; > - rval = qla2x00_find_new_loop_id(base_vha, fcport); > - if (rval != QLA_SUCCESS) { > - /* Ran out of IDs to use */ > - break; > - } > + /* > + * If we're not an initiator, skip looking for devices > + * and logging in. There's no reason for us to do it, > + * and it seems to actively cause problems in target > + * mode if we race with the initiator logging into us > + * (we might get the "port ID used" status back from > + * our login command and log out the initiator, which > + * seems to cause havoc). > + */ > + if (qla_ini_mode_enabled(base_vha)) { > + /* Find a new loop ID to use. */ > + fcport->loop_id = next_loopid; > + rval = qla2x00_find_new_loop_id(base_vha, > + fcport); > + if (rval != QLA_SUCCESS) { > + /* Ran out of IDs to use */ > + break; > + } > > - /* Login and update database */ > - qla2x00_fabric_dev_login(vha, fcport, &next_loopid); > + /* Login and update database */ > + qla2x00_fabric_dev_login(vha, fcport, > + &next_loopid); > + } else { > + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079, > + "new port %8phC state 0x%x flags 0x%x fc4_type " > + "0x%x scan_state %d (initiator mode disabled; " > + "skipping login)\n", > + fcport->port_name, > + atomic_read(&fcport->state), > + fcport->flags, fcport->fc4_type, > + fcport->scan_state); > + } > > list_move_tail(&fcport->list, &vha->vp_fcports); > } > @@ -3727,11 +3794,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, > fcport->fp_speed = new_fcport->fp_speed; > > /* > - * If address the same and state FCS_ONLINE, nothing > - * changed. > + * If address the same and state FCS_ONLINE > + * (or in target mode), nothing changed. > */ > if (fcport->d_id.b24 == new_fcport->d_id.b24 && > - atomic_read(&fcport->state) == FCS_ONLINE) { > + (atomic_read(&fcport->state) == FCS_ONLINE || > + !qla_ini_mode_enabled(base_vha))) { > break; > } > > @@ -3751,6 +3819,22 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, > * Log it out if still logged in and mark it for > * relogin later. > */ > + if (!qla_ini_mode_enabled(base_vha)) { > + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080, > + "port changed FC ID, %8phC" > + " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n", > + fcport->port_name, > + fcport->d_id.b.domain, > + fcport->d_id.b.area, > + fcport->d_id.b.al_pa, > + fcport->loop_id, > + new_fcport->d_id.b.domain, > + new_fcport->d_id.b.area, > + new_fcport->d_id.b.al_pa); > + fcport->d_id.b24 = new_fcport->d_id.b24; > + break; > + } > + > fcport->d_id.b24 = new_fcport->d_id.b24; > fcport->flags |= FCF_LOGIN_NEEDED; > if (fcport->loop_id != FC_NO_LOOP_ID && > @@ -3770,6 +3854,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, > if (found) > continue; > /* If device was not in our fcports list, then add it. */ > + new_fcport->scan_state = QLA_FCPORT_FOUND; > list_add_tail(&new_fcport->list, new_fcports); > > /* Allocate a new replacement fcport. */ > diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c > index 52d8f10..97b42c0 100644 > --- a/drivers/scsi/qla2xxx/qla_target.c > +++ b/drivers/scsi/qla2xxx/qla_target.c > @@ -113,6 +113,7 @@ static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, > static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, > struct atio_from_isp *atio, uint16_t status, int qfull); > static void qlt_disable_vha(struct scsi_qla_host *vha); > +static void qlt_clear_tgt_db(struct qla_tgt *tgt); > /* > * Global Variables > */ > @@ -431,10 +432,10 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) > > loop_id = le16_to_cpu(n->u.isp24.nport_handle); > if (loop_id == 0xFFFF) { > -#if 0 /* FIXME: Re-enable Global event handling.. */ > /* Global event */ > - atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count); > - qlt_clear_tgt_db(ha->tgt.qla_tgt); > + atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count); > + qlt_clear_tgt_db(vha->vha_tgt.qla_tgt); > +#if 0 /* FIXME: do we need to choose a session here? */ > if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { > sess = list_entry(ha->tgt.qla_tgt->sess_list.next, > typeof(*sess), sess_list_entry); Hmm? What happened to the original FIXME? Is it not required anymore? I guess this warrants a separate patch. Cheers, Hannes -- Dr. Hannes Reinecke zSeries & Storage hare@xxxxxxx +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nürnberg) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html