From 3b661a92e869ebe2358de8f4b3230ad84f7fce51 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 21 Jun 2012 23:47:28 -0700 Subject: [SCSI] fix hot unplug vs async scan race The following crash results from cases where the end_device has been removed before scsi_sysfs_add_sdev has had a chance to run. BUG: unable to handle kernel NULL pointer dereference at 0000000000000098 IP: [] sysfs_create_dir+0x32/0xb6 ... Call Trace: [] kobject_add_internal+0x120/0x1e3 [] ? trace_hardirqs_on+0xd/0xf [] kobject_add_varg+0x41/0x50 [] kobject_add+0x64/0x66 [] device_add+0x12d/0x63a [] ? _raw_spin_unlock_irqrestore+0x47/0x56 [] ? module_refcount+0x89/0xa0 [] scsi_sysfs_add_sdev+0x4e/0x28a [] do_scan_async+0x9c/0x145 ...teach scsi_sysfs_add_devices() to check for deleted devices() before trying to add them, and teach scsi_remove_target() how to remove targets that have not been added via device_add(). Cc: Reported-by: Dariusz Majchrzak Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 2e5fe584aad3..f55e5f166973 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1717,6 +1717,9 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) { struct scsi_device *sdev; shost_for_each_device(sdev, shost) { + /* target removed before the device could be added */ + if (sdev->sdev_state == SDEV_DEL) + continue; if (!scsi_host_scan_allowed(shost) || scsi_sysfs_add_sdev(sdev) != 0) __scsi_remove_device(sdev); -- cgit v1.2.3 From 6cdd55205d160f63003c321fcea608336953dd5b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 9 Jul 2012 19:33:35 -0700 Subject: [SCSI] queue async scan work to an async_schedule domain This is preparation to enable async_synchronize_full() to be used as a replacement for scsi_complete_async_scans(), i.e. to stop leaking scsi internal details where they are not needed. Signed-off-by: Dan Williams Tested-by: Eldad Zack Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index f55e5f166973..dff17c198a72 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1845,14 +1845,13 @@ static void do_scsi_scan_host(struct Scsi_Host *shost) } } -static int do_scan_async(void *_data) +static void do_scan_async(void *_data, async_cookie_t c) { struct async_scan_data *data = _data; struct Scsi_Host *shost = data->shost; do_scsi_scan_host(shost); scsi_finish_async_scan(data); - return 0; } /** @@ -1861,7 +1860,6 @@ static int do_scan_async(void *_data) **/ void scsi_scan_host(struct Scsi_Host *shost) { - struct task_struct *p; struct async_scan_data *data; if (strncmp(scsi_scan_type, "none", 4) == 0) @@ -1876,9 +1874,11 @@ void scsi_scan_host(struct Scsi_Host *shost) return; } - p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); - if (IS_ERR(p)) - do_scan_async(data); + /* register with the async subsystem so wait_for_device_probe() + * will flush this work + */ + async_schedule(do_scan_async, data); + /* scsi_autopm_put_host(shost) is called in scsi_finish_async_scan() */ } EXPORT_SYMBOL(scsi_scan_host); -- cgit v1.2.3 From 492d542273a4859f8bf8cc7744cdf71ef50b39ea Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 9 Jul 2012 19:33:40 -0700 Subject: [SCSI] cleanup usages of scsi_complete_async_scans Now that scsi registers its async scan work with the async subsystem, wait_for_device_probe() is sufficient for ensuring all scanning is complete. [jejb: fix merge problems with eea03c20ae38 Make wait_for_device_probe() also do scsi_complete_async_scans()] Signed-off-by: Dan Williams Tested-by: Eldad Zack Signed-off-by: James Bottomley --- drivers/base/dd.c | 2 -- drivers/scsi/scsi_scan.c | 12 ------------ include/scsi/scsi_scan.h | 11 ----------- 3 files changed, 25 deletions(-) delete mode 100644 include/scsi/scsi_scan.h (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 4b01ab3d2c24..dcb8a6e48692 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "base.h" #include "power/power.h" @@ -333,7 +332,6 @@ void wait_for_device_probe(void) /* wait for the known devices to complete their probing */ wait_event(probe_waitqueue, atomic_read(&probe_count) == 0); async_synchronize_full(); - scsi_complete_async_scans(); } EXPORT_SYMBOL_GPL(wait_for_device_probe); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index dff17c198a72..a0bc66372654 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -187,18 +187,6 @@ int scsi_complete_async_scans(void) return 0; } -/* Only exported for the benefit of scsi_wait_scan */ -EXPORT_SYMBOL_GPL(scsi_complete_async_scans); - -#ifndef MODULE -/* - * For async scanning we need to wait for all the scans to complete before - * trying to mount the root fs. Otherwise non-modular drivers may not be ready - * yet. - */ -late_initcall(scsi_complete_async_scans); -#endif - /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command * @sdev: scsi device to send command to diff --git a/include/scsi/scsi_scan.h b/include/scsi/scsi_scan.h deleted file mode 100644 index 78898889243d..000000000000 --- a/include/scsi/scsi_scan.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _SCSI_SCSI_SCAN_H -#define _SCSI_SCSI_SCAN_H - -#ifdef CONFIG_SCSI -/* drivers/scsi/scsi_scan.c */ -extern int scsi_complete_async_scans(void); -#else -static inline int scsi_complete_async_scans(void) { return 0; } -#endif - -#endif /* _SCSI_SCSI_SCAN_H */ -- cgit v1.2.3 From e96eb23d82b4246cce4eeb14a7eedbbdcf37b3d4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 9 Jul 2012 19:33:45 -0700 Subject: [SCSI] Revert "[SCSI] fix async probe regression" This reverts commit 43a8d39d0137612c336aa8bbb2cb886a79772ffb. Commit 43a8d39d fixed the fact that wait_for_device_probe() was unable to flush sd probe work. Now that sd probe work is once again flushable via wait_for_device_probe() this workaround is no longer needed. Signed-off-by: Dan Williams Tested-by: Eldad Zack Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index a0bc66372654..56a93794c470 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -147,7 +147,7 @@ int scsi_complete_async_scans(void) do { if (list_empty(&scanning_hosts)) - goto out; + return 0; /* If we can't get memory immediately, that's OK. Just * sleep a little. Even if we never get memory, the async * scans will finish eventually. @@ -179,11 +179,8 @@ int scsi_complete_async_scans(void) } done: spin_unlock(&async_scan_lock); - kfree(data); - - out: - async_synchronize_full_domain(&scsi_sd_probe_domain); + kfree(data); return 0; } -- cgit v1.2.3