scsi: wait in scsi_remove_host till async scan ends
PATCH 1/1 scsi: wait in scsi_remove_host till async scan ends
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)
---
drivers/scsi/hosts.c +7 -0
@@ -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 ))
drivers/scsi/scsi_scan.c +15 -13
@@ -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 );