[v2,1/7] drivers/base: Introduce kill_device()
diff mbox series

Message ID 156341207332.292348.14959761496009347574.stgit@dwillia2-desk3.amr.corp.intel.com
State Accepted
Commit 00289cd87676e14913d2d8492d1ce05c4baafdae
Headers show
Series
  • libnvdimm: Fix async operations and locking
Related show

Commit Message

Dan Williams July 18, 2019, 1:07 a.m. UTC
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>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/base/core.c    |   27 +++++++++++++++++++--------
 include/linux/device.h |    1 +
 2 files changed, 20 insertions(+), 8 deletions(-)

Comments

Greg KH July 18, 2019, 2:29 a.m. UTC | #1
On Wed, Jul 17, 2019 at 06:07:53PM -0700, Dan Williams wrote:
> 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>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Sasha Levin July 19, 2019, 12:45 a.m. UTC | #2
Hi,

[This is an automated email]

This commit has been processed because it contains a "Fixes:" tag,
fixing commit: 4d88a97aa9e8 libnvdimm, nvdimm: dimm driver and base libnvdimm device-driver infrastructure.

The bot has tested the following trees: v5.2.1, v5.1.18, v4.19.59, v4.14.133, v4.9.185, v4.4.185.

v5.2.1: Build OK!
v5.1.18: Build OK!
v4.19.59: Failed to apply! Possible dependencies:
    3451a495ef24 ("driver core: Establish order of operations for device_add and device_del via bitflag")

v4.14.133: Failed to apply! Possible dependencies:
    3451a495ef24 ("driver core: Establish order of operations for device_add and device_del via bitflag")

v4.9.185: Failed to apply! Possible dependencies:
    3451a495ef24 ("driver core: Establish order of operations for device_add and device_del via bitflag")

v4.4.185: Failed to apply! Possible dependencies:
    3451a495ef24 ("driver core: Establish order of operations for device_add and device_del via bitflag")
    656b8035b0ee ("ARM: 8524/1: driver cohandle -EPROBE_DEFER from bus_type.match()")


NOTE: The patch will not be queued to stable trees until it is upstream.

How should we proceed with this patch?

--
Thanks,
Sasha

Patch
diff mbox series

diff --git a/drivers/base/core.c b/drivers/base/core.c
index fd7511e04e62..eaf3aa0cb803 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2211,6 +2211,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.
@@ -2230,15 +2248,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
diff --git a/include/linux/device.h b/include/linux/device.h
index e85264fb6616..0da5c67f6be1 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1373,6 +1373,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);