From: stuart hayes <stuart.w.hayes@gmail.com>
To: David Jeffery <djeffery@redhat.com>
Cc: Jan Kiszka <jan.kiszka@siemens.com>,
linux-kernel@vger.kernel.org,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J . Wysocki" <rafael@kernel.org>,
Martin Belanger <Martin.Belanger@dell.com>,
Oliver O'Halloran <oohall@gmail.com>,
Daniel Wagner <dwagner@suse.de>, Keith Busch <kbusch@kernel.org>,
Lukas Wunner <lukas@wunner.de>, Jeremy Allison <jallison@ciq.com>,
Jens Axboe <axboe@fb.com>, Christoph Hellwig <hch@lst.de>,
Sagi Grimberg <sagi@grimberg.me>,
linux-nvme@lists.infradead.org,
Nathan Chancellor <nathan@kernel.org>
Subject: Re: [PATCH v8 3/4] driver core: shut down devices asynchronously
Date: Thu, 12 Sep 2024 11:20:05 -0500 [thread overview]
Message-ID: <754401e6-b6a5-4393-ad9b-ffe113e33a72@gmail.com> (raw)
In-Reply-To: <CA+-xHTEMM09PXgWyKX4h48diUxxGnSSrDowh5Gt=Y+EVhHL-_Q@mail.gmail.com>
On 9/12/2024 9:30 AM, David Jeffery wrote:
> On Tue, Sep 10, 2024 at 8:14 PM stuart hayes <stuart.w.hayes@gmail.com> wrote:
>>
> ...
>> diff --git a/drivers/base/core.c b/drivers/base/core.c
>> index b69b82da8837..52d64b419c01 100644
>> --- a/drivers/base/core.c
>> +++ b/drivers/base/core.c
>> @@ -4832,6 +4832,13 @@ static void shutdown_one_device_async(void *data, async_cookie_t cookie)
>> {
>> struct device *dev = data;
>>
>> + /*
>> + * Sanity check to prevent shutdown hang in case a parent or supplier
>> + * is in devices_kset list in the wrong order
>> + */
>> + if (dev->p->shutdown_after > cookie)
>> + dev->p->shutdown_after = cookie - 1;
>> +
>> async_synchronize_cookie_domain(dev->p->shutdown_after + 1, &sd_domain);
>>
>> shutdown_one_device(dev);
>
> While the race window is really small, there is a potential race with
> this fixup. It's possible for the shutdown operation to write a new
> value to shutdown_after in the time between the if check and
> shutdown_after being re-read and used in the
> async_synchronize_cookie_domain call. Such a race would allow a too
> high value to be used.
>
> Instead, could do something like:
>
> --- a/drivers/base/core.c
> +++ b/drivers/base/core.c
> @@ -4833,8 +4833,12 @@ static void shutdown_one_device(struct device *dev)
> static void shutdown_one_device_async(void *data, async_cookie_t cookie)
> {
> struct device *dev = data;
> + async_cookie_t wait = dev->p->shutdown_after + 1;
>
> - async_synchronize_cookie_domain(dev->p->shutdown_after + 1, &sd_domain);
> + if (wait > cookie)
> + wait = cookie;
> +
> + async_synchronize_cookie_domain(wait, &sd_domain);
>
> shutdown_one_device(dev);
> }
>
> This reads the shutdown_after value once and avoids the race window
> where its value being changed on another CPU could still cause a
> potential deadlock.
>
Good point. Really that sanity check shouldn't be needed at all. But... maybe it
would be better to just not change the shutdown_after on any device that's
already been scheduled for shutdown... this would work regardless of why the supplier
and consumer devices are in the wrong order on the devices_kset list, and would still
work if supplier/consumer devices don't get reordered for some reason other than
the devlink being sync_state only in the future. Plus, it's a bit simpler.
How does this look?
diff --git a/drivers/base/base.h b/drivers/base/base.h
index ea18aa70f151..f818a0251bb7 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -105,6 +105,8 @@ struct driver_private {
* @dead - This device is currently either in the process of or has been
* removed from the system. Any asynchronous events scheduled for this
* device should exit without taking any action.
+ * @shutdown_scheduled - asynchronous shutdown of the device has already
+ * been scheduled
*
* Nothing outside of the driver core should ever touch these fields.
*/
@@ -120,6 +122,7 @@ struct device_private {
async_cookie_t shutdown_after;
struct device *device;
u8 dead:1;
+ u8 shutdown_scheduled:1;
};
#define to_device_private_parent(obj) \
container_of(obj, struct device_private, knode_parent)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b69b82da8837..bd6bc4a3dc15 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -4888,6 +4888,8 @@ void device_shutdown(void)
cookie = async_schedule_domain(shutdown_one_device_async,
dev, &sd_domain);
+ dev->p->shutdown_scheduled = 1;
+
/*
* Ensure parent & suppliers wait for this device to shut down
*/
@@ -4898,8 +4900,18 @@ void device_shutdown(void)
idx = device_links_read_lock();
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
- device_links_read_lock_held())
- link->supplier->p->shutdown_after = cookie;
+ device_links_read_lock_held()) {
+ /*
+ * Only update cookie if device shutdown hasn't
+ * already been scheduled. Some supplier/consumer
+ * devices (sync_state only) aren't reordered on
+ * devices_kset list and don't need this, and setting
+ * this could result in a circular dependency if the
+ * supplier shutdown has already been scheduled.
+ */
+ if (!link->supplier->p->shutdown_scheduled)
+ link->supplier->p->shutdown_after = cookie;
+ }
device_links_read_unlock(idx);
put_device(dev);
next prev parent reply other threads:[~2024-09-12 16:20 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-22 20:28 [PATCH v8 0/4] shut down devices asynchronously Stuart Hayes
2024-08-22 20:28 ` [PATCH v8 1/4] driver core: don't always lock parent in shutdown Stuart Hayes
2024-08-23 6:26 ` Christoph Hellwig
2024-08-25 7:56 ` Sagi Grimberg
2024-08-22 20:28 ` [PATCH v8 2/4] driver core: separate function to shutdown one device Stuart Hayes
2024-08-23 6:26 ` Christoph Hellwig
2024-08-25 7:56 ` Sagi Grimberg
2024-08-22 20:28 ` [PATCH v8 3/4] driver core: shut down devices asynchronously Stuart Hayes
2024-08-23 6:26 ` Christoph Hellwig
2024-08-24 10:29 ` Lukas Wunner
2024-08-25 7:58 ` Sagi Grimberg
2024-09-05 22:13 ` Nathan Chancellor
2024-09-06 14:44 ` stuart hayes
2024-09-08 13:36 ` Jan Kiszka
2024-09-11 0:14 ` stuart hayes
2024-09-11 5:51 ` Jan Kiszka
2024-09-11 22:06 ` stuart hayes
2024-09-12 14:30 ` David Jeffery
2024-09-12 16:20 ` stuart hayes [this message]
2024-09-08 14:44 ` Christophe JAILLET
2024-09-23 20:50 ` Andrey Skvortsov
2024-09-24 9:23 ` Greg Kroah-Hartman
2024-09-24 20:44 ` Andrey Skvortsov
2024-09-25 8:55 ` Greg Kroah-Hartman
2024-08-22 20:28 ` [PATCH v8 4/4] nvme-pci: Make driver prefer asynchronous shutdown Stuart Hayes
2024-08-23 6:27 ` Christoph Hellwig
2024-08-25 7:57 ` Sagi Grimberg
2024-08-23 16:54 ` [PATCH v8 0/4] shut down devices asynchronously Keith Busch
2024-09-03 11:10 ` Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=754401e6-b6a5-4393-ad9b-ffe113e33a72@gmail.com \
--to=stuart.w.hayes@gmail.com \
--cc=Martin.Belanger@dell.com \
--cc=axboe@fb.com \
--cc=djeffery@redhat.com \
--cc=dwagner@suse.de \
--cc=gregkh@linuxfoundation.org \
--cc=hch@lst.de \
--cc=jallison@ciq.com \
--cc=jan.kiszka@siemens.com \
--cc=kbusch@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=lukas@wunner.de \
--cc=nathan@kernel.org \
--cc=oohall@gmail.com \
--cc=rafael@kernel.org \
--cc=sagi@grimberg.me \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.