* [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver
@ 2015-07-14 20:00 Himanshu Madhani
2015-07-14 20:00 ` [PATCH v2 1/8] qla2xxx: kill sessions/log out initiator on RSCN and port down events Himanshu Madhani
` (8 more replies)
0 siblings, 9 replies; 20+ messages in thread
From: Himanshu Madhani @ 2015-07-14 20:00 UTC (permalink / raw)
To: jbottomley
Cc: hch, giridhar.malavali, himanshu.madhani, andrew.vasquez,
linux-scsi, target-devel
Hi James,
This series is applied on top of patch series sent on June 10
[PATCH 0/9] qla2xxx: Patches for scsi "misc" branch
(http://marc.info/?l=linux-scsi&m=143395156920505&w=2)
These set of patches addresses issue with reuse of stale command found
in a customer enviorment. Here's sequence of events which could result
into this reuse of stale command which could potentially lead to data
corruption.
- Backend driver goes out of sync with front end driver due to session
management problem.
- During this time a session receives a NEW login by the same initiator.
- All the commands from previous session are not flushed before establishing
a new session/connection.
- These stale commands leaks into new session resulting into case
where they could potentially share same Exchange ID.
In such case data can cross path between old and new session when the frontend
driver/fabric driver allows a new connection to be established without backend
knowledge. To fix this problem, old session is destroyed first before creating
new session. The session destroy process would wait for all existing commands
to finish.
The Changes from v1 of this series are:
- Rebased patch series on top of v4.2.0-rc1+.
- Dropped following patches and will be sent as seperate series.
qla2xxx: Added interface to send ELS commands from driver.
qla2xxx: delete session if initiator is gone from FW
qla2xxx: wait for all conflicts before ack'ing PLOGI
Please apply these patches to scsi tree at your earliest for inclusion in the
next mainline merge window.
Thanks,
Himanshu
Alexei Potashnik (6):
qla2xxx: delay plogi/prli ack until existing sessions are deleted
qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives
qla2xxx: added sess generations to detect RSCN update races
qla2xxx: disable scsi_transport_fc registration in target mode
qla2xxx: drop cmds/tmrs arrived while session is being deleted
qla2xxx: terminate exchange when command is aborted by LIO
Roland Dreier (1):
qla2xxx: kill sessions/log out initiator on RSCN and port down events
Swapnil Nagle (1):
qla2xxx: cleanup cmd in qla workqueue before processing TMR
drivers/scsi/qla2xxx/qla_dbg.c | 6 +-
drivers/scsi/qla2xxx/qla_def.h | 12 +
drivers/scsi/qla2xxx/qla_init.c | 188 ++++++++--
drivers/scsi/qla2xxx/qla_iocb.c | 3 +
drivers/scsi/qla2xxx/qla_os.c | 11 +-
drivers/scsi/qla2xxx/qla_target.c | 714 +++++++++++++++++++++++++++++++++---
drivers/scsi/qla2xxx/qla_target.h | 69 +++-
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 23 +-
8 files changed, 906 insertions(+), 120 deletions(-)
--
1.7.7
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 1/8] qla2xxx: kill sessions/log out initiator on RSCN and port down events
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
@ 2015-07-14 20:00 ` Himanshu Madhani
2015-07-27 8:09 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 2/8] qla2xxx: cleanup cmd in qla workqueue before processing TMR Himanshu Madhani
` (7 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Himanshu Madhani @ 2015-07-14 20:00 UTC (permalink / raw)
To: jbottomley
Cc: hch, giridhar.malavali, himanshu.madhani, andrew.vasquez,
linux-scsi, target-devel
From: Roland Dreier <roland@purestorage.com>
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@vger.kernel.org>
Signed-off-by: Roland Dreier <roland@purestorage.com>
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>
---
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);
@@ -788,7 +789,7 @@ void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
if (!vha->hw->tgt.tgt_ops)
return;
- if (!tgt || (fcport->port_type != FCT_INITIATOR))
+ if (!tgt)
return;
if (tgt->tgt_stop) {
--
1.7.7
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 2/8] qla2xxx: cleanup cmd in qla workqueue before processing TMR
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
2015-07-14 20:00 ` [PATCH v2 1/8] qla2xxx: kill sessions/log out initiator on RSCN and port down events Himanshu Madhani
@ 2015-07-14 20:00 ` Himanshu Madhani
2015-07-27 8:11 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 3/8] qla2xxx: delay plogi/prli ack until existing sessions are deleted Himanshu Madhani
` (6 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Himanshu Madhani @ 2015-07-14 20:00 UTC (permalink / raw)
To: jbottomley
Cc: hch, giridhar.malavali, himanshu.madhani, andrew.vasquez,
linux-scsi, target-devel
From: Swapnil Nagle <swapnil.nagle@purestorage.com>
Since cmds go into qla_tgt_wq and TMRs don't, it's possible that TMR
like TASK_ABORT can be queued over the cmd for which it was meant.
To avoid this race, use a per-port list to keep track of cmds that
are enqueued to qla_tgt_wq but not yet processed. When a TMR arrives,
iterate through this list and remove any cmds that match the TMR.
This patch supports TASK_ABORT and LUN_RESET.
Cc: <stable@vger.kernel.org>
Signed-off-by: Swapnil Nagle <swapnil.nagle@purestorage.com>
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>
---
drivers/scsi/qla2xxx/qla_dbg.c | 2 +-
drivers/scsi/qla2xxx/qla_def.h | 5 ++
drivers/scsi/qla2xxx/qla_os.c | 3 +
drivers/scsi/qla2xxx/qla_target.c | 123 ++++++++++++++++++++++++++++++++++--
drivers/scsi/qla2xxx/qla_target.h | 12 ++++
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 8 +--
6 files changed, 140 insertions(+), 13 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index e9ae6b9..e63aa07 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 | 0xf080 | 0xf002 |
+ * | Target Mode Management | 0xf083 | 0xf002 |
* | | | 0xf046-0xf049 |
* | Target Mode Task Management | 0x1000b | |
* ----------------------------------------------------------------------
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a47374d..2c10f1f 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3600,6 +3600,11 @@ typedef struct scsi_qla_host {
uint16_t fcoe_fcf_idx;
uint8_t fcoe_vn_port_mac[6];
+ /* list of commands waiting on workqueue */
+ struct list_head qla_cmd_list;
+ struct list_head qla_sess_op_cmd_list;
+ spinlock_t cmd_list_lock;
+
uint32_t vp_abort_cnt;
struct fc_vport *fc_vport; /* holds fc_vport * for each vport */
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7c7528b..7ce395a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3764,8 +3764,11 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
INIT_LIST_HEAD(&vha->vp_fcports);
INIT_LIST_HEAD(&vha->work_list);
INIT_LIST_HEAD(&vha->list);
+ INIT_LIST_HEAD(&vha->qla_cmd_list);
+ INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list);
spin_lock_init(&vha->work_lock);
+ spin_lock_init(&vha->cmd_list_lock);
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
ql_dbg(ql_dbg_init, vha, 0x0041,
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 97b42c0..2c483cc 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1170,6 +1170,70 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha,
FCP_TMF_CMPL, true);
}
+static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag)
+{
+ struct qla_tgt_sess_op *op;
+ struct qla_tgt_cmd *cmd;
+
+ spin_lock(&vha->cmd_list_lock);
+
+ list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
+ if (tag == op->atio.u.isp24.exchange_addr) {
+ op->aborted = true;
+ spin_unlock(&vha->cmd_list_lock);
+ return 1;
+ }
+ }
+
+ list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
+ if (tag == cmd->atio.u.isp24.exchange_addr) {
+ cmd->state = QLA_TGT_STATE_ABORTED;
+ spin_unlock(&vha->cmd_list_lock);
+ return 1;
+ }
+ }
+
+ spin_unlock(&vha->cmd_list_lock);
+ return 0;
+}
+
+/* drop cmds for the given lun
+ * XXX only looks for cmds on the port through which lun reset was recieved
+ * XXX does not go through the list of other port (which may have cmds
+ * for the same lun)
+ */
+static void abort_cmds_for_lun(struct scsi_qla_host *vha,
+ uint32_t lun, uint8_t *s_id)
+{
+ struct qla_tgt_sess_op *op;
+ struct qla_tgt_cmd *cmd;
+ uint32_t key;
+
+ key = sid_to_key(s_id);
+ spin_lock(&vha->cmd_list_lock);
+ list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
+ uint32_t op_key;
+ uint32_t op_lun;
+
+ op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
+ op_lun = scsilun_to_int(
+ (struct scsi_lun *)&op->atio.u.isp24.fcp_cmnd.lun);
+ if (op_key == key && op_lun == lun)
+ op->aborted = true;
+ }
+ list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
+ uint32_t cmd_key;
+ uint32_t cmd_lun;
+
+ cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
+ cmd_lun = scsilun_to_int(
+ (struct scsi_lun *)&cmd->atio.u.isp24.fcp_cmnd.lun);
+ if (cmd_key == key && cmd_lun == lun)
+ cmd->state = QLA_TGT_STATE_ABORTED;
+ }
+ spin_unlock(&vha->cmd_list_lock);
+}
+
/* ha->hardware_lock supposed to be held on entry */
static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess)
@@ -1194,8 +1258,19 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
}
spin_unlock(&se_sess->sess_cmd_lock);
- if (!found_lun)
- return -ENOENT;
+ /* cmd not in LIO lists, look in qla list */
+ if (!found_lun) {
+ if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) {
+ /* send TASK_ABORT response immediately */
+ qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_CMPL, false);
+ return 0;
+ } else {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081,
+ "unable to find cmd in driver or LIO for tag 0x%x\n",
+ abts->exchange_addr_to_abort);
+ return -ENOENT;
+ }
+ }
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f,
"qla_target(%d): task abort (tag=%d)\n",
@@ -3270,6 +3345,13 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
if (tgt->tgt_stop)
goto out_term;
+ if (cmd->state == QLA_TGT_STATE_ABORTED) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf082,
+ "cmd with tag %u is aborted\n",
+ cmd->atio.u.isp24.exchange_addr);
+ goto out_term;
+ }
+
cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
cmd->se_cmd.tag = atio->u.isp24.exchange_addr;
cmd->unpacked_lun = scsilun_to_int(
@@ -3323,6 +3405,12 @@ out_term:
static void qlt_do_work(struct work_struct *work)
{
struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
+ scsi_qla_host_t *vha = cmd->vha;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
+ list_del(&cmd->cmd_list);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
__qlt_do_work(cmd);
}
@@ -3374,14 +3462,25 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
unsigned long flags;
uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id;
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
+ list_del(&op->cmd_list);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
+
+ if (op->aborted) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083,
+ "sess_op with tag %u is aborted\n",
+ op->atio.u.isp24.exchange_addr);
+ goto out_term;
+ }
+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022,
- "qla_target(%d): Unable to find wwn login"
- " (s_id %x:%x:%x), trying to create it manually\n",
- vha->vp_idx, s_id[0], s_id[1], s_id[2]);
+ "qla_target(%d): Unable to find wwn login"
+ " (s_id %x:%x:%x), trying to create it manually\n",
+ vha->vp_idx, s_id[0], s_id[1], s_id[2]);
if (op->atio.u.raw.entry_count > 1) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023,
- "Dropping multy entry atio %p\n", &op->atio);
+ "Dropping multy entry atio %p\n", &op->atio);
goto out_term;
}
@@ -3446,6 +3545,11 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
memcpy(&op->atio, atio, sizeof(*atio));
op->vha = vha;
+
+ spin_lock(&vha->cmd_list_lock);
+ list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list);
+ spin_unlock(&vha->cmd_list_lock);
+
INIT_WORK(&op->work, qlt_create_sess_from_atio);
queue_work(qla_tgt_wq, &op->work);
return 0;
@@ -3465,6 +3569,11 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
cmd->cmd_in_wq = 1;
cmd->cmd_flags |= BIT_0;
+
+ spin_lock(&vha->cmd_list_lock);
+ list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list);
+ spin_unlock(&vha->cmd_list_lock);
+
INIT_WORK(&cmd->work, qlt_do_work);
queue_work(qla_tgt_wq, &cmd->work);
return 0;
@@ -3478,6 +3587,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
struct scsi_qla_host *vha = sess->vha;
struct qla_hw_data *ha = vha->hw;
struct qla_tgt_mgmt_cmd *mcmd;
+ struct atio_from_isp *a = (struct atio_from_isp *)iocb;
int res;
uint8_t tmr_func;
@@ -3518,6 +3628,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002,
"qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx);
tmr_func = TMR_LUN_RESET;
+ abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id);
break;
case QLA_TGT_CLEAR_TS:
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index dfeeadf..3104335 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -874,6 +874,8 @@ struct qla_tgt_sess_op {
struct scsi_qla_host *vha;
struct atio_from_isp atio;
struct work_struct work;
+ struct list_head cmd_list;
+ bool aborted;
};
/*
@@ -1076,6 +1078,16 @@ static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
ha->host->active_mode |= MODE_INITIATOR;
}
+static inline uint32_t sid_to_key(const uint8_t *s_id)
+{
+ uint32_t key;
+
+ key = (((unsigned long)s_id[0] << 16) |
+ ((unsigned long)s_id[1] << 8) |
+ (unsigned long)s_id[2]);
+ return key;
+}
+
/*
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
*/
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 3c981d7..f0dd8b7 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -1152,9 +1152,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
return NULL;
}
- key = (((unsigned long)s_id[0] << 16) |
- ((unsigned long)s_id[1] << 8) |
- (unsigned long)s_id[2]);
+ key = sid_to_key(s_id);
pr_debug("find_sess_by_s_id: 0x%06x\n", key);
se_nacl = btree_lookup32(&lport->lport_fcport_map, key);
@@ -1189,9 +1187,7 @@ static void tcm_qla2xxx_set_sess_by_s_id(
void *slot;
int rc;
- key = (((unsigned long)s_id[0] << 16) |
- ((unsigned long)s_id[1] << 8) |
- (unsigned long)s_id[2]);
+ key = sid_to_key(s_id);
pr_debug("set_sess_by_s_id: %06x\n", key);
slot = btree_lookup32(&lport->lport_fcport_map, key);
--
1.7.7
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 3/8] qla2xxx: delay plogi/prli ack until existing sessions are deleted
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
2015-07-14 20:00 ` [PATCH v2 1/8] qla2xxx: kill sessions/log out initiator on RSCN and port down events Himanshu Madhani
2015-07-14 20:00 ` [PATCH v2 2/8] qla2xxx: cleanup cmd in qla workqueue before processing TMR Himanshu Madhani
@ 2015-07-14 20:00 ` Himanshu Madhani
2015-07-27 8:14 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 4/8] qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives Himanshu Madhani
` (5 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Himanshu Madhani @ 2015-07-14 20:00 UTC (permalink / raw)
To: jbottomley
Cc: hch, giridhar.malavali, himanshu.madhani, andrew.vasquez,
linux-scsi, target-devel
From: Alexei Potashnik <alexei@purestorage.com>
- keep qla_tgt_sess object on the session list until it's freed
- modify use of sess->deleted flag to differentiate delayed
session deletion that can be cancelled from irreversible one:
QLA_SESS_DELETION_PENDING vs QLA_SESS_DELETION_IN_PROGRESS
- during IN_PROGRESS deletion all newly arrived commands and TMRs will
be rejected, existing commands and TMRs will be terminated when
given by the core to the fabric or simply dropped if session logout
has already happened (logout terminates all existing exchanges)
- new PLOGI will initiate deletion of the following sessions
(unless deletion is already IN_PROGRESS):
- with the same port_name (with logout)
- different port_name, different loop_id but the same port_id
(with logout)
- different port_name, different port_id, but the same loop_id
(without logout)
- additionally each new PLOGI will store imm notify iocb in the
same port_name session being deleted. When deletion process
completes this iocb will be acked. Only the most recent PLOGI
iocb is stored. The older ones will be terminated when replaced.
- new PRLI will initiate deletion of the following sessions
(unless deletion is already IN_PROGRESS):
- different port_name, different port_id, but the same loop_id
(without logout)
Cc: <stable@vger.kernel.org>
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>
---
drivers/scsi/qla2xxx/qla_dbg.c | 6 +-
drivers/scsi/qla2xxx/qla_def.h | 2 +
drivers/scsi/qla2xxx/qla_init.c | 7 +-
drivers/scsi/qla2xxx/qla_iocb.c | 3 +
drivers/scsi/qla2xxx/qla_target.c | 438 ++++++++++++++++++++++++++++++++++--
drivers/scsi/qla2xxx/qla_target.h | 43 ++++-
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 +
7 files changed, 481 insertions(+), 22 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index e63aa07..05793b7 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -67,10 +67,10 @@
* | | | 0xd031-0xd0ff |
* | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe |
- * | Target Mode | 0xe079 | |
- * | Target Mode Management | 0xf083 | 0xf002 |
+ * | Target Mode | 0xe080 | |
+ * | Target Mode Management | 0xf091 | 0xf002 |
* | | | 0xf046-0xf049 |
- * | Target Mode Task Management | 0x1000b | |
+ * | Target Mode Task Management | 0x1000d | |
* ----------------------------------------------------------------------
*/
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 2c10f1f..b036f1a 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -274,6 +274,7 @@
#define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
struct req_que;
+struct qla_tgt_sess;
/*
* (sd.h is not exported, hence local inclusion)
@@ -2026,6 +2027,7 @@ typedef struct fc_port {
uint16_t port_id;
unsigned long retry_delay_timestamp;
+ struct qla_tgt_sess *tgt_session;
} fc_port_t;
#include "qla_mr.h"
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 4895a4a..14456b1 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -115,6 +115,8 @@ qla2x00_async_iocb_timeout(void *data)
QLA_LOGIO_LOGIN_RETRIED : 0;
qla2x00_post_async_login_done_work(fcport->vha, fcport,
lio->u.logio.data);
+ } else if (sp->type == SRB_LOGOUT_CMD) {
+ qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
}
}
@@ -497,7 +499,10 @@ void
qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
uint16_t *data)
{
- qla2x00_mark_device_lost(vha, fcport, 1, 0);
+ /* Don't re-login in target mode */
+ if (!fcport->tgt_session)
+ qla2x00_mark_device_lost(vha, fcport, 1, 0);
+ qlt_logo_completion_handler(fcport, data[0]);
return;
}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 42d0e44..6b23970 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1944,6 +1944,9 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags =
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
+ if (!sp->fcport->tgt_session ||
+ !sp->fcport->tgt_session->keep_nport_handle)
+ logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
logio->port_id[1] = sp->fcport->d_id.b.area;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 2c483cc..9757bc8 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -114,6 +114,10 @@ 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);
+static void qlt_send_notify_ack(struct scsi_qla_host *vha,
+ struct imm_ntfy_from_isp *ntfy,
+ uint32_t add_flags, uint16_t resp_code, int resp_code_valid,
+ uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan);
/*
* Global Variables
*/
@@ -382,14 +386,73 @@ static void qlt_free_session_done(struct work_struct *work)
struct qla_tgt *tgt = sess->tgt;
struct scsi_qla_host *vha = sess->vha;
struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
+ bool logout_started = false;
+ fc_port_t fcport;
+
+ 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",
+ __func__, sess->se_sess, sess, sess->port_name, sess->loop_id,
+ sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+ sess->logout_on_delete, sess->keep_nport_handle,
+ sess->plogi_ack_needed);
BUG_ON(!tgt);
+
+ if (sess->logout_on_delete) {
+ int rc;
+
+ memset(&fcport, 0, sizeof(fcport));
+ fcport.loop_id = sess->loop_id;
+ fcport.d_id = sess->s_id;
+ memcpy(fcport.port_name, sess->port_name, WWN_SIZE);
+ fcport.vha = vha;
+ fcport.tgt_session = sess;
+
+ rc = qla2x00_post_async_logout_work(vha, &fcport, NULL);
+ if (rc != QLA_SUCCESS)
+ ql_log(ql_log_warn, vha, 0xf085,
+ "Schedule logo failed sess %p rc %d\n",
+ sess, rc);
+ else
+ logout_started = true;
+ }
+
/*
* Release the target session for FC Nexus from fabric module code.
*/
if (sess->se_sess != NULL)
ha->tgt.tgt_ops->free_session(sess);
+ if (logout_started) {
+ bool traced = false;
+
+ while (!ACCESS_ONCE(sess->logout_completed)) {
+ if (!traced) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf086,
+ "%s: waiting for sess %p logout\n",
+ __func__, sess);
+ traced = true;
+ }
+ msleep(100);
+ }
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf087,
+ "%s: sess %p logout completed\n",
+ __func__, sess);
+ }
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+ if (sess->plogi_ack_needed)
+ qlt_send_notify_ack(vha, &sess->tm_iocb,
+ 0, 0, 0, 0, 0, 0);
+
+ list_del(&sess->sess_list_entry);
+
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001,
"Unregistration of sess %p finished\n", sess);
@@ -410,9 +473,9 @@ void qlt_unreg_sess(struct qla_tgt_sess *sess)
vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
- list_del(&sess->sess_list_entry);
- if (sess->deleted)
- list_del(&sess->del_list_entry);
+ if (!list_empty(&sess->del_list_entry))
+ list_del_init(&sess->del_list_entry);
+ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
INIT_WORK(&sess->free_work, qlt_free_session_done);
schedule_work(&sess->free_work);
@@ -490,27 +553,36 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
struct qla_tgt *tgt = sess->tgt;
uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5;
- if (sess->deleted)
- return;
+ if (sess->deleted) {
+ /* Upgrade to unconditional deletion in case it was temporary */
+ if (immediate && sess->deleted == QLA_SESS_DELETION_PENDING)
+ list_del(&sess->del_list_entry);
+ else
+ return;
+ }
ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
"Scheduling sess %p for deletion\n", sess);
- list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
- sess->deleted = 1;
- if (immediate)
+ if (immediate) {
dev_loss_tmo = 0;
+ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
+ list_add(&sess->del_list_entry, &tgt->del_sess_list);
+ } else {
+ sess->deleted = QLA_SESS_DELETION_PENDING;
+ list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
+ }
sess->expires = jiffies + dev_loss_tmo * HZ;
ql_dbg(ql_dbg_tgt, sess->vha, 0xe048,
"qla_target(%d): session for port %8phC (loop ID %d) scheduled for "
- "deletion in %u secs (expires: %lu) immed: %d\n",
+ "deletion in %u secs (expires: %lu) immed: %d, logout: %d\n",
sess->vha->vp_idx, sess->port_name, sess->loop_id, dev_loss_tmo,
- sess->expires, immediate);
+ sess->expires, immediate, sess->logout_on_delete);
if (immediate)
- schedule_delayed_work(&tgt->sess_del_work, 0);
+ mod_delayed_work(system_wq, &tgt->sess_del_work, 0);
else
schedule_delayed_work(&tgt->sess_del_work,
sess->expires - jiffies);
@@ -579,9 +651,9 @@ out_free_id_list:
/* ha->hardware_lock supposed to be held on entry */
static void qlt_undelete_sess(struct qla_tgt_sess *sess)
{
- BUG_ON(!sess->deleted);
+ BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING);
- list_del(&sess->del_list_entry);
+ list_del_init(&sess->del_list_entry);
sess->deleted = 0;
}
@@ -600,7 +672,9 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
del_list_entry);
elapsed = jiffies;
if (time_after_eq(elapsed, sess->expires)) {
- qlt_undelete_sess(sess);
+ /* No turning back */
+ list_del_init(&sess->del_list_entry);
+ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
"Timeout: sess %p about to be deleted\n",
@@ -644,6 +718,13 @@ static struct qla_tgt_sess *qlt_create_sess(
fcport->d_id.b.al_pa, fcport->d_id.b.area,
fcport->loop_id);
+ /* Cannot undelete at this point */
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ spin_unlock_irqrestore(&ha->hardware_lock,
+ flags);
+ return NULL;
+ }
+
if (sess->deleted)
qlt_undelete_sess(sess);
@@ -674,6 +755,14 @@ static struct qla_tgt_sess *qlt_create_sess(
sess->s_id = fcport->d_id;
sess->loop_id = fcport->loop_id;
sess->local = local;
+ INIT_LIST_HEAD(&sess->del_list_entry);
+
+ /* Under normal circumstances we want to logout from firmware when
+ * session eventually ends and release corresponding nport handle.
+ * In the exception cases (e.g. when new PLOGI is waiting) corresponding
+ * code will adjust these flags as necessary. */
+ sess->logout_on_delete = 1;
+ sess->keep_nport_handle = 0;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006,
"Adding sess %p to tgt %p via ->check_initiator_node_acl()\n",
@@ -751,6 +840,10 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
mutex_unlock(&vha->vha_tgt.tgt_mutex);
spin_lock_irqsave(&ha->hardware_lock, flags);
+ } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ /* Point of no return */
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ return;
} else {
kref_get(&sess->se_sess->sess_kref);
@@ -2371,6 +2464,19 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
unsigned long flags = 0;
int res;
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ if (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ cmd->state = QLA_TGT_STATE_PROCESSED;
+ if (cmd->sess->logout_completed)
+ /* no need to terminate. FW already freed exchange. */
+ qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
+ else
+ qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
memset(&prm, 0, sizeof(prm));
qlt_check_srr_debug(cmd, &xmit_type);
@@ -2537,7 +2643,8 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (qla2x00_reset_active(vha) || cmd->reset_count != ha->chip_reset) {
+ if (qla2x00_reset_active(vha) || (cmd->reset_count != ha->chip_reset) ||
+ (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)) {
/*
* Either a chip reset is active or this request was from
* previous life, just abort the processing.
@@ -2730,6 +2837,89 @@ out:
/* If hardware_lock held on entry, might drop it, then reaquire */
/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
+static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
+ struct imm_ntfy_from_isp *ntfy)
+{
+ struct nack_to_isp *nack;
+ struct qla_hw_data *ha = vha->hw;
+ request_t *pkt;
+ int ret = 0;
+
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0xe01c,
+ "Sending TERM ELS CTIO (ha=%p)\n", ha);
+
+ pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL);
+ if (pkt == NULL) {
+ ql_dbg(ql_dbg_tgt, vha, 0xe080,
+ "qla_target(%d): %s failed: unable to allocate "
+ "request packet\n", vha->vp_idx, __func__);
+ return -ENOMEM;
+ }
+
+ pkt->entry_type = NOTIFY_ACK_TYPE;
+ pkt->entry_count = 1;
+ pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
+
+ nack = (struct nack_to_isp *)pkt;
+ nack->ox_id = ntfy->ox_id;
+
+ nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
+ if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
+ nack->u.isp24.flags = ntfy->u.isp24.flags &
+ __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
+ }
+
+ /* terminate */
+ nack->u.isp24.flags |=
+ __constant_cpu_to_le16(NOTIFY_ACK_FLAGS_TERMINATE);
+
+ nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
+ nack->u.isp24.status = ntfy->u.isp24.status;
+ nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
+ nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
+ nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
+ nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
+ nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
+ nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
+
+ qla2x00_start_iocbs(vha, vha->req);
+ return ret;
+}
+
+static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
+ struct imm_ntfy_from_isp *imm, int ha_locked)
+{
+ unsigned long flags = 0;
+ int rc;
+
+ if (qlt_issue_marker(vha, ha_locked) < 0)
+ return;
+
+ if (ha_locked) {
+ rc = __qlt_send_term_imm_notif(vha, imm);
+
+#if 0 /* Todo */
+ if (rc == -ENOMEM)
+ qlt_alloc_qfull_cmd(vha, imm, 0, 0);
+#endif
+ goto done;
+ }
+
+ spin_lock_irqsave(&vha->hw->hardware_lock, flags);
+ rc = __qlt_send_term_imm_notif(vha, imm);
+
+#if 0 /* Todo */
+ if (rc == -ENOMEM)
+ qlt_alloc_qfull_cmd(vha, imm, 0, 0);
+#endif
+
+done:
+ if (!ha_locked)
+ spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+}
+
+/* If hardware_lock held on entry, might drop it, then reaquire */
+/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
struct qla_tgt_cmd *cmd,
struct atio_from_isp *atio)
@@ -3782,22 +3972,237 @@ static int qlt_abort_task(struct scsi_qla_host *vha,
return __qlt_abort_task(vha, iocb, sess);
}
+void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
+{
+ if (fcport->tgt_session) {
+ if (rc != MBS_COMMAND_COMPLETE) {
+ ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf088,
+ "%s: se_sess %p / sess %p from"
+ " port %8phC loop_id %#04x s_id %02x:%02x:%02x"
+ " LOGO failed: %#x\n",
+ __func__,
+ fcport->tgt_session->se_sess,
+ fcport->tgt_session,
+ fcport->port_name, fcport->loop_id,
+ fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa, rc);
+ }
+
+ fcport->tgt_session->logout_completed = 1;
+ }
+}
+
+static void qlt_swap_imm_ntfy_iocb(struct imm_ntfy_from_isp *a,
+ struct imm_ntfy_from_isp *b)
+{
+ struct imm_ntfy_from_isp tmp;
+ memcpy(&tmp, a, sizeof(struct imm_ntfy_from_isp));
+ memcpy(a, b, sizeof(struct imm_ntfy_from_isp));
+ memcpy(b, &tmp, sizeof(struct imm_ntfy_from_isp));
+}
+
+/*
+* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list)
+*
+* Schedules sessions with matching port_id/loop_id but different wwn for
+* deletion. Returns existing session with matching wwn if present.
+* Null otherwise.
+*/
+static struct qla_tgt_sess *
+qlt_find_sess_invalidate_other(struct qla_tgt *tgt, uint64_t wwn,
+ port_id_t port_id, uint16_t loop_id)
+{
+ struct qla_tgt_sess *sess = NULL, *other_sess;
+ uint64_t other_wwn;
+
+ list_for_each_entry(other_sess, &tgt->sess_list, sess_list_entry) {
+
+ other_wwn = wwn_to_u64(other_sess->port_name);
+
+ if (wwn == other_wwn) {
+ WARN_ON(sess);
+ sess = other_sess;
+ continue;
+ }
+
+ /* find other sess with nport_id collision */
+ if (port_id.b24 == other_sess->s_id.b24) {
+ if (loop_id != other_sess->loop_id) {
+ ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000c,
+ "Invalidating sess %p loop_id %d wwn %llx.\n",
+ other_sess, other_sess->loop_id, other_wwn);
+
+ /*
+ * logout_on_delete is set by default, but another
+ * session that has the same s_id/loop_id combo
+ * might have cleared it when requested this session
+ * deletion, so don't touch it
+ */
+ qlt_schedule_sess_for_deletion(other_sess, true);
+ } else {
+ /*
+ * Another wwn used to have our s_id/loop_id
+ * combo - kill the session, but don't log out
+ */
+ sess->logout_on_delete = 0;
+ qlt_schedule_sess_for_deletion(other_sess,
+ true);
+ }
+ continue;
+ }
+
+ /* find other sess with nport handle collision */
+ if (loop_id == other_sess->loop_id) {
+ ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000d,
+ "Invalidating sess %p loop_id %d wwn %llx.\n",
+ other_sess, other_sess->loop_id, other_wwn);
+
+ /* Same loop_id but different s_id
+ * Ok to kill and logout */
+ qlt_schedule_sess_for_deletion(other_sess, true);
+ }
+ }
+
+ return sess;
+}
+
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
struct imm_ntfy_from_isp *iocb)
{
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct qla_tgt_sess *sess = NULL;
+ uint64_t wwn;
+ port_id_t port_id;
+ uint16_t loop_id;
+ uint16_t wd3_lo;
int res = 0;
+ wwn = wwn_to_u64(iocb->u.isp24.port_name);
+
+ port_id.b.domain = iocb->u.isp24.port_id[2];
+ port_id.b.area = iocb->u.isp24.port_id[1];
+ port_id.b.al_pa = iocb->u.isp24.port_id[0];
+ port_id.b.rsvd_1 = 0;
+
+ loop_id = le16_to_cpu(iocb->u.isp24.nport_handle);
+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026,
"qla_target(%d): Port ID: 0x%3phC ELS opcode: 0x%02x\n",
vha->vp_idx, iocb->u.isp24.port_id, iocb->u.isp24.status_subcode);
+ /* res = 1 means ack at the end of thread
+ * res = 0 means ack async/later.
+ */
switch (iocb->u.isp24.status_subcode) {
case ELS_PLOGI:
- case ELS_FLOGI:
+
+ if (wwn)
+ sess = qlt_find_sess_invalidate_other(tgt, wwn,
+ port_id, loop_id);
+
+ if (!sess || IS_SW_RESV_ADDR(sess->s_id)) {
+ res = 1;
+ break;
+ }
+
+ if (sess->plogi_ack_needed) {
+ /*
+ * Initiator sent another PLOGI before last PLOGI could
+ * finish. Swap plogi iocbs and terminate old one
+ * without acking, new one will get acked when session
+ * deletion completes.
+ */
+ ql_log(ql_log_warn, sess->vha, 0xf089,
+ "sess %p received double plogi.\n", sess);
+
+ qlt_swap_imm_ntfy_iocb(iocb, &sess->tm_iocb);
+
+ qlt_send_term_imm_notif(vha, iocb, 1);
+
+ res = 0;
+ break;
+ }
+
+ res = 0;
+
+ /*
+ * Save immediate Notif IOCB for Ack when sess is done
+ * and being deleted.
+ */
+ memcpy(&sess->tm_iocb, iocb, sizeof(sess->tm_iocb));
+ sess->plogi_ack_needed = 1;
+
+ /*
+ * Under normal circumstances we want to release nport handle
+ * during LOGO process to avoid nport handle leaks inside FW.
+ * The exception is when LOGO is done while another PLOGI with
+ * the same nport handle is waiting as might be the case here.
+ * Note: there is always a possibily of a race where session
+ * deletion has already started for other reasons (e.g. ACL
+ * removal) and now PLOGI arrives:
+ * 1. if PLOGI arrived in FW after nport handle has been freed,
+ * FW must have assigned this PLOGI a new/same handle and we
+ * can proceed ACK'ing it as usual when session deletion
+ * completes.
+ * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT
+ * bit reached it, the handle has now been released. We'll
+ * get an error when we ACK this PLOGI. Nothing will be sent
+ * back to initiator. Initiator should eventually retry
+ * PLOGI and situation will correct itself.
+ */
+ sess->keep_nport_handle = ((sess->loop_id == loop_id) &&
+ (sess->s_id.b24 == port_id.b24));
+ qlt_schedule_sess_for_deletion(sess, true);
+ break;
+
case ELS_PRLI:
+ wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
+
+ if (wwn)
+ sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id,
+ loop_id);
+
+ if (sess != NULL) {
+ if (sess->deleted) {
+ /*
+ * Impatient initiator sent PRLI before last
+ * PLOGI could finish. Will force him to re-try,
+ * while last one finishes.
+ */
+ ql_log(ql_log_warn, sess->vha, 0xf090,
+ "sess %p PRLI received, before plogi ack.\n",
+ sess);
+ qlt_send_term_imm_notif(vha, iocb, 1);
+ res = 0;
+ break;
+ }
+
+ /*
+ * This shouldn't happen under normal circumstances,
+ * since we have deleted the old session during PLOGI
+ */
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf091,
+ "PRLI (loop_id %#04x) for existing sess %p (loop_id %#04x)\n",
+ sess->loop_id, sess, iocb->u.isp24.nport_handle);
+
+ sess->local = 0;
+ sess->loop_id = loop_id;
+ sess->s_id = port_id;
+
+ if (wd3_lo & BIT_7)
+ sess->conf_compl_supported = 1;
+
+ res = 1;
+ } else {
+ /* todo: else - create sess here. */
+ res = 1; /* send notify ack */
+ }
+
+ break;
+
case ELS_LOGO:
case ELS_PRLO:
res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS);
@@ -3815,6 +4220,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
break;
}
+ case ELS_FLOGI: /* should never happen */
default:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061,
"qla_target(%d): Unsupported ELS command %x "
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 3104335..165efb5 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -167,7 +167,24 @@ struct imm_ntfy_from_isp {
uint32_t srr_rel_offs;
uint16_t srr_ui;
uint16_t srr_ox_id;
- uint8_t reserved_4[19];
+ union {
+ struct {
+ uint8_t node_name[8];
+ } plogi; /* PLOGI/ADISC/PDISC */
+ struct {
+ /* PRLI word 3 bit 0-15 */
+ uint16_t wd3_lo;
+ uint8_t resv0[6];
+ } prli;
+ struct {
+ uint8_t port_id[3];
+ uint8_t resv1;
+ uint16_t nport_handle;
+ uint16_t resv2;
+ } req_els;
+ } u;
+ uint8_t port_name[8];
+ uint8_t resv3[3];
uint8_t vp_index;
uint32_t reserved_5;
uint8_t port_id[3];
@@ -234,6 +251,7 @@ struct nack_to_isp {
uint8_t reserved[2];
uint16_t ox_id;
} __packed;
+#define NOTIFY_ACK_FLAGS_TERMINATE BIT_3
#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
#define NOTIFY_ACK_SRR_FLAGS_REJECT 1
@@ -878,6 +896,13 @@ struct qla_tgt_sess_op {
bool aborted;
};
+enum qla_sess_deletion {
+ QLA_SESS_DELETION_NONE = 0,
+ QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of
+ * this one */
+ QLA_SESS_DELETION_IN_PROGRESS = 2,
+};
+
/*
* Equivilant to IT Nexus (Initiator-Target)
*/
@@ -886,8 +911,13 @@ struct qla_tgt_sess {
port_id_t s_id;
unsigned int conf_compl_supported:1;
- unsigned int deleted:1;
+ unsigned int deleted:2;
unsigned int local:1;
+ unsigned int logout_on_delete:1;
+ unsigned int plogi_ack_needed:1;
+ unsigned int keep_nport_handle:1;
+
+ unsigned char logout_completed;
struct se_session *se_sess;
struct scsi_qla_host *vha;
@@ -899,6 +929,10 @@ struct qla_tgt_sess {
uint8_t port_name[WWN_SIZE];
struct work_struct free_work;
+
+ union {
+ struct imm_ntfy_from_isp tm_iocb;
+ };
};
struct qla_tgt_cmd {
@@ -1031,6 +1065,10 @@ struct qla_tgt_srr_ctio {
struct qla_tgt_cmd *cmd;
};
+/* Check for Switch reserved address */
+#define IS_SW_RESV_ADDR(_s_id) \
+ ((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc))
+
#define QLA_TGT_XMIT_DATA 1
#define QLA_TGT_XMIT_STATUS 2
#define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA)
@@ -1124,5 +1162,6 @@ extern void qlt_stop_phase2(struct qla_tgt *);
extern irqreturn_t qla83xx_msix_atio_q(int, void *);
extern void qlt_83xx_iospace_config(struct qla_hw_data *);
extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
+extern void qlt_logo_completion_handler(fc_port_t *, int);
#endif /* __QLA_TARGET_H */
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index f0dd8b7..04238a1 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -1543,6 +1543,10 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
}
sess->conf_compl_supported = conf_compl_supported;
+
+ /* Reset logout parameters to default */
+ sess->logout_on_delete = 1;
+ sess->keep_nport_handle = 0;
}
/*
--
1.7.7
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 4/8] qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
` (2 preceding siblings ...)
2015-07-14 20:00 ` [PATCH v2 3/8] qla2xxx: delay plogi/prli ack until existing sessions are deleted Himanshu Madhani
@ 2015-07-14 20:00 ` Himanshu Madhani
2015-07-27 8:14 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 5/8] qla2xxx: added sess generations to detect RSCN update races Himanshu Madhani
` (4 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Himanshu Madhani @ 2015-07-14 20:00 UTC (permalink / raw)
To: jbottomley
Cc: hch, giridhar.malavali, himanshu.madhani, andrew.vasquez,
linux-scsi, target-devel
From: Alexei Potashnik <alexei@purestorage.com>
cancel any commands from initiator's s_id that are still waiting
on qla_tgt_wq when PLOGI arrives.
Cc: <stable@vger.kernel.org>
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>
---
drivers/scsi/qla2xxx/qla_target.c | 35 +++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 9757bc8..6c6c65c 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -4066,6 +4066,38 @@ qlt_find_sess_invalidate_other(struct qla_tgt *tgt, uint64_t wwn,
return sess;
}
+/* Abort any commands for this s_id waiting on qla_tgt_wq workqueue */
+static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
+{
+ struct qla_tgt_sess_op *op;
+ struct qla_tgt_cmd *cmd;
+ uint32_t key;
+ int count = 0;
+
+ key = (((u32)s_id->b.domain << 16) |
+ ((u32)s_id->b.area << 8) |
+ ((u32)s_id->b.al_pa));
+
+ spin_lock(&vha->cmd_list_lock);
+ list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
+ uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
+ if (op_key == key) {
+ op->aborted = true;
+ count++;
+ }
+ }
+ list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
+ uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
+ if (cmd_key == key) {
+ cmd->state = QLA_TGT_STATE_ABORTED;
+ count++;
+ }
+ }
+ spin_unlock(&vha->cmd_list_lock);
+
+ return count;
+}
+
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
@@ -4099,6 +4131,9 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
switch (iocb->u.isp24.status_subcode) {
case ELS_PLOGI:
+ /* Mark all stale commands in qla_tgt_wq for deletion */
+ abort_cmds_for_s_id(vha, &port_id);
+
if (wwn)
sess = qlt_find_sess_invalidate_other(tgt, wwn,
port_id, loop_id);
--
1.7.7
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 5/8] qla2xxx: added sess generations to detect RSCN update races
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
` (3 preceding siblings ...)
2015-07-14 20:00 ` [PATCH v2 4/8] qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives Himanshu Madhani
@ 2015-07-14 20:00 ` Himanshu Madhani
2015-07-27 8:16 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 6/8] qla2xxx: disable scsi_transport_fc registration in target mode Himanshu Madhani
` (3 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Himanshu Madhani @ 2015-07-14 20:00 UTC (permalink / raw)
To: jbottomley
Cc: hch, giridhar.malavali, himanshu.madhani, andrew.vasquez,
linux-scsi, target-devel
From: Alexei Potashnik <alexei@purestorage.com>
RSCN processing in qla2xxx driver can run in parallel with ELS/IO
processing. As such the decision to remove disappeared fc port's
session could be stale, because a new login sequence has occurred
since and created a brand new session.
Previous mechanism of dealing with this by delaying deletion request
was prone to erroneous deletions if the event that was supposed to
cancel the deletion never arrived or has been delayed in processing.
New mechanism relies on a time-like generation counter to serialize
RSCN updates relative to ELS/IO updates.
Cc: <stable@vger.kernel.org>
Signed-off-by: Alexei Potashnik <alexei@purestorage.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
drivers/scsi/qla2xxx/qla_dbg.c | 2 +-
drivers/scsi/qla2xxx/qla_def.h | 5 +++
drivers/scsi/qla2xxx/qla_init.c | 32 ++++++++++++-------
drivers/scsi/qla2xxx/qla_os.c | 5 ++-
drivers/scsi/qla2xxx/qla_target.c | 60 ++++++++++++++++++++++++++++++-------
drivers/scsi/qla2xxx/qla_target.h | 5 ++-
6 files changed, 83 insertions(+), 26 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 05793b7..8b011ae 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 | 0xe080 | |
- * | Target Mode Management | 0xf091 | 0xf002 |
+ * | Target Mode Management | 0xf096 | 0xf002 |
* | | | 0xf046-0xf049 |
* | Target Mode Task Management | 0x1000d | |
* ----------------------------------------------------------------------
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index b036f1a..4a7aadc 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3607,6 +3607,11 @@ typedef struct scsi_qla_host {
struct list_head qla_sess_op_cmd_list;
spinlock_t cmd_list_lock;
+ /* Counter to detect races between ELS and RSCN events */
+ atomic_t generation_tick;
+ /* Time when global fcport update has been scheduled */
+ int total_fcport_update_gen;
+
uint32_t vp_abort_cnt;
struct fc_vport *fc_vport; /* holds fc_vport * for each vport */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 14456b1..3f3cdbf 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2925,24 +2925,14 @@ qla2x00_rport_del(void *data)
{
fc_port_t *fcport = data;
struct fc_rport *rport;
- scsi_qla_host_t *vha = fcport->vha;
unsigned long flags;
- unsigned long vha_flags;
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
rport = fcport->drport ? fcport->drport: fcport->rport;
fcport->drport = NULL;
spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
- if (rport) {
+ if (rport)
fc_remote_port_delete(rport);
- /*
- * Release the target mode FC NEXUS in qla_target.c code
- * if target mod is enabled.
- */
- spin_lock_irqsave(&vha->hw->hardware_lock, vha_flags);
- qlt_fc_port_deleted(vha, fcport);
- spin_unlock_irqrestore(&vha->hw->hardware_lock, vha_flags);
- }
}
/**
@@ -3382,6 +3372,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
LIST_HEAD(new_fcports);
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+ int discovery_gen;
/* If FL port exists, then SNS is present */
if (IS_FWI2_CAPABLE(ha))
@@ -3452,6 +3443,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
fcport->scan_state = QLA_FCPORT_SCAN;
}
+ /* Mark the time right before querying FW for connected ports.
+ * This process is long, asynchronous and by the time it's done,
+ * collected information might not be accurate anymore. E.g.
+ * disconnected port might have re-connected and a brand new
+ * session has been created. In this case session's generation
+ * will be newer than discovery_gen. */
+ qlt_do_generation_tick(vha, &discovery_gen);
+
rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
if (rval != QLA_SUCCESS)
break;
@@ -3503,7 +3502,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
atomic_read(&fcport->state),
fcport->flags, fcport->fc4_type,
fcport->scan_state);
- qlt_fc_port_deleted(vha, fcport);
+ qlt_fc_port_deleted(vha, fcport,
+ discovery_gen);
}
}
}
@@ -4280,6 +4280,14 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
spin_unlock_irqrestore(&ha->vport_slock, flags);
qla2x00_rport_del(fcport);
+
+ /*
+ * Release the target mode FC NEXUS in
+ * qla_target.c, if target mod is enabled.
+ */
+ qlt_fc_port_deleted(vha, fcport,
+ base_vha->total_fcport_update_gen);
+
spin_lock_irqsave(&ha->vport_slock, flags);
}
}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7ce395a..be6de2a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3230,11 +3230,14 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
spin_lock_irqsave(vha->host->host_lock, flags);
fcport->drport = rport;
spin_unlock_irqrestore(vha->host->host_lock, flags);
+ qlt_do_generation_tick(vha, &base_vha->total_fcport_update_gen);
set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
qla2xxx_wake_dpc(base_vha);
} else {
+ int now;
fc_remote_port_delete(rport);
- qlt_fc_port_deleted(vha, fcport);
+ qlt_do_generation_tick(vha, &now);
+ qlt_fc_port_deleted(vha, fcport, now);
}
}
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 6c6c65c..fbfdf3e 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -127,6 +127,16 @@ static struct workqueue_struct *qla_tgt_wq;
static DEFINE_MUTEX(qla_tgt_mutex);
static LIST_HEAD(qla_tgt_glist);
+/* This API intentionally takes dest as a parameter, rather than returning
+ * int value to avoid caller forgetting to issue wmb() after the store */
+void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest)
+{
+ scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev);
+ *dest = atomic_inc_return(&base_vha->generation_tick);
+ /* memory barrier */
+ wmb();
+}
+
/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
static struct qla_tgt_sess *qlt_find_sess_by_port_name(
struct qla_tgt *tgt,
@@ -576,10 +586,12 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
sess->expires = jiffies + dev_loss_tmo * HZ;
ql_dbg(ql_dbg_tgt, sess->vha, 0xe048,
- "qla_target(%d): session for port %8phC (loop ID %d) scheduled for "
- "deletion in %u secs (expires: %lu) immed: %d, logout: %d\n",
- sess->vha->vp_idx, sess->port_name, sess->loop_id, dev_loss_tmo,
- sess->expires, immediate, sess->logout_on_delete);
+ "qla_target(%d): session for port %8phC (loop ID %d s_id %02x:%02x:%02x)"
+ " scheduled for deletion in %u secs (expires: %lu) immed: %d, logout: %d, gen: %#x\n",
+ sess->vha->vp_idx, sess->port_name, sess->loop_id,
+ sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+ dev_loss_tmo, sess->expires, immediate, sess->logout_on_delete,
+ sess->generation);
if (immediate)
mod_delayed_work(system_wq, &tgt->sess_del_work, 0);
@@ -734,6 +746,9 @@ static struct qla_tgt_sess *qlt_create_sess(
if (sess->local && !local)
sess->local = 0;
+
+ qlt_do_generation_tick(vha, &sess->generation);
+
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return sess;
@@ -795,6 +810,7 @@ static struct qla_tgt_sess *qlt_create_sess(
spin_lock_irqsave(&ha->hardware_lock, flags);
list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list);
vha->vha_tgt.qla_tgt->sess_count++;
+ qlt_do_generation_tick(vha, &sess->generation);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b,
@@ -808,7 +824,7 @@ static struct qla_tgt_sess *qlt_create_sess(
}
/*
- * Called from drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port()
+ * Called from qla2x00_reg_remote_port()
*/
void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
{
@@ -874,7 +890,12 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
-void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
+/*
+ * max_gen - specifies maximum session generation
+ * at which this deletion requestion is still valid
+ */
+void
+qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
{
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct qla_tgt_sess *sess;
@@ -893,6 +914,15 @@ void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
return;
}
+ if (max_gen - sess->generation < 0) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092,
+ "Ignoring stale deletion request for se_sess %p / sess %p"
+ " for port %8phC, req_gen %d, sess_gen %d\n",
+ sess->se_sess, sess, sess->port_name, max_gen,
+ sess->generation);
+ return;
+ }
+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess);
sess->local = 1;
@@ -3976,7 +4006,7 @@ void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
{
if (fcport->tgt_session) {
if (rc != MBS_COMMAND_COMPLETE) {
- ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf088,
+ ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf093,
"%s: se_sess %p / sess %p from"
" port %8phC loop_id %#04x s_id %02x:%02x:%02x"
" LOGO failed: %#x\n",
@@ -4105,6 +4135,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
struct imm_ntfy_from_isp *iocb)
{
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct qla_hw_data *ha = vha->hw;
struct qla_tgt_sess *sess = NULL;
uint64_t wwn;
port_id_t port_id;
@@ -4150,7 +4181,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
* without acking, new one will get acked when session
* deletion completes.
*/
- ql_log(ql_log_warn, sess->vha, 0xf089,
+ ql_log(ql_log_warn, sess->vha, 0xf094,
"sess %p received double plogi.\n", sess);
qlt_swap_imm_ntfy_iocb(iocb, &sess->tm_iocb);
@@ -4207,7 +4238,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
* PLOGI could finish. Will force him to re-try,
* while last one finishes.
*/
- ql_log(ql_log_warn, sess->vha, 0xf090,
+ ql_log(ql_log_warn, sess->vha, 0xf095,
"sess %p PRLI received, before plogi ack.\n",
sess);
qlt_send_term_imm_notif(vha, iocb, 1);
@@ -4219,7 +4250,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
* This shouldn't happen under normal circumstances,
* since we have deleted the old session during PLOGI
*/
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf091,
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf096,
"PRLI (loop_id %#04x) for existing sess %p (loop_id %#04x)\n",
sess->loop_id, sess, iocb->u.isp24.nport_handle);
@@ -4230,7 +4261,14 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
if (wd3_lo & BIT_7)
sess->conf_compl_supported = 1;
- res = 1;
+ }
+ res = 1; /* send notify ack */
+
+ /* Make session global (not used in fabric mode) */
+ if (ha->current_topology != ISP_CFG_F) {
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
} else {
/* todo: else - create sess here. */
res = 1; /* send notify ack */
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 165efb5..2ceb60f 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -919,6 +919,8 @@ struct qla_tgt_sess {
unsigned char logout_completed;
+ int generation;
+
struct se_session *se_sess;
struct scsi_qla_host *vha;
struct qla_tgt *tgt;
@@ -1086,7 +1088,7 @@ extern int qlt_lport_register(void *, u64, u64, u64,
extern void qlt_lport_deregister(struct scsi_qla_host *);
extern void qlt_unreg_sess(struct qla_tgt_sess *);
extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *);
-extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *);
+extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int);
extern int __init qlt_init(void);
extern void qlt_exit(void);
extern void qlt_update_vp_map(struct scsi_qla_host *, int);
@@ -1163,5 +1165,6 @@ extern irqreturn_t qla83xx_msix_atio_q(int, void *);
extern void qlt_83xx_iospace_config(struct qla_hw_data *);
extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
extern void qlt_logo_completion_handler(fc_port_t *, int);
+extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
#endif /* __QLA_TARGET_H */
--
1.7.7
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 6/8] qla2xxx: disable scsi_transport_fc registration in target mode
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
` (4 preceding siblings ...)
2015-07-14 20:00 ` [PATCH v2 5/8] qla2xxx: added sess generations to detect RSCN update races Himanshu Madhani
@ 2015-07-14 20:00 ` Himanshu Madhani
2015-07-27 8:17 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 7/8] qla2xxx: drop cmds/tmrs arrived while session is being deleted Himanshu Madhani
` (2 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Himanshu Madhani @ 2015-07-14 20:00 UTC (permalink / raw)
To: jbottomley
Cc: hch, giridhar.malavali, himanshu.madhani, andrew.vasquez,
linux-scsi, target-devel
From: Alexei Potashnik <alexei@purestorage.com>
There are multiple reasons for disabling this:
1. It provides no functional benefit. We pretty much only get a few more
sysfs entries for each port, but all that information is already
available from /sys/kernel/debug/target/qla-session-X
2. It already only works in private-loop mode. By disabling we'll be
getting more uniform behavior with fabric mode.
3. It creates complications for the new PLOGI handling mechanism:
scsi_transport_fc port deletion timer could race with new session
from initiator and cause logout after successful login.
Cc: <stable@vger.kernel.org>
Signed-off-by: Alexei Potashnik <alexei@purestorage.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
drivers/scsi/qla2xxx/qla_init.c | 14 +++++++++++---
drivers/scsi/qla2xxx/qla_os.c | 3 ++-
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 3f3cdbf..5ba5851 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3338,8 +3338,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
if (IS_QLAFX00(vha->hw)) {
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
- qla2x00_reg_remote_port(vha, fcport);
- return;
+ goto reg_port;
}
fcport->login_retry = 0;
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
@@ -3347,7 +3346,16 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
qla2x00_iidma_fcport(vha, fcport);
qla24xx_update_fcport_fcp_prio(vha, fcport);
- qla2x00_reg_remote_port(vha, fcport);
+
+reg_port:
+ if (qla_ini_mode_enabled(vha))
+ qla2x00_reg_remote_port(vha, fcport);
+ else {
+ /*
+ * Create target mode FC NEXUS in qla_target.c
+ */
+ qlt_fc_port_added(vha, fcport);
+ }
}
/*
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index be6de2a..8a5cac8 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3235,7 +3235,8 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
qla2xxx_wake_dpc(base_vha);
} else {
int now;
- fc_remote_port_delete(rport);
+ if (rport)
+ fc_remote_port_delete(rport);
qlt_do_generation_tick(vha, &now);
qlt_fc_port_deleted(vha, fcport, now);
}
--
1.7.7
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 7/8] qla2xxx: drop cmds/tmrs arrived while session is being deleted
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
` (5 preceding siblings ...)
2015-07-14 20:00 ` [PATCH v2 6/8] qla2xxx: disable scsi_transport_fc registration in target mode Himanshu Madhani
@ 2015-07-14 20:00 ` Himanshu Madhani
2015-07-27 8:17 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 8/8] qla2xxx: terminate exchange when command is aborted by LIO Himanshu Madhani
2015-07-24 7:38 ` [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Nicholas A. Bellinger
8 siblings, 1 reply; 20+ messages in thread
From: Himanshu Madhani @ 2015-07-14 20:00 UTC (permalink / raw)
To: jbottomley
Cc: hch, giridhar.malavali, himanshu.madhani, andrew.vasquez,
linux-scsi, target-devel
From: Alexei Potashnik <alexei@purestorage.com>
If a new initiator (different WWN) shows up on the same fcport, old
initiator's session is scheduled for deletion. But there is a small
window between it being marked with QLA_SESS_DELETION_IN_PROGRESS
and qlt_unret_sess getting called when new session's commands will
keep finding old session in the fcport map.
This patch drops cmds/tmrs if they find session in the progress of
being deleted.
Cc: <stable@vger.kernel.org>
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>
---
drivers/scsi/qla2xxx/qla_target.c | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index fbfdf3e..a120209 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1477,6 +1477,11 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
return;
}
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
+ return;
+ }
+
rc = __qlt_24xx_handle_abts(vha, abts, sess);
if (rc != 0) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054,
@@ -3774,6 +3779,16 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
queue_work(qla_tgt_wq, &op->work);
return 0;
}
+
+ /* Another WWN used to have our s_id. Our PLOGI scheduled its
+ * session deletion, but it's still in sess_del_work wq */
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ ql_dbg(ql_dbg_io, vha, 0x3061,
+ "New command while old session %p is being deleted\n",
+ sess);
+ return -EFAULT;
+ }
+
/*
* Do kref_get() before returning + dropping qla_hw_data->hardware_lock.
*/
@@ -3937,6 +3952,9 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
sizeof(struct atio_from_isp));
}
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)
+ return -EFAULT;
+
return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
}
@@ -5610,6 +5628,11 @@ static void qlt_abort_work(struct qla_tgt *tgt,
if (!sess)
goto out_term;
} else {
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ sess = NULL;
+ goto out_term;
+ }
+
kref_get(&sess->se_sess->sess_kref);
}
@@ -5664,6 +5687,11 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
if (!sess)
goto out_term;
} else {
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ sess = NULL;
+ goto out_term;
+ }
+
kref_get(&sess->se_sess->sess_kref);
}
--
1.7.7
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 8/8] qla2xxx: terminate exchange when command is aborted by LIO
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
` (6 preceding siblings ...)
2015-07-14 20:00 ` [PATCH v2 7/8] qla2xxx: drop cmds/tmrs arrived while session is being deleted Himanshu Madhani
@ 2015-07-14 20:00 ` Himanshu Madhani
2015-07-27 8:18 ` Hannes Reinecke
2015-07-24 7:38 ` [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Nicholas A. Bellinger
8 siblings, 1 reply; 20+ messages in thread
From: Himanshu Madhani @ 2015-07-14 20:00 UTC (permalink / raw)
To: jbottomley
Cc: hch, giridhar.malavali, himanshu.madhani, andrew.vasquez,
linux-scsi, target-devel
From: Alexei Potashnik <alexei@purestorage.com>
The newly introduced aborted_task TFO callback has to terminate
exchange with QLogic driver, since command is being deleted and
no status will be queued to the driver at a later point.
This patch also moves the burden of releasing one cmd refcount to
the aborted_task handler.
Changed iSCSI aborted_task logic to satisfy the above requirement.
Cc: <stable@vger.kernel.org>
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>
---
drivers/scsi/qla2xxx/qla_target.c | 35 ++++++++++++++++++-----------------
drivers/scsi/qla2xxx/qla_target.h | 9 +--------
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 11 +----------
3 files changed, 20 insertions(+), 35 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index a120209..aef9933 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1924,20 +1924,6 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
struct qla_hw_data *ha = vha->hw;
struct se_cmd *se_cmd = &cmd->se_cmd;
- if (unlikely(cmd->aborted)) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
- "qla_target(%d): terminating exchange for aborted cmd=%p (se_cmd=%p, tag=%lld)",
- vha->vp_idx, cmd, se_cmd, se_cmd->tag);
-
- cmd->state = QLA_TGT_STATE_ABORTED;
- cmd->cmd_flags |= BIT_6;
-
- qlt_send_term_exchange(vha, cmd, &cmd->atio, 0);
-
- /* !! At this point cmd could be already freed !! */
- return QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED;
- }
-
prm->cmd = cmd;
prm->tgt = tgt;
prm->rq_result = scsi_status;
@@ -2524,9 +2510,6 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
&full_req_cnt);
if (unlikely(res != 0)) {
- if (res == QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED)
- return 0;
-
return res;
}
@@ -3098,6 +3081,24 @@ static void qlt_chk_exch_leak_thresh_hold(struct scsi_qla_host *vha)
}
+void qlt_abort_cmd(struct qla_tgt_cmd *cmd)
+{
+ struct qla_tgt *tgt = cmd->tgt;
+ struct scsi_qla_host *vha = tgt->vha;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
+ "qla_target(%d): terminating exchange for aborted cmd=%p "
+ "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd,
+ se_cmd->tag);
+
+ cmd->state = QLA_TGT_STATE_ABORTED;
+ cmd->cmd_flags |= BIT_6;
+
+ qlt_send_term_exchange(vha, cmd, &cmd->atio, 0);
+}
+EXPORT_SYMBOL(qlt_abort_cmd);
+
void qlt_free_cmd(struct qla_tgt_cmd *cmd)
{
struct qla_tgt_sess *sess = cmd->sess;
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 2ceb60f..bca584a 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -808,13 +808,6 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
#define FC_TM_REJECT 4
#define FC_TM_FAILED 5
-/*
- * Error code of qlt_pre_xmit_response() meaning that cmd's exchange was
- * terminated, so no more actions is needed and success should be returned
- * to target.
- */
-#define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717
-
#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
#define pci_dma_lo32(a) (a & 0xffffffff)
#define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff)
@@ -950,7 +943,6 @@ struct qla_tgt_cmd {
unsigned int conf_compl_supported:1;
unsigned int sg_mapped:1;
unsigned int free_sg:1;
- unsigned int aborted:1; /* Needed in case of SRR */
unsigned int write_data_transferred:1;
unsigned int ctx_dsd_alloced:1;
unsigned int q_full:1;
@@ -1134,6 +1126,7 @@ static inline uint32_t sid_to_key(const uint8_t *s_id)
extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *);
extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
+extern void qlt_abort_cmd(struct qla_tgt_cmd *);
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 04238a1..ff55c8c 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -545,7 +545,6 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
cmd->cmd_flags |= BIT_4;
cmd->bufflen = se_cmd->data_length;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
- cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
cmd->sg_cnt = se_cmd->t_data_nents;
cmd->sg = se_cmd->t_data_sg;
@@ -574,7 +573,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
cmd->sg_cnt = 0;
cmd->offset = 0;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
- cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
if (cmd->cmd_flags & BIT_5) {
pr_crit("Bit_5 already set for cmd = %p.\n", cmd);
dump_stack();
@@ -639,14 +637,7 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
{
struct qla_tgt_cmd *cmd = container_of(se_cmd,
struct qla_tgt_cmd, se_cmd);
- struct scsi_qla_host *vha = cmd->vha;
- struct qla_hw_data *ha = vha->hw;
-
- if (!cmd->sg_mapped)
- return;
-
- pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
- cmd->sg_mapped = 0;
+ qlt_abort_cmd(cmd);
}
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
--
1.7.7
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
` (7 preceding siblings ...)
2015-07-14 20:00 ` [PATCH v2 8/8] qla2xxx: terminate exchange when command is aborted by LIO Himanshu Madhani
@ 2015-07-24 7:38 ` Nicholas A. Bellinger
8 siblings, 0 replies; 20+ messages in thread
From: Nicholas A. Bellinger @ 2015-07-24 7:38 UTC (permalink / raw)
To: Himanshu Madhani
Cc: jbottomley, hch, giridhar.malavali, andrew.vasquez, linux-scsi,
target-devel
On Tue, 2015-07-14 at 16:00 -0400, Himanshu Madhani wrote:
> Hi James,
>
> This series is applied on top of patch series sent on June 10
> [PATCH 0/9] qla2xxx: Patches for scsi "misc" branch
> (http://marc.info/?l=linux-scsi&m=143395156920505&w=2)
>
> These set of patches addresses issue with reuse of stale command found
> in a customer enviorment. Here's sequence of events which could result
> into this reuse of stale command which could potentially lead to data
> corruption.
> - Backend driver goes out of sync with front end driver due to session
> management problem.
> - During this time a session receives a NEW login by the same initiator.
> - All the commands from previous session are not flushed before establishing
> a new session/connection.
> - These stale commands leaks into new session resulting into case
> where they could potentially share same Exchange ID.
> In such case data can cross path between old and new session when the frontend
> driver/fabric driver allows a new connection to be established without backend
> knowledge. To fix this problem, old session is destroyed first before creating
> new session. The session destroy process would wait for all existing commands
> to finish.
>
> The Changes from v1 of this series are:
>
> - Rebased patch series on top of v4.2.0-rc1+.
> - Dropped following patches and will be sent as seperate series.
> qla2xxx: Added interface to send ELS commands from driver.
> qla2xxx: delete session if initiator is gone from FW
> qla2xxx: wait for all conflicts before ack'ing PLOGI
>
> Please apply these patches to scsi tree at your earliest for inclusion in the
> next mainline merge window.
>
> Thanks,
> Himanshu
>
> Alexei Potashnik (6):
> qla2xxx: delay plogi/prli ack until existing sessions are deleted
> qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives
> qla2xxx: added sess generations to detect RSCN update races
> qla2xxx: disable scsi_transport_fc registration in target mode
> qla2xxx: drop cmds/tmrs arrived while session is being deleted
> qla2xxx: terminate exchange when command is aborted by LIO
>
> Roland Dreier (1):
> qla2xxx: kill sessions/log out initiator on RSCN and port down events
>
> Swapnil Nagle (1):
> qla2xxx: cleanup cmd in qla workqueue before processing TMR
>
> drivers/scsi/qla2xxx/qla_dbg.c | 6 +-
> drivers/scsi/qla2xxx/qla_def.h | 12 +
> drivers/scsi/qla2xxx/qla_init.c | 188 ++++++++--
> drivers/scsi/qla2xxx/qla_iocb.c | 3 +
> drivers/scsi/qla2xxx/qla_os.c | 11 +-
> drivers/scsi/qla2xxx/qla_target.c | 714 +++++++++++++++++++++++++++++++++---
> drivers/scsi/qla2xxx/qla_target.h | 69 +++-
> drivers/scsi/qla2xxx/tcm_qla2xxx.c | 23 +-
> 8 files changed, 906 insertions(+), 120 deletions(-)
>
Thanks for re-submitting the patches that only address outstanding
qla2xxx target mode bugs.
Normally I would be apprehensive about merging this for v4.2-rc code,
given the size of the changes involved..
However, the changes are localized to qla2xxx target, are submitted by
the hardware LLD maintainer(s), contributed by an serious customer of
the code, and are all marked for CC' stable. Given these circumstances,
it doesn't make sense to wait another 6 weeks to get these real-world
bug-fixes into mainline.
That said, I'm applying this series to target-pending/master now, and
will be planning to include in the v4.2-rc fixes PULL request to Linus
sometime next week. Please let me know if the series has issues, and
should not be merged up.
As mentioned in the previous email, also please let me know which
patches in the series preceding this one need to be marked for stable
too, as they will be a stable dependency for this series.
Thank you QLogic + Pure Storage folks.
--nab
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/8] qla2xxx: kill sessions/log out initiator on RSCN and port down events
2015-07-14 20:00 ` [PATCH v2 1/8] qla2xxx: kill sessions/log out initiator on RSCN and port down events Himanshu Madhani
@ 2015-07-27 8:09 ` Hannes Reinecke
2015-07-27 18:09 ` Roland Dreier
0 siblings, 1 reply; 20+ messages in thread
From: Hannes Reinecke @ 2015-07-27 8:09 UTC (permalink / raw)
To: Himanshu Madhani, jbottomley
Cc: hch, giridhar.malavali, andrew.vasquez, linux-scsi, target-devel
On 07/14/2015 10:00 PM, Himanshu Madhani wrote:
> From: Roland Dreier <roland@purestorage.com>
>
> 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@vger.kernel.org>
> Signed-off-by: Roland Dreier <roland@purestorage.com>
> 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>
> ---
> 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@suse.de +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@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 2/8] qla2xxx: cleanup cmd in qla workqueue before processing TMR
2015-07-14 20:00 ` [PATCH v2 2/8] qla2xxx: cleanup cmd in qla workqueue before processing TMR Himanshu Madhani
@ 2015-07-27 8:11 ` Hannes Reinecke
0 siblings, 0 replies; 20+ messages in thread
From: Hannes Reinecke @ 2015-07-27 8:11 UTC (permalink / raw)
To: Himanshu Madhani, jbottomley
Cc: hch, giridhar.malavali, andrew.vasquez, linux-scsi, target-devel
On 07/14/2015 10:00 PM, Himanshu Madhani wrote:
> From: Swapnil Nagle <swapnil.nagle@purestorage.com>
>
> Since cmds go into qla_tgt_wq and TMRs don't, it's possible that TMR
> like TASK_ABORT can be queued over the cmd for which it was meant.
> To avoid this race, use a per-port list to keep track of cmds that
> are enqueued to qla_tgt_wq but not yet processed. When a TMR arrives,
> iterate through this list and remove any cmds that match the TMR.
> This patch supports TASK_ABORT and LUN_RESET.
>
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Swapnil Nagle <swapnil.nagle@purestorage.com>
> 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>
> ---
[ .. ]
> @@ -3374,14 +3462,25 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
> unsigned long flags;
> uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id;
>
> + spin_lock_irqsave(&vha->cmd_list_lock, flags);
> + list_del(&op->cmd_list);
> + spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
> +
> + if (op->aborted) {
> + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083,
> + "sess_op with tag %u is aborted\n",
> + op->atio.u.isp24.exchange_addr);
> + goto out_term;
> + }
> +
> ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022,
> - "qla_target(%d): Unable to find wwn login"
> - " (s_id %x:%x:%x), trying to create it manually\n",
> - vha->vp_idx, s_id[0], s_id[1], s_id[2]);
> + "qla_target(%d): Unable to find wwn login"
> + " (s_id %x:%x:%x), trying to create it manually\n",
> + vha->vp_idx, s_id[0], s_id[1], s_id[2]);
>
> if (op->atio.u.raw.entry_count > 1) {
> ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023,
> - "Dropping multy entry atio %p\n", &op->atio);
> + "Dropping multy entry atio %p\n", &op->atio);
> goto out_term;
> }
>
Pointless indentation change.
Other than that:
Reviewed-by: Hannes Reinecke <hare@suse.com>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +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@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 3/8] qla2xxx: delay plogi/prli ack until existing sessions are deleted
2015-07-14 20:00 ` [PATCH v2 3/8] qla2xxx: delay plogi/prli ack until existing sessions are deleted Himanshu Madhani
@ 2015-07-27 8:14 ` Hannes Reinecke
0 siblings, 0 replies; 20+ messages in thread
From: Hannes Reinecke @ 2015-07-27 8:14 UTC (permalink / raw)
To: Himanshu Madhani, jbottomley
Cc: hch, giridhar.malavali, andrew.vasquez, linux-scsi, target-devel
On 07/14/2015 10:00 PM, Himanshu Madhani wrote:
> From: Alexei Potashnik <alexei@purestorage.com>
>
> - keep qla_tgt_sess object on the session list until it's freed
>
> - modify use of sess->deleted flag to differentiate delayed
> session deletion that can be cancelled from irreversible one:
> QLA_SESS_DELETION_PENDING vs QLA_SESS_DELETION_IN_PROGRESS
>
> - during IN_PROGRESS deletion all newly arrived commands and TMRs will
> be rejected, existing commands and TMRs will be terminated when
> given by the core to the fabric or simply dropped if session logout
> has already happened (logout terminates all existing exchanges)
>
> - new PLOGI will initiate deletion of the following sessions
> (unless deletion is already IN_PROGRESS):
> - with the same port_name (with logout)
> - different port_name, different loop_id but the same port_id
> (with logout)
> - different port_name, different port_id, but the same loop_id
> (without logout)
>
> - additionally each new PLOGI will store imm notify iocb in the
> same port_name session being deleted. When deletion process
> completes this iocb will be acked. Only the most recent PLOGI
> iocb is stored. The older ones will be terminated when replaced.
>
> - new PRLI will initiate deletion of the following sessions
> (unless deletion is already IN_PROGRESS):
> - different port_name, different port_id, but the same loop_id
> (without logout)
>
> Cc: <stable@vger.kernel.org>
> 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>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +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)
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 4/8] qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives
2015-07-14 20:00 ` [PATCH v2 4/8] qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives Himanshu Madhani
@ 2015-07-27 8:14 ` Hannes Reinecke
0 siblings, 0 replies; 20+ messages in thread
From: Hannes Reinecke @ 2015-07-27 8:14 UTC (permalink / raw)
To: Himanshu Madhani, jbottomley
Cc: hch, giridhar.malavali, andrew.vasquez, linux-scsi, target-devel
On 07/14/2015 10:00 PM, Himanshu Madhani wrote:
> From: Alexei Potashnik <alexei@purestorage.com>
>
> cancel any commands from initiator's s_id that are still waiting
> on qla_tgt_wq when PLOGI arrives.
>
> Cc: <stable@vger.kernel.org>
> 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>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +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@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 5/8] qla2xxx: added sess generations to detect RSCN update races
2015-07-14 20:00 ` [PATCH v2 5/8] qla2xxx: added sess generations to detect RSCN update races Himanshu Madhani
@ 2015-07-27 8:16 ` Hannes Reinecke
0 siblings, 0 replies; 20+ messages in thread
From: Hannes Reinecke @ 2015-07-27 8:16 UTC (permalink / raw)
To: Himanshu Madhani, jbottomley
Cc: hch, giridhar.malavali, andrew.vasquez, linux-scsi, target-devel
On 07/14/2015 10:00 PM, Himanshu Madhani wrote:
> From: Alexei Potashnik <alexei@purestorage.com>
>
> RSCN processing in qla2xxx driver can run in parallel with ELS/IO
> processing. As such the decision to remove disappeared fc port's
> session could be stale, because a new login sequence has occurred
> since and created a brand new session.
>
> Previous mechanism of dealing with this by delaying deletion request
> was prone to erroneous deletions if the event that was supposed to
> cancel the deletion never arrived or has been delayed in processing.
>
> New mechanism relies on a time-like generation counter to serialize
> RSCN updates relative to ELS/IO updates.
>
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Alexei Potashnik <alexei@purestorage.com>
> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
> ---
Reviewed-by: Hannes Reinecke <hare@suse.com>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +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@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 6/8] qla2xxx: disable scsi_transport_fc registration in target mode
2015-07-14 20:00 ` [PATCH v2 6/8] qla2xxx: disable scsi_transport_fc registration in target mode Himanshu Madhani
@ 2015-07-27 8:17 ` Hannes Reinecke
0 siblings, 0 replies; 20+ messages in thread
From: Hannes Reinecke @ 2015-07-27 8:17 UTC (permalink / raw)
To: Himanshu Madhani, jbottomley
Cc: hch, giridhar.malavali, andrew.vasquez, linux-scsi, target-devel
On 07/14/2015 10:00 PM, Himanshu Madhani wrote:
> From: Alexei Potashnik <alexei@purestorage.com>
>
> There are multiple reasons for disabling this:
>
> 1. It provides no functional benefit. We pretty much only get a few more
> sysfs entries for each port, but all that information is already
> available from /sys/kernel/debug/target/qla-session-X
>
> 2. It already only works in private-loop mode. By disabling we'll be
> getting more uniform behavior with fabric mode.
>
> 3. It creates complications for the new PLOGI handling mechanism:
> scsi_transport_fc port deletion timer could race with new session
> from initiator and cause logout after successful login.
>
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Alexei Potashnik <alexei@purestorage.com>
> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
> ---
Reviewed-by: Hannes Reinecke <hare@suse.com>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +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)
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 7/8] qla2xxx: drop cmds/tmrs arrived while session is being deleted
2015-07-14 20:00 ` [PATCH v2 7/8] qla2xxx: drop cmds/tmrs arrived while session is being deleted Himanshu Madhani
@ 2015-07-27 8:17 ` Hannes Reinecke
0 siblings, 0 replies; 20+ messages in thread
From: Hannes Reinecke @ 2015-07-27 8:17 UTC (permalink / raw)
To: Himanshu Madhani, jbottomley
Cc: hch, giridhar.malavali, andrew.vasquez, linux-scsi, target-devel
On 07/14/2015 10:00 PM, Himanshu Madhani wrote:
> From: Alexei Potashnik <alexei@purestorage.com>
>
> If a new initiator (different WWN) shows up on the same fcport, old
> initiator's session is scheduled for deletion. But there is a small
> window between it being marked with QLA_SESS_DELETION_IN_PROGRESS
> and qlt_unret_sess getting called when new session's commands will
> keep finding old session in the fcport map.
>
> This patch drops cmds/tmrs if they find session in the progress of
> being deleted.
>
> Cc: <stable@vger.kernel.org>
> 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>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +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)
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 8/8] qla2xxx: terminate exchange when command is aborted by LIO
2015-07-14 20:00 ` [PATCH v2 8/8] qla2xxx: terminate exchange when command is aborted by LIO Himanshu Madhani
@ 2015-07-27 8:18 ` Hannes Reinecke
0 siblings, 0 replies; 20+ messages in thread
From: Hannes Reinecke @ 2015-07-27 8:18 UTC (permalink / raw)
To: Himanshu Madhani, jbottomley
Cc: hch, giridhar.malavali, andrew.vasquez, linux-scsi, target-devel
On 07/14/2015 10:00 PM, Himanshu Madhani wrote:
> From: Alexei Potashnik <alexei@purestorage.com>
>
> The newly introduced aborted_task TFO callback has to terminate
> exchange with QLogic driver, since command is being deleted and
> no status will be queued to the driver at a later point.
>
> This patch also moves the burden of releasing one cmd refcount to
> the aborted_task handler.
>
> Changed iSCSI aborted_task logic to satisfy the above requirement.
>
> Cc: <stable@vger.kernel.org>
> 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>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +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@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/8] qla2xxx: kill sessions/log out initiator on RSCN and port down events
2015-07-27 8:09 ` Hannes Reinecke
@ 2015-07-27 18:09 ` Roland Dreier
2015-07-28 5:54 ` Hannes Reinecke
0 siblings, 1 reply; 20+ messages in thread
From: Roland Dreier @ 2015-07-27 18:09 UTC (permalink / raw)
To: Hannes Reinecke
Cc: Himanshu Madhani, James Bottomley, Christoph Hellwig,
Giridhar Malavali, Andrew Vasquez, linux-scsi, target-devel
On Mon, Jul 27, 2015 at 1:09 AM, Hannes Reinecke <hare@suse.de> wrote:
> Hmm? What happened to the original FIXME?
> Is it not required anymore?
Not sure I follow the question. The original FIXME was "/* FIXME:
Re-enable Global event handling.. */" and this patch indeed re-enables
global event handling. I don't think it's a separate patch, it's all
part of the same work.
Unless I'm misunderstanding...
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/8] qla2xxx: kill sessions/log out initiator on RSCN and port down events
2015-07-27 18:09 ` Roland Dreier
@ 2015-07-28 5:54 ` Hannes Reinecke
0 siblings, 0 replies; 20+ messages in thread
From: Hannes Reinecke @ 2015-07-28 5:54 UTC (permalink / raw)
To: Roland Dreier
Cc: Himanshu Madhani, James Bottomley, Christoph Hellwig,
Giridhar Malavali, Andrew Vasquez, linux-scsi, target-devel
On 07/27/2015 08:09 PM, Roland Dreier wrote:
> On Mon, Jul 27, 2015 at 1:09 AM, Hannes Reinecke <hare@suse.de> wrote:
>> Hmm? What happened to the original FIXME?
>> Is it not required anymore?
>
> Not sure I follow the question. The original FIXME was "/* FIXME:
> Re-enable Global event handling.. */" and this patch indeed re-enables
> global event handling. I don't think it's a separate patch, it's all
> part of the same work.
>
> Unless I'm misunderstanding...
>
No, not really.
If the patch indeed enables global event handling everything's fine.
Wasn't just not quite obvious from the description nor the patch itself.
So:
Reviewed-by: Hannes Reinecke <hare@suse.com>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +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)
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2015-07-28 5:54 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-14 20:00 [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Himanshu Madhani
2015-07-14 20:00 ` [PATCH v2 1/8] qla2xxx: kill sessions/log out initiator on RSCN and port down events Himanshu Madhani
2015-07-27 8:09 ` Hannes Reinecke
2015-07-27 18:09 ` Roland Dreier
2015-07-28 5:54 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 2/8] qla2xxx: cleanup cmd in qla workqueue before processing TMR Himanshu Madhani
2015-07-27 8:11 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 3/8] qla2xxx: delay plogi/prli ack until existing sessions are deleted Himanshu Madhani
2015-07-27 8:14 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 4/8] qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives Himanshu Madhani
2015-07-27 8:14 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 5/8] qla2xxx: added sess generations to detect RSCN update races Himanshu Madhani
2015-07-27 8:16 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 6/8] qla2xxx: disable scsi_transport_fc registration in target mode Himanshu Madhani
2015-07-27 8:17 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 7/8] qla2xxx: drop cmds/tmrs arrived while session is being deleted Himanshu Madhani
2015-07-27 8:17 ` Hannes Reinecke
2015-07-14 20:00 ` [PATCH v2 8/8] qla2xxx: terminate exchange when command is aborted by LIO Himanshu Madhani
2015-07-27 8:18 ` Hannes Reinecke
2015-07-24 7:38 ` [PATCH v2 0/8] qla2xxx: Updates for Target Mode driver Nicholas A. Bellinger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).