[PATCH 1/5] driver core: Support two-pass driver shutdown

Sagi Grimberg sagi at grimberg.me
Thu Jan 4 05:12:11 PST 2024



On 1/3/24 23:04, Jeremy Allison wrote:
> From: Tanjore Suresh <tansuresh at google.com>
> 
> This changes the bus driver interface with an additional entry point
> to enable devices to implement two-pass shutdown. The existing
> synchronous interface to shutdown is called, and if a shutdown_wait
> method is defined the device is moved to an alternate list.
> 
> Once the shutdown method is called for all devices, the
> shutdown_wait method is then called synchronously for
> all devices on the alternate list.
> 
> Signed-off-by: Tanjore Suresh <tansuresh at google.com>
> Signed-off-by: Jeremy Allison <jallison at ciq.com>
> ---
>   drivers/base/core.c        | 37 +++++++++++++++++++++++++++++++++++++
>   include/linux/device/bus.h |  6 +++++-
>   2 files changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/base/core.c b/drivers/base/core.c
> index 67ba592afc77..e1f4c54de3e1 100644
> --- a/drivers/base/core.c
> +++ b/drivers/base/core.c
> @@ -4725,6 +4725,7 @@ EXPORT_SYMBOL_GPL(device_change_owner);
>   void device_shutdown(void)
>   {
>   	struct device *dev, *parent;
> +	LIST_HEAD(shutdown_wait_list);
>   
>   	wait_for_device_probe();
>   	device_block_probing();
> @@ -4769,10 +4770,17 @@ void device_shutdown(void)
>   				dev_info(dev, "shutdown_pre\n");
>   			dev->class->shutdown_pre(dev);
>   		}
> +
>   		if (dev->bus && dev->bus->shutdown) {
>   			if (initcall_debug)
>   				dev_info(dev, "shutdown\n");
>   			dev->bus->shutdown(dev);
> +			/*
> +			 * Only put the device on the shutdown_wait_list
> +			 * if a shutdown_wait() method is also defined.
> +			 */
> +			if (dev->bus->shutdown_wait)
> +				list_add(&dev->kobj.entry, &shutdown_wait_list);
>   		} else if (dev->driver && dev->driver->shutdown) {
>   			if (initcall_debug)
>   				dev_info(dev, "shutdown\n");
> @@ -4789,6 +4797,35 @@ void device_shutdown(void)
>   		spin_lock(&devices_kset->list_lock);
>   	}
>   	spin_unlock(&devices_kset->list_lock);
> +
> +	/*
> +	 * Second pass only for devices that have configured
> +	 * a shutdown_wait() method.
> +	 */
> +	while (!list_empty(&shutdown_wait_list)) {
> +		dev = list_entry(shutdown_wait_list.next, struct device,
> +				kobj.entry);
> +		parent = get_device(dev->parent);
> +		get_device(dev);
> +		/*
> +		 * Make sure the device is off the  list
> +		 */
> +		list_del_init(&dev->kobj.entry);
> +		if (parent)
> +			device_lock(parent);
> +		device_lock(dev);
> +		if (dev->bus && dev->bus->shutdown_wait) {

How can dev->bus or dev->bus->shutdown_wait be null at this
point?



More information about the Linux-nvme mailing list