Blame SOURCES/0102-scsi-scsi-qla2xxx-Fix-kernel-crash-after-disconnecti.patch

3c6e85
From 741f33d07b43d9585bec668d21d2cbbafdf646db Mon Sep 17 00:00:00 2001
3c6e85
From: Himanshu Madhani <hmadhani@redhat.com>
3c6e85
Date: Thu, 1 Aug 2019 15:56:02 -0400
3c6e85
Subject: [PATCH 102/124] [scsi] scsi: qla2xxx: Fix kernel crash after
3c6e85
 disconnecting NVMe devices
3c6e85
3c6e85
Message-id: <20190801155618.12650-103-hmadhani@redhat.com>
3c6e85
Patchwork-id: 267891
3c6e85
O-Subject: [RHEL 7.8 e-stor PATCH 102/118] scsi: qla2xxx: Fix kernel crash after disconnecting NVMe devices
3c6e85
Bugzilla: 1729270
3c6e85
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
3c6e85
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
3c6e85
3c6e85
From: Arun Easi <aeasi@marvell.com>
3c6e85
3c6e85
Bugzilla 1729270
3c6e85
3c6e85
BUG: unable to handle kernel NULL pointer dereference at           (null)
3c6e85
IP: [<ffffffffc050d10c>] qla_nvme_unregister_remote_port+0x6c/0xf0 [qla2xxx]
3c6e85
PGD 800000084cf41067 PUD 84d288067 PMD 0
3c6e85
Oops: 0000 [#1] SMP
3c6e85
Call Trace:
3c6e85
 [<ffffffff98abcfdf>] process_one_work+0x17f/0x440
3c6e85
 [<ffffffff98abdca6>] worker_thread+0x126/0x3c0
3c6e85
 [<ffffffff98abdb80>] ? manage_workers.isra.26+0x2a0/0x2a0
3c6e85
 [<ffffffff98ac4f81>] kthread+0xd1/0xe0
3c6e85
 [<ffffffff98ac4eb0>] ? insert_kthread_work+0x40/0x40
3c6e85
 [<ffffffff9918ad37>] ret_from_fork_nospec_begin+0x21/0x21
3c6e85
 [<ffffffff98ac4eb0>] ? insert_kthread_work+0x40/0x40
3c6e85
RIP  [<ffffffffc050d10c>] qla_nvme_unregister_remote_port+0x6c/0xf0 [qla2xxx]
3c6e85
3c6e85
The crash is due to a bad entry in the nvme_rport_list. This list is not
3c6e85
protected, and when a remoteport_delete callback is called, driver
3c6e85
traverses the list and crashes.
3c6e85
3c6e85
Actually, the list could be removed and driver could traverse the main
3c6e85
fcport list instead. Fix does exactly that.
3c6e85
3c6e85
Signed-off-by: Arun Easi <aeasi@marvell.com>
3c6e85
Signed-off-by: Himanshu Madhani <hmadhani@redhat.com>
3c6e85
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
3c6e85
(cherry picked from commit 6a81533d616fe581b0d421ee6db3319eeac9486d)
3c6e85
Signed-off-by: Himanshu Madhani <hmadhani@redhat.com>
3c6e85
Signed-off-by: Jan Stancek <jstancek@redhat.com>
3c6e85
---
3c6e85
 drivers/scsi/qla2xxx/qla_def.h  |  1 -
3c6e85
 drivers/scsi/qla2xxx/qla_nvme.c | 37 ++++++++++---------------------------
3c6e85
 drivers/scsi/qla2xxx/qla_nvme.h |  1 -
3c6e85
 drivers/scsi/qla2xxx/qla_os.c   |  1 -
3c6e85
 4 files changed, 10 insertions(+), 30 deletions(-)
3c6e85
3c6e85
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
3c6e85
index e5e1081501a9..7d07c6e65eed 100644
3c6e85
--- a/drivers/scsi/qla2xxx/qla_def.h
3c6e85
+++ b/drivers/scsi/qla2xxx/qla_def.h
3c6e85
@@ -4411,7 +4411,6 @@ typedef struct scsi_qla_host {
3c6e85
 
3c6e85
 	struct		nvme_fc_local_port *nvme_local_port;
3c6e85
 	struct completion nvme_del_done;
3c6e85
-	struct list_head nvme_rport_list;
3c6e85
 
3c6e85
 	uint16_t	fcoe_vlan_id;
3c6e85
 	uint16_t	fcoe_fcf_idx;
3c6e85
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
3c6e85
index dea081c27182..494082a6f8ed 100644
3c6e85
--- a/drivers/scsi/qla2xxx/qla_nvme.c
3c6e85
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
3c6e85
@@ -74,7 +74,6 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport)
3c6e85
 
3c6e85
 	rport = fcport->nvme_remote_port->private;
3c6e85
 	rport->fcport = fcport;
3c6e85
-	list_add_tail(&rport->list, &vha->nvme_rport_list);
3c6e85
 
3c6e85
 	fcport->nvme_flag |= NVME_FLAG_REGISTERED;
3c6e85
 	return 0;
3c6e85
@@ -559,19 +558,12 @@ static void qla_nvme_localport_delete(struct nvme_fc_local_port *lport)
3c6e85
 static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport)
3c6e85
 {
3c6e85
 	fc_port_t *fcport;
3c6e85
-	struct qla_nvme_rport *qla_rport = rport->private, *trport;
3c6e85
+	struct qla_nvme_rport *qla_rport = rport->private;
3c6e85
 
3c6e85
 	fcport = qla_rport->fcport;
3c6e85
 	fcport->nvme_remote_port = NULL;
3c6e85
 	fcport->nvme_flag &= ~NVME_FLAG_REGISTERED;
3c6e85
 
3c6e85
-	list_for_each_entry_safe(qla_rport, trport,
3c6e85
-	    &fcport->vha->nvme_rport_list, list) {
3c6e85
-		if (qla_rport->fcport == fcport) {
3c6e85
-			list_del(&qla_rport->list);
3c6e85
-			break;
3c6e85
-		}
3c6e85
-	}
3c6e85
 	complete(&fcport->nvme_del_done);
3c6e85
 
3c6e85
 	if (!test_bit(UNLOADING, &fcport->vha->dpc_flags)) {
3c6e85
@@ -608,7 +600,7 @@ static void qla_nvme_unregister_remote_port(struct work_struct *work)
3c6e85
 {
3c6e85
 	struct fc_port *fcport = container_of(work, struct fc_port,
3c6e85
 	    nvme_del_work);
3c6e85
-	struct qla_nvme_rport *qla_rport, *trport;
3c6e85
+	int ret;
3c6e85
 
3c6e85
 	if (!IS_ENABLED(CONFIG_NVME_FC))
3c6e85
 		return;
3c6e85
@@ -616,23 +608,14 @@ static void qla_nvme_unregister_remote_port(struct work_struct *work)
3c6e85
 	ql_log(ql_log_warn, NULL, 0x2112,
3c6e85
 	    "%s: unregister remoteport on %p\n",__func__, fcport);
3c6e85
 
3c6e85
-	list_for_each_entry_safe(qla_rport, trport,
3c6e85
-	    &fcport->vha->nvme_rport_list, list) {
3c6e85
-		if (qla_rport->fcport == fcport) {
3c6e85
-			ql_log(ql_log_info, fcport->vha, 0x2113,
3c6e85
-			    "%s: fcport=%p\n", __func__, fcport);
3c6e85
-			nvme_fc_set_remoteport_devloss
3c6e85
-				(fcport->nvme_remote_port, 0);
3c6e85
-			init_completion(&fcport->nvme_del_done);
3c6e85
-			if (nvme_fc_unregister_remoteport
3c6e85
-			    (fcport->nvme_remote_port))
3c6e85
-				ql_log(ql_log_info, fcport->vha, 0x2114,
3c6e85
-				    "%s: Failed to unregister nvme_remote_port\n",
3c6e85
-				    __func__);
3c6e85
-			wait_for_completion(&fcport->nvme_del_done);
3c6e85
-			break;
3c6e85
-		}
3c6e85
-	}
3c6e85
+	nvme_fc_set_remoteport_devloss(fcport->nvme_remote_port, 0);
3c6e85
+	init_completion(&fcport->nvme_del_done);
3c6e85
+	ret = nvme_fc_unregister_remoteport(fcport->nvme_remote_port);
3c6e85
+	if (ret)
3c6e85
+		ql_log(ql_log_info, fcport->vha, 0x2114,
3c6e85
+			"%s: Failed to unregister nvme_remote_port (%d)\n",
3c6e85
+			    __func__, ret);
3c6e85
+	wait_for_completion(&fcport->nvme_del_done);
3c6e85
 }
3c6e85
 
3c6e85
 void qla_nvme_delete(struct scsi_qla_host *vha)
3c6e85
diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h
3c6e85
index 0db04f0a4d5d..a48f9e7a3567 100644
3c6e85
--- a/drivers/scsi/qla2xxx/qla_nvme.h
3c6e85
+++ b/drivers/scsi/qla2xxx/qla_nvme.h
3c6e85
@@ -36,7 +36,6 @@ struct nvme_private {
3c6e85
 };
3c6e85
 
3c6e85
 struct qla_nvme_rport {
3c6e85
-	struct list_head list;
3c6e85
 	struct fc_port *fcport;
3c6e85
 };
3c6e85
 
3c6e85
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
3c6e85
index f3200e25d1e7..5009c5e4b276 100644
3c6e85
--- a/drivers/scsi/qla2xxx/qla_os.c
3c6e85
+++ b/drivers/scsi/qla2xxx/qla_os.c
3c6e85
@@ -4925,7 +4925,6 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
3c6e85
 	INIT_LIST_HEAD(&vha->logo_list);
3c6e85
 	INIT_LIST_HEAD(&vha->plogi_ack_list);
3c6e85
 	INIT_LIST_HEAD(&vha->gnl.fcports);
3c6e85
-	INIT_LIST_HEAD(&vha->nvme_rport_list);
3c6e85
 	INIT_LIST_HEAD(&vha->gpnid_list);
3c6e85
 	INIT_WORK(&vha->iocb_work, qla2x00_iocb_work_fn);
3c6e85
 
3c6e85
-- 
3c6e85
2.13.6
3c6e85