[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20211110182001.628982980@linuxfoundation.org>
Date: Wed, 10 Nov 2021 19:43:08 +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 4.9 01/22] 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
@@ -951,8 +951,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
@@ -427,9 +427,12 @@ static void scsi_device_dev_release_user
struct device *parent;
struct list_head *this, *tmp;
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;
@@ -461,11 +464,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