]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
drivers/base: Introduce kill_device()
authorDan Williams <dan.j.williams@intel.com>
Tue, 6 Aug 2019 01:31:51 +0000 (18:31 -0700)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Tue, 17 Sep 2019 16:02:18 +0000 (18:02 +0200)
BugLink: https://bugs.launchpad.net/bugs/1840378
commit 00289cd87676e14913d2d8492d1ce05c4baafdae upstream.

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: 4d88a97aa9e8 ("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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
drivers/base/core.c
include/linux/device.h

index dff1ef65d768180a97fd3ce56ec36a32a10213b9..ddfaf230292c68cff999bcdfc739ff7593cde6dd 100644 (file)
@@ -1964,6 +1964,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.
@@ -1983,15 +2001,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
index b67683738812ea11458294a0be5a95f5cc0bb12e..84aa3f0aa3138a8b377a3394486b6b06e3abae99 100644 (file)
@@ -1260,6 +1260,7 @@ extern int (*platform_notify_remove)(struct device *dev);
  */
 extern struct device *get_device(struct device *dev);
 extern void put_device(struct device *dev);
+extern bool kill_device(struct device *dev);
 
 #ifdef CONFIG_DEVTMPFS
 extern int devtmpfs_create_node(struct device *dev);