Commit 6245838f authored by Hugh Daschbach's avatar Hugh Daschbach Committed by Greg Kroah-Hartman

Driver core: Protect device shutdown from hot unplug events.

While device_shutdown() walks through devices_kset to shutdown all
devices, device unplug events may race to shutdown individual devices.
Specifically, sd_shutdown(), on behalf of fc_starget_delete(), has
been observed deleting devices during device_shutdown()'s list
traversal.  So we factor out list_for_each_entry_safe_reverse(...) in
favor of while (!list_empty(...)).
Signed-off-by: default avatarHugh Daschbach <hdasch@broadcom.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e177123f
...@@ -1734,10 +1734,25 @@ EXPORT_SYMBOL_GPL(device_move); ...@@ -1734,10 +1734,25 @@ EXPORT_SYMBOL_GPL(device_move);
*/ */
void device_shutdown(void) void device_shutdown(void)
{ {
struct device *dev, *devn; struct device *dev;
spin_lock(&devices_kset->list_lock);
/*
* Walk the devices list backward, shutting down each in turn.
* Beware that device unplug events may also start pulling
* devices offline, even as the system is shutting down.
*/
while (!list_empty(&devices_kset->list)) {
dev = list_entry(devices_kset->list.prev, struct device,
kobj.entry);
get_device(dev);
/*
* Make sure the device is off the kset list, in the
* event that dev->*->shutdown() doesn't remove it.
*/
list_del_init(&dev->kobj.entry);
spin_unlock(&devices_kset->list_lock);
list_for_each_entry_safe_reverse(dev, devn, &devices_kset->list,
kobj.entry) {
if (dev->bus && dev->bus->shutdown) { if (dev->bus && dev->bus->shutdown) {
dev_dbg(dev, "shutdown\n"); dev_dbg(dev, "shutdown\n");
dev->bus->shutdown(dev); dev->bus->shutdown(dev);
...@@ -1745,6 +1760,10 @@ void device_shutdown(void) ...@@ -1745,6 +1760,10 @@ void device_shutdown(void)
dev_dbg(dev, "shutdown\n"); dev_dbg(dev, "shutdown\n");
dev->driver->shutdown(dev); dev->driver->shutdown(dev);
} }
put_device(dev);
spin_lock(&devices_kset->list_lock);
} }
spin_unlock(&devices_kset->list_lock);
async_synchronize_full(); async_synchronize_full();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment