Re: [PATCH 06/20] qla2xxx: Delete session if initiator is gone from FW

2015-12-08 Thread Hannes Reinecke
On 12/08/2015 01:48 AM, Himanshu Madhani wrote:
> From: Alexei Potashnik 
> 
> 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  when corresponding exchange is terminated. The
> patch modifies exchange termination to always use ,
> 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 
> Acked-by: Quinn Tran 
> Signed-off-by: Himanshu Madhani 
> ---
Reviewed-by: Hannes Reinecke 

Cheers,

Hannes
-- 
Dr. Hannes Reinecke   zSeries & Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 06/20] qla2xxx: Delete session if initiator is gone from FW

2015-12-07 Thread kbuild test robot
Hi Alexei,

[auto build test WARNING on target/master]
[also build test WARNING on v4.4-rc4 next-20151207]
[cannot apply to scsi/for-next]

url:
https://github.com/0day-ci/linux/commits/Himanshu-Madhani/qla2xxx-Patches-for-target-pending-branch/20151208-093328
base:   https://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git 
master
config: i386-randconfig-x007-12070758 (attached as .config)
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All warnings (new ones prefixed by >>):

   drivers/scsi/qla2xxx/qla_target.c: In function 'qlt_do_ctio_completion':
>> drivers/scsi/qla2xxx/qla_target.c:3465:20: warning: comparison of constant 
>> '41' with boolean expression is always false [-Wbool-compare]
   (logged_out == CTIO_PORT_LOGGED_OUT) ?
   ^

vim +/41 +3465 drivers/scsi/qla2xxx/qla_target.c

  3449  /* They are OK */
  3450  ql_dbg(ql_dbg_tgt_mgt, vha, 0xf058,
  3451  "qla_target(%d): CTIO with "
  3452  "status %#x received, state %x, se_cmd %p, "
  3453  "(LIP_RESET=e, ABORTED=2, TARGET_RESET=17, "
  3454  "TIMEOUT=b, INVALID_RX_ID=8)\n", 
vha->vp_idx,
  3455  status, cmd->state, se_cmd);
  3456  break;
  3457  
  3458  case CTIO_PORT_LOGGED_OUT:
  3459  case CTIO_PORT_UNAVAILABLE:
  3460  {
  3461  bool logged_out = (status & 0x);
  3462  ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059,
  3463  "qla_target(%d): CTIO with %s status %x "
  3464  "received (state %x, se_cmd %p)\n", 
vha->vp_idx,
> 3465  (logged_out == CTIO_PORT_LOGGED_OUT) ?
  3466  "PORT LOGGED OUT" : "PORT UNAVAILABLE",
  3467  status, cmd->state, se_cmd);
  3468  
  3469  if (logged_out && cmd->sess) {
  3470  /*
  3471   * Session is already logged out, but 
we need
  3472   * to notify initiator, who's not aware 
of this
  3473   */

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: Binary data


[PATCH 06/20] qla2xxx: Delete session if initiator is gone from FW

2015-12-07 Thread Himanshu Madhani
From: Alexei Potashnik 

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  when corresponding exchange is terminated. The
patch modifies exchange termination to always use ,
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 
Acked-by: Quinn Tran 
Signed-off-by: Himanshu Madhani 
---
 drivers/scsi/qla2xxx/qla_def.h|2 +
 drivers/scsi/qla2xxx/qla_os.c |1 +
 drivers/scsi/qla2xxx/qla_target.c |  108 +++--
 drivers/scsi/qla2xxx/qla_target.h |9 +++
 4 files changed, 104 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 366f65b..1050fc2 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3652,6 +3652,8 @@ typedef struct scsi_qla_host {
atomic_tgeneration_tick;
/* Time when global fcport update has been scheduled */
int total_fcport_update_gen;
+   /* List of pending LOGOs, protected by tgt_mutex */
+   struct list_headlogo_list;
 
uint32_tvp_abort_cnt;
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a63ce6e..c02cbc6 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3918,6 +3918,7 @@ struct scsi_qla_host *qla2x00_create_host(struct 
scsi_host_template *sht,
INIT_LIST_HEAD(&vha->list);
INIT_LIST_HEAD(&vha->qla_cmd_list);
INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list);
+   INIT_LIST_HEAD(&vha->logo_list);
 
spin_lock_init(&vha->work_lock);
spin_lock_init(&vha->cmd_list_lock);
diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 661124a..5ef9d4c 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -389,6 +389,52 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, 
response_t *pkt)
 
 }
 
+typedef struct {
+   /* These fields must be initialized by the caller */
+   port_id_t id;
+   /*
+* number of cmds dropped while we were waiting for
+* initiator to ack LOGO initialize to 1 if LOGO is
+* triggered by a command, otherwise, to 0
+*/
+   int cmd_count;
+
+   /* These fields are used by callee */
+   struct list_head list;
+} qlt_port_logo_t;
+
+static void
+qlt_send_first_logo(struct scsi_qla_host *vha, qlt_port_logo_t *logo)
+{
+   qlt_port_logo_t *tmp;
+   int res;
+
+   mutex_lock(&vha->vha_tgt.tgt_mutex);
+
+   list_for_each_entry(tmp, &vha->logo_list, list) {
+   if (tmp->id.b24 == logo->id.b24) {
+   tmp->cmd_count += logo->cmd_count;
+   mutex_unlock(&vha->vha_tgt.tgt_mutex);
+   return;
+   }
+   }
+
+   list_add_tail(&logo->list, &vha->logo_list);
+
+   mutex_unlock(&vha->vha_tgt.tgt_mutex);
+
+   res = qla24xx_els_dcmd_iocb(vha, ELS_DCMD_LOGO, logo->id);
+
+   mutex_lock(&vha->vha_tgt.tgt_mutex);
+   list_del(&logo->list);
+   mutex_unlock(&vha->vha_tgt.tgt_mutex);
+
+   dev_info(&vha->hw->pdev->dev,
+"Finished LOGO to %02x:%02x:%02x, dropped %d cmds, res = 
%#x\n",
+logo->id.b.domain, logo->id.b.area, logo->id.b.al_pa,
+logo->cmd_count, res);
+}
+
 static void qlt_free_session_done(struct work_struct *work)
 {
struct qla_tgt_sess *sess = container_of(work, struct qla_tgt_sess,
@@ -402,14 +448,21 @@ static void qlt_free_session_done(struct work_struct 
*work)
 
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084,
"%s: se_sess %p / sess %p from port %8phC loop_id %#04x"
-   " s_id %02x:%02x:%02x logout %d keep %d plogi %d\n",
+   " s_id %02x:%02x:%02x logout %d keep %d plogi %d els_logo %d\n",
__func__, sess->se_sess, sess, sess->port_name, ses