drivers/base: Introduce kill_device()
The libnvdimm subsystem arranges for devices to be destroyed as a result
of a sysfs operation. Since device_unregister() cannot be called from
an actively running sysfs attribute of the same device libnvdimm
arranges for device_unregister() to be performed in an out-of-line async
context.
The driver core maintains a 'dead' state for coordinating its own racing
async registration / de-registration requests. Rather than add local
'dead' state tracking infrastructure to libnvdimm device objects, export
the existing state tracking via a new kill_device() helper.
The kill_device() helper simply marks the device as dead, i.e. that it
is on its way to device_del(), or returns that the device was already
dead. This can be used in advance of calling device_unregister() for
subsystems like libnvdimm that might need to handle multiple user
threads racing to delete a device.
This refactoring does not change any behavior, but it is a pre-requisite
for follow-on fixes and therefore marked for -stable.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Fixes: 4d88a97aa9
("libnvdimm, nvdimm: dimm driver and base libnvdimm device-driver...")
Cc: <stable@vger.kernel.org>
Tested-by: Jane Chu <jane.chu@oracle.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/156341207332.292348.14959761496009347574.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Родитель
d1fdb6d8f6
Коммит
00289cd876
|
@ -2211,6 +2211,24 @@ void put_device(struct device *dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(put_device);
|
EXPORT_SYMBOL_GPL(put_device);
|
||||||
|
|
||||||
|
bool kill_device(struct device *dev)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Require the device lock and set the "dead" flag to guarantee that
|
||||||
|
* the update behavior is consistent with the other bitfields near
|
||||||
|
* it and that we cannot have an asynchronous probe routine trying
|
||||||
|
* to run while we are tearing out the bus/class/sysfs from
|
||||||
|
* underneath the device.
|
||||||
|
*/
|
||||||
|
lockdep_assert_held(&dev->mutex);
|
||||||
|
|
||||||
|
if (dev->p->dead)
|
||||||
|
return false;
|
||||||
|
dev->p->dead = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(kill_device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* device_del - delete device from system.
|
* device_del - delete device from system.
|
||||||
* @dev: device.
|
* @dev: device.
|
||||||
|
@ -2230,15 +2248,8 @@ void device_del(struct device *dev)
|
||||||
struct kobject *glue_dir = NULL;
|
struct kobject *glue_dir = NULL;
|
||||||
struct class_interface *class_intf;
|
struct class_interface *class_intf;
|
||||||
|
|
||||||
/*
|
|
||||||
* Hold the device lock and set the "dead" flag to guarantee that
|
|
||||||
* the update behavior is consistent with the other bitfields near
|
|
||||||
* it and that we cannot have an asynchronous probe routine trying
|
|
||||||
* to run while we are tearing out the bus/class/sysfs from
|
|
||||||
* underneath the device.
|
|
||||||
*/
|
|
||||||
device_lock(dev);
|
device_lock(dev);
|
||||||
dev->p->dead = true;
|
kill_device(dev);
|
||||||
device_unlock(dev);
|
device_unlock(dev);
|
||||||
|
|
||||||
/* Notify clients of device removal. This call must come
|
/* Notify clients of device removal. This call must come
|
||||||
|
|
|
@ -1373,6 +1373,7 @@ extern int (*platform_notify_remove)(struct device *dev);
|
||||||
*/
|
*/
|
||||||
extern struct device *get_device(struct device *dev);
|
extern struct device *get_device(struct device *dev);
|
||||||
extern void put_device(struct device *dev);
|
extern void put_device(struct device *dev);
|
||||||
|
extern bool kill_device(struct device *dev);
|
||||||
|
|
||||||
#ifdef CONFIG_DEVTMPFS
|
#ifdef CONFIG_DEVTMPFS
|
||||||
extern int devtmpfs_create_node(struct device *dev);
|
extern int devtmpfs_create_node(struct device *dev);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче