All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] scsi: wait in scsi_remove_host till async scan ends
@ 2012-04-24 13:10 Tomas Henzl
  0 siblings, 0 replies; only message in thread
From: Tomas Henzl @ 2012-04-24 13:10 UTC (permalink / raw)
  To: 'linux-scsi@vger.kernel.org'

When a driver is rmmoded while a async scan is in progress, the lld is removed, and accessing
the host_template will causes a BUG : BUG: unable to handle kernel paging request at ffffffffa01874b8
This patch waits in the scsi_remove_host until the async scan ends. The scan thread checks for the host
state and the thread can end faster when the SHOST_CANCEL state is set. 

Another possibility - locking the lld with try_module_get before the scan starts does have problems
with 'rmmod --wait' (BUG again), the reason is that in scsi_device_get we don't check the return value
of try_module_get. When this gets fixed, this code could be replaced with a try_module_get approach.
(This was added 85b6c720b0931101c8bcc3a5abdc2b8514b0fb4b [SCSI] sd: fix cache flushing on module removal (and individual device removal)

Signed-off-by: Tomas Henzl <thenzl@redhat.com>
---
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 351dc0b..269b23f 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -33,6 +33,7 @@
 #include <linux/transport_class.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/delay.h>
 
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
@@ -172,6 +173,12 @@ void scsi_remove_host(struct Scsi_Host *shost)
 	scsi_forget_host(shost);
 	mutex_unlock(&shost->scan_mutex);
 	scsi_proc_host_rm(shost);
+	
+	while (shost->async_scan)
+		msleep(10);
+	/* the above while block needs to wait for a host_lock
+	 * this is now provided by the next code block
+	 */
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	if (scsi_host_set_state(shost, SHOST_DEL))
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 29c4c04..02a36b2 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1743,10 +1743,9 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
 
 	data = kmalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
-		goto err;
-	data->shost = scsi_host_get(shost);
-	if (!data->shost)
-		goto err;
+		return NULL;
+
+	data->shost = shost;
 	init_completion(&data->prev_finished);
 
 	mutex_lock(&shost->scan_mutex);
@@ -1762,10 +1761,6 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
 	spin_unlock(&async_scan_lock);
 
 	return data;
-
- err:
-	kfree(data);
-	return NULL;
 }
 
 /**
@@ -1800,9 +1795,6 @@ static void scsi_finish_async_scan(struct async_scan_data *data)
 
 	scsi_sysfs_add_devices(shost);
 
-	spin_lock_irqsave(shost->host_lock, flags);
-	shost->async_scan = 0;
-	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	mutex_unlock(&shost->scan_mutex);
 
@@ -1816,7 +1808,11 @@ static void scsi_finish_async_scan(struct async_scan_data *data)
 	spin_unlock(&async_scan_lock);
 
 	scsi_autopm_put_host(shost);
-	scsi_host_put(shost);
+	
+	spin_lock_irqsave(shost->host_lock, flags);
+	shost->async_scan = 0;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	
 	kfree(data);
 }
 
@@ -1827,8 +1823,14 @@ static void do_scsi_scan_host(struct Scsi_Host *shost)
 		if (shost->hostt->scan_start)
 			shost->hostt->scan_start(shost);
 
-		while (!shost->hostt->scan_finished(shost, jiffies - start))
+		while (!shost->hostt->scan_finished(shost, jiffies - start)) {
 			msleep(10);
+			if (!scsi_host_scan_allowed(shost)) {
+				printk (KERN_INFO "scsi: host not in proper  "
+					"state, async scan aborted ...\n");
+				break;
+			}
+		}
 	} else {
 		scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
 				SCAN_WILD_CARD, 0);



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2012-04-24 13:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-24 13:10 [PATCH] scsi: wait in scsi_remove_host till async scan ends Tomas Henzl

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.