From c245707ec5f6c5ac2f83c79edd8ee7cfbbc48f55 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sun, 29 Jul 2012 14:15:30 +0000 Subject: [PATCH] qla2x00t: With NPIV initiators being destroyed and recreated, the loop_id and/or the d_id of a virtual initiator may change. The current implementation not always catches these changes, which leads to wrong virtual devices being presented to the initiators. This can lead to i.e. corruption of LUN content and multiple initiators writing to the same LUN, although the LUN's access group only contains a single port. Until a better solution is found, we schedule a session deletion for the nexus when receiving an ELS port logout message. That way SCST will re-initialize both loop_id and d_id when the initiator reconnects before the actual deletion takes place. The performance impact is minimal (few milliseconds) and currently necessary. Signed-off-by: Jens-U. Mozdzen (Merge r3583 from trunk) git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.2.x@4435 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t/qla2x00-target/qla2x00t.c | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index 89b511ee5..aab09da9f 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -4067,6 +4067,8 @@ out: static int q24_handle_els(scsi_qla_host_t *ha, notify24xx_entry_t *iocb) { int res = 1; /* send notify ack */ + struct q2t_sess *sess; + int loop_id; TRACE_ENTRY(); @@ -4082,6 +4084,37 @@ static int q24_handle_els(scsi_qla_host_t *ha, notify24xx_entry_t *iocb) case ELS_LOGO: case ELS_PRLO: res = q2t_reset(ha, iocb, Q2T_NEXUS_LOSS_SESS); + + /* The peer logged out - if we have a session, we'll drop it */ + if (IS_FWI2_CAPABLE(ha)) { + notify24xx_entry_t *n = (notify24xx_entry_t *)iocb; + loop_id = le16_to_cpu(n->nport_handle); + } else + loop_id = GET_TARGET_ID(ha, (notify_entry_t *)iocb); + + if (loop_id != 0xFFFF) { + sess = q2t_find_sess_by_loop_id(ha->tgt, loop_id); + + if (sess) { + TRACE_MGMT_DBG("qla2x00t(%ld): port logged out - scheduling session %p for deletion " + "(port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, loop_id %d)", + ha->instance, sess, + sess->port_name[0], sess->port_name[1], + sess->port_name[2], sess->port_name[3], + sess->port_name[4], sess->port_name[5], + sess->port_name[6], sess->port_name[7], + loop_id); + + q2t_schedule_sess_for_deletion( sess); + + } else { + /* no session - no action required */ + } + } else { + PRINT_ERROR("qla2x00t(%ld): invalid loop id " + "%x for ELS opcode %x", ha->instance, + loop_id, iocb->status_subcode); + } break; case ELS_PDISC: