]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
qla2xxx: drop cmds/tmrs arrived while session is being deleted
authorAlexei Potashnik <alexei@purestorage.com>
Tue, 14 Jul 2015 20:00:48 +0000 (16:00 -0400)
committerSasha Levin <sasha.levin@oracle.com>
Tue, 23 Feb 2016 15:04:44 +0000 (10:04 -0500)
[ Upstream commit e52a8b45b9c782937f74b701f8c656d4e5619eb5 ]

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> # v3.18+
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>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
drivers/scsi/qla2xxx/qla_target.c

index e3e4f0a142ac4cec11f624bcd5db7d84c2f50372..71cc3818fbe51b3afe134f83346b1ec5c6a790ad 100644 (file)
@@ -1447,6 +1447,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,
@@ -3739,6 +3744,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.
         */
@@ -3902,6 +3917,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);
 }
 
@@ -5533,6 +5551,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);
        }
 
@@ -5587,6 +5610,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);
        }