1
0

qla2xxx: Delete session if initiator is gone from FW

1. Initiator A is logged in with fc_id(1)/loop_id(1)
2. Initiator A re-logs in with fc_id(2)/loop_id(2)
3. Part of old session deletion async logoout for 1/1 is queued
4. Initiator B logs in with fc_id(1)/loop_id(1), starts
   passing data and creates session.
5. Async logo from 3 is processed by DPC and sent to FW

Now initiator B has the session but is logged out from FW.

This condition is detected first with CTIO error 29 at which
point we should delete current session. During session
deletion we will send LOGO to initiator to force re-login.

Under rare circumstances initiator might be logged out of FW,
not have driver session, but still think it's logged in.
E.g. the above sequence plus session deletion due to re-config.
Incoming commands will fail to create local session because
initiator is not found in FW. In this case we also issue LOGO
to initiator to force him re-login.

Finally this patch fixes exchange leak when commands where
received in logged out state. In this case loop_id must be
set to FFFF when corresponding exchange is terminated. The
patch modifies exchange termination to always use FFFF,
since in certain scenarios it's impossible to tell whether
command was received in logged in or logged out state.

Signed-off-by: Alexei Potashnik <alexei@purestorage.com>
Acked-by: Quinn Tran <quinn.tran@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Alexei Potashnik
2015-12-17 14:57:01 -05:00
committed by Nicholas Bellinger
parent 6eb54715b5
commit 71cdc07964
4 changed files with 104 additions and 16 deletions

View File

@@ -909,6 +909,7 @@ struct qla_tgt_sess {
unsigned int logout_on_delete:1;
unsigned int plogi_ack_needed:1;
unsigned int keep_nport_handle:1;
unsigned int send_els_logo:1;
unsigned char logout_completed;
@@ -1120,6 +1121,14 @@ static inline uint32_t sid_to_key(const uint8_t *s_id)
return key;
}
static inline void sid_to_portid(const uint8_t *s_id, port_id_t *p)
{
memset(p, 0, sizeof(*p));
p->b.domain = s_id[0];
p->b.area = s_id[1];
p->b.al_pa = s_id[2];
}
/*
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
*/