[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-scsi
Subject:    [PATCH v2 2/3] scsi: Make scsi_forget_host() wait for request queue removal
From:       Bart Van Assche <bvanassche () acm ! org>
Date:       2022-06-30 21:37:32
Message-ID: 20220630213733.17689-3-bvanassche () acm ! org
[Download RAW message or body]

Prepare for freeing the host tag set earlier by making scsi_forget_host()
wait until all activity on the host tag set has stopped.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Ming Lei <ming.lei@redhat.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: John Garry <john.garry@huawei.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 drivers/scsi/scsi_scan.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 5c3bb4ceeac3..c8331ccdde95 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1961,6 +1961,16 @@ void scsi_scan_host(struct Scsi_Host *shost)
 }
 EXPORT_SYMBOL(scsi_scan_host);
 
+/**
+ * scsi_forget_host() - Remove all SCSI devices from a host.
+ * @shost: SCSI host to remove devices from.
+ *
+ * Removes all SCSI devices that have not yet been removed. For the SCSI devices
+ * for which removal started before scsi_forget_host(), wait until the
+ * associated request queue has reached the "dead" state. In that state it is
+ * guaranteed that no new requests will be allocated and also that no requests
+ * are in progress anymore.
+ */
 void scsi_forget_host(struct Scsi_Host *shost)
 {
 	struct scsi_device *sdev;
@@ -1970,8 +1980,21 @@ void scsi_forget_host(struct Scsi_Host *shost)
  restart:
 	spin_lock_irq(shost->host_lock);
 	list_for_each_entry(sdev, &shost->__devices, siblings) {
-		if (sdev->sdev_state == SDEV_DEL)
+		if (sdev->sdev_state == SDEV_DEL &&
+		    blk_queue_dead(sdev->request_queue)) {
 			continue;
+		}
+		if (sdev->sdev_state == SDEV_DEL) {
+			get_device(&sdev->sdev_gendev);
+			spin_unlock_irq(shost->host_lock);
+
+			while (!blk_queue_dead(sdev->request_queue))
+				msleep(10);
+
+			spin_lock_irq(shost->host_lock);
+			put_device(&sdev->sdev_gendev);
+			goto restart;
+		}
 		spin_unlock_irq(shost->host_lock);
 		__scsi_remove_device(sdev);
 		goto restart;
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic