Merge 5.3-rc4 into driver-core-next
We need the driver core fixes in here as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
このコミットが含まれているのは:
@@ -1835,6 +1835,9 @@ void device_initialize(struct device *dev)
|
||||
kobject_init(&dev->kobj, &device_ktype);
|
||||
INIT_LIST_HEAD(&dev->dma_pools);
|
||||
mutex_init(&dev->mutex);
|
||||
#ifdef CONFIG_PROVE_LOCKING
|
||||
mutex_init(&dev->lockdep_mutex);
|
||||
#endif
|
||||
lockdep_set_novalidate_class(&dev->mutex);
|
||||
spin_lock_init(&dev->devres_lock);
|
||||
INIT_LIST_HEAD(&dev->devres_head);
|
||||
@@ -1994,12 +1997,63 @@ static inline struct kobject *get_glue_dir(struct device *dev)
|
||||
*/
|
||||
static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
|
||||
{
|
||||
unsigned int ref;
|
||||
|
||||
/* see if we live in a "glue" directory */
|
||||
if (!live_in_glue_dir(glue_dir, dev))
|
||||
return;
|
||||
|
||||
mutex_lock(&gdp_mutex);
|
||||
if (!kobject_has_children(glue_dir))
|
||||
/**
|
||||
* There is a race condition between removing glue directory
|
||||
* and adding a new device under the glue directory.
|
||||
*
|
||||
* CPU1: CPU2:
|
||||
*
|
||||
* device_add()
|
||||
* get_device_parent()
|
||||
* class_dir_create_and_add()
|
||||
* kobject_add_internal()
|
||||
* create_dir() // create glue_dir
|
||||
*
|
||||
* device_add()
|
||||
* get_device_parent()
|
||||
* kobject_get() // get glue_dir
|
||||
*
|
||||
* device_del()
|
||||
* cleanup_glue_dir()
|
||||
* kobject_del(glue_dir)
|
||||
*
|
||||
* kobject_add()
|
||||
* kobject_add_internal()
|
||||
* create_dir() // in glue_dir
|
||||
* sysfs_create_dir_ns()
|
||||
* kernfs_create_dir_ns(sd)
|
||||
*
|
||||
* sysfs_remove_dir() // glue_dir->sd=NULL
|
||||
* sysfs_put() // free glue_dir->sd
|
||||
*
|
||||
* // sd is freed
|
||||
* kernfs_new_node(sd)
|
||||
* kernfs_get(glue_dir)
|
||||
* kernfs_add_one()
|
||||
* kernfs_put()
|
||||
*
|
||||
* Before CPU1 remove last child device under glue dir, if CPU2 add
|
||||
* a new device under glue dir, the glue_dir kobject reference count
|
||||
* will be increase to 2 in kobject_get(k). And CPU2 has been called
|
||||
* kernfs_create_dir_ns(). Meanwhile, CPU1 call sysfs_remove_dir()
|
||||
* and sysfs_put(). This result in glue_dir->sd is freed.
|
||||
*
|
||||
* Then the CPU2 will see a stale "empty" but still potentially used
|
||||
* glue dir around in kernfs_new_node().
|
||||
*
|
||||
* In order to avoid this happening, we also should make sure that
|
||||
* kernfs_node for glue_dir is released in CPU1 only when refcount
|
||||
* for glue_dir kobj is 1.
|
||||
*/
|
||||
ref = kref_read(&glue_dir->kref);
|
||||
if (!kobject_has_children(glue_dir) && !--ref)
|
||||
kobject_del(glue_dir);
|
||||
kobject_put(glue_dir);
|
||||
mutex_unlock(&gdp_mutex);
|
||||
@@ -2403,6 +2457,24 @@ void put_device(struct device *dev)
|
||||
}
|
||||
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.
|
||||
* @dev: device.
|
||||
@@ -2422,15 +2494,8 @@ void device_del(struct device *dev)
|
||||
struct kobject *glue_dir = NULL;
|
||||
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);
|
||||
dev->p->dead = true;
|
||||
kill_device(dev);
|
||||
device_unlock(dev);
|
||||
|
||||
/* Notify clients of device removal. This call must come
|
||||
|
新しいイシューから参照
ユーザーをブロックする