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

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