[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20211104141158.434717408@linuxfoundation.org>
Date: Thu, 4 Nov 2021 15:12:54 +0100
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org, Changhui Zhong <czhong@...hat.com>,
Yi Zhang <yi.zhang@...hat.com>, Ming Lei <ming.lei@...hat.com>,
"Martin K. Petersen" <martin.petersen@...cle.com>
Subject: [PATCH 5.4 1/9] scsi: core: Put LLD module refcnt after SCSI device is released
From: Ming Lei <ming.lei@...hat.com>
commit f2b85040acec9a928b4eb1b57a989324e8e38d3f upstream.
SCSI host release is triggered when SCSI device is freed. We have to make
sure that the low-level device driver module won't be unloaded before SCSI
host instance is released because shost->hostt is required in the release
handler.
Make sure to put LLD module refcnt after SCSI device is released.
Fixes a kernel panic of 'BUG: unable to handle page fault for address'
reported by Changhui and Yi.
Link: https://lore.kernel.org/r/20211008050118.1440686-1-ming.lei@redhat.com
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Reported-by: Changhui Zhong <czhong@...hat.com>
Reported-by: Yi Zhang <yi.zhang@...hat.com>
Tested-by: Yi Zhang <yi.zhang@...hat.com>
Signed-off-by: Ming Lei <ming.lei@...hat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@...cle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
---
drivers/scsi/scsi.c | 4 +++-
drivers/scsi/scsi_sysfs.c | 9 +++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -555,8 +555,10 @@ EXPORT_SYMBOL(scsi_device_get);
*/
void scsi_device_put(struct scsi_device *sdev)
{
- module_put(sdev->host->hostt->module);
+ struct module *mod = sdev->host->hostt->module;
+
put_device(&sdev->sdev_gendev);
+ module_put(mod);
}
EXPORT_SYMBOL(scsi_device_put);
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -438,9 +438,12 @@ static void scsi_device_dev_release_user
struct list_head *this, *tmp;
struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL;
unsigned long flags;
+ struct module *mod;
sdev = container_of(work, struct scsi_device, ew.work);
+ mod = sdev->host->hostt->module;
+
scsi_dh_release_device(sdev);
parent = sdev->sdev_gendev.parent;
@@ -481,11 +484,17 @@ static void scsi_device_dev_release_user
if (parent)
put_device(parent);
+ module_put(mod);
}
static void scsi_device_dev_release(struct device *dev)
{
struct scsi_device *sdp = to_scsi_device(dev);
+
+ /* Set module pointer as NULL in case of module unloading */
+ if (!try_module_get(sdp->host->hostt->module))
+ sdp->host->hostt->module = NULL;
+
execute_in_process_context(scsi_device_dev_release_usercontext,
&sdp->ew);
}
Powered by blists - more mailing lists