public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2] scsi: core: put LLD module refcnt after SCSI device is released
@ 2021-09-30  7:40 Ming Lei
  2021-09-30  7:50 ` Ming Lei
  2021-09-30  8:07 ` Greg Kroah-Hartman
  0 siblings, 2 replies; 8+ messages in thread
From: Ming Lei @ 2021-09-30  7:40 UTC (permalink / raw)
  To: Martin K . Petersen, linux-scsi
  Cc: Ming Lei, Changhui Zhong, Yi Zhang, Greg Kroah-Hartman

SCSI host release is triggered when SCSI device is freed, and we have to
make sure that LLD module won't be unloaded before SCSI host instance is
released because shost->hostt is required in host release handler.

So put LLD module refcnt after SCSI device is released.

The real release handler can be run from wq context in case of
in_interrupt(), so add one atomic counter for serializing putting
module via current and wq context. This way is fine since we don't
call scsi_device_put() in fast IO path.

Reported-by: Changhui Zhong <czhong@redhat.com>
Reported-by: Yi Zhang <yi.zhang@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
 drivers/scsi/scsi.c        |  8 +++++++-
 drivers/scsi/scsi_sysfs.c  | 10 ++++++++++
 include/scsi/scsi_device.h |  2 ++
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index b241f9e3885c..b6612161587f 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -553,8 +553,14 @@ 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;
+
+	atomic_inc(&sdev->put_dev_cnt);
+
 	put_device(&sdev->sdev_gendev);
+
+	if (atomic_dec_if_positive(&sdev->put_dev_cnt) >= 0)
+		module_put(mod);
 }
 EXPORT_SYMBOL(scsi_device_put);
 
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 86793259e541..ba6defac91ae 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -449,9 +449,16 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
 	struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL;
 	struct scsi_vpd *vpd_pg0 = NULL, *vpd_pg89 = NULL;
 	unsigned long flags;
+	struct module *mod;
+	bool put_mod = false;
 
 	sdev = container_of(work, struct scsi_device, ew.work);
 
+	if (atomic_dec_if_positive(&sdev->put_dev_cnt) >= 0) {
+		put_mod = true;
+		mod = sdev->host->hostt->module;
+	}
+
 	scsi_dh_release_device(sdev);
 
 	parent = sdev->sdev_gendev.parent;
@@ -502,6 +509,9 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
 
 	if (parent)
 		put_device(parent);
+
+	if (put_mod)
+		module_put(mod);
 }
 
 static void scsi_device_dev_release(struct device *dev)
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 430b73bd02ac..76268c473c22 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -111,6 +111,8 @@ struct scsi_device {
 	struct sbitmap budget_map;
 	atomic_t device_blocked;	/* Device returned QUEUE_FULL. */
 
+	atomic_t put_dev_cnt;	/* increased by 1 when we are putting device */
+
 	atomic_t restarts;
 	spinlock_t list_lock;
 	struct list_head starved_entry;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-09-30 11:07 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-09-30  7:40 [PATCH V2] scsi: core: put LLD module refcnt after SCSI device is released Ming Lei
2021-09-30  7:50 ` Ming Lei
2021-09-30  8:07 ` Greg Kroah-Hartman
2021-09-30  8:20   ` Ming Lei
2021-09-30  8:29     ` Greg Kroah-Hartman
2021-09-30  8:44       ` Ming Lei
2021-09-30 10:12         ` Greg Kroah-Hartman
2021-09-30 11:07           ` Ming Lei

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox