[RFC PATCH v1] PM: wakeup: Provide interface for userspace to abort suspend

Saravana Kannan posted 1 patch 2 months, 2 weeks ago
drivers/base/power/wakeup.c | 2 ++
1 file changed, 2 insertions(+)
[RFC PATCH v1] PM: wakeup: Provide interface for userspace to abort suspend
Posted by Saravana Kannan 2 months, 2 weeks ago
Once suspend starts, it can take a while before file system sync
finishes and all the userspace threads are frozen. During this time,
there can be events that originate in userspace that would require the
suspend to be aborted.

The only way to abort suspend from userspace as of today is to grab
and release a kernel wakelock using the /sys/power/wake_lock and
/sys/power/wake_unlock files. This has the disadvantage of:

* Doing the useless work of creating and destroying wakelocks.
* If the userspace entity crashes after the wake lock is created, we
  get a wake lock/memory leak.

To avoid all this and simplify the interface, this patch allows
canceling a suspend by writing UINT_MAX value to the
/sys/power/wakeup_count that is meant for tracking wakeup events.

Signed-off-by: Saravana Kannan <saravanak@google.com>
---

Rafael,

If the idea looks good to you, I can also update Documentation and sent
it as a non-RFC patch. I'm not too tied on what file we use to trigger
an abort from userspace as long as it's possible.

Thanks,
Saravana

 drivers/base/power/wakeup.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index d1283ff1080b..9316de561bcc 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -1008,6 +1008,8 @@ bool pm_save_wakeup_count(unsigned int count)
 	if (cnt == count && inpr == 0) {
 		saved_count = count;
 		events_check_enabled = true;
+	} else if (cnt == UINT_MAX) {
+		pm_system_wakeup();
 	}
 	raw_spin_unlock_irqrestore(&events_lock, flags);
 	return events_check_enabled;
-- 
2.50.0.727.gbf7dc18ff4-goog
Re: [RFC PATCH v1] PM: wakeup: Provide interface for userspace to abort suspend
Posted by Rafael J. Wysocki 2 months, 2 weeks ago
On Fri, Jul 18, 2025 at 9:18 AM Saravana Kannan <saravanak@google.com> wrote:
>
> Once suspend starts, it can take a while before file system sync
> finishes and all the userspace threads are frozen. During this time,
> there can be events that originate in userspace that would require the
> suspend to be aborted.
>
> The only way to abort suspend from userspace as of today is to grab
> and release a kernel wakelock using the /sys/power/wake_lock and
> /sys/power/wake_unlock files. This has the disadvantage of:
>
> * Doing the useless work of creating and destroying wakelocks.
> * If the userspace entity crashes after the wake lock is created, we
>   get a wake lock/memory leak.

But wakelocks are for this purpose.

> To avoid all this and simplify the interface, this patch allows
> canceling a suspend by writing UINT_MAX value to the
> /sys/power/wakeup_count that is meant for tracking wakeup events.
>
> Signed-off-by: Saravana Kannan <saravanak@google.com>
> ---
>
> Rafael,
>
> If the idea looks good to you, I can also update Documentation and sent
> it as a non-RFC patch. I'm not too tied on what file we use to trigger
> an abort from userspace as long as it's possible.

I would rather add an interface based on a special device file for
wakelocks to address this.

For example, open it to create a wakelock with the name of a calling
process, write 1 to it to block suspending, write 0 to it to unblock,
close to remove it.

Then it will go away automatically when the process exits.

>  drivers/base/power/wakeup.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
> index d1283ff1080b..9316de561bcc 100644
> --- a/drivers/base/power/wakeup.c
> +++ b/drivers/base/power/wakeup.c
> @@ -1008,6 +1008,8 @@ bool pm_save_wakeup_count(unsigned int count)
>         if (cnt == count && inpr == 0) {
>                 saved_count = count;
>                 events_check_enabled = true;
> +       } else if (cnt == UINT_MAX) {
> +               pm_system_wakeup();
>         }
>         raw_spin_unlock_irqrestore(&events_lock, flags);
>         return events_check_enabled;
> --
> 2.50.0.727.gbf7dc18ff4-goog
>
>
Re: [RFC PATCH v1] PM: wakeup: Provide interface for userspace to abort suspend
Posted by Saravana Kannan 2 months, 2 weeks ago
On Mon, Jul 21, 2025 at 12:51 PM Rafael J. Wysocki <rafael@kernel.org> wrote:

Thanks for responding to my RFC!

>
> On Fri, Jul 18, 2025 at 9:18 AM Saravana Kannan <saravanak@google.com> wrote:
> >
> > Once suspend starts, it can take a while before file system sync
> > finishes and all the userspace threads are frozen. During this time,
> > there can be events that originate in userspace that would require the
> > suspend to be aborted.
> >
> > The only way to abort suspend from userspace as of today is to grab
> > and release a kernel wakelock using the /sys/power/wake_lock and
> > /sys/power/wake_unlock files. This has the disadvantage of:
> >
> > * Doing the useless work of creating and destroying wakelocks.
> > * If the userspace entity crashes after the wake lock is created, we
> >   get a wake lock/memory leak.
>
> But wakelocks are for this purpose.

Right, wakelocks might be working as intended where they don't go away
if the userspace process crashes.

>
> > To avoid all this and simplify the interface, this patch allows
> > canceling a suspend by writing UINT_MAX value to the
> > /sys/power/wakeup_count that is meant for tracking wakeup events.
> >
> > Signed-off-by: Saravana Kannan <saravanak@google.com>
> > ---
> >
> > Rafael,
> >
> > If the idea looks good to you, I can also update Documentation and sent
> > it as a non-RFC patch. I'm not too tied on what file we use to trigger
> > an abort from userspace as long as it's possible.
>
> I would rather add an interface based on a special device file for
> wakelocks to address this.

While the device file based approach for creating kernel wakelocks
from userspace might be cleaner, this patch isn't trying to address
that though. We already have a UAPI for that and the userspace suspend
managers use it.

>
> For example, open it to create a wakelock with the name of a calling
> process, write 1 to it to block suspending, write 0 to it to unblock,
> close to remove it.
>
> Then it will go away automatically when the process exits.

The scenario this patch is trying to address is to abort a suspend
that was initiated by userspace (system with CONFIG_PM_AUTOSLEEP
disabled). It's not really a kernel wakelock request asking the kernel
to keep the system from suspending -- it doesn't need to because
CONFIG_PM_AUTOSLEEP is disabled. And we certainly don't want to create
a kernel wakelock for every single user space wakelock. That's a lot
of unnecessary overhead.

Another way to look at this is that we have a way to initiate suspend
by writing "mem" to /sys/power/state, but we don't have any way to
abort it. Another version of this patch that I was considering was to
write "abort" to /sys/power/state to abort an ongoing suspend. Would
that version of the patch make more sense to you?

Thanks,
Saravana


>
> >  drivers/base/power/wakeup.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
> > index d1283ff1080b..9316de561bcc 100644
> > --- a/drivers/base/power/wakeup.c
> > +++ b/drivers/base/power/wakeup.c
> > @@ -1008,6 +1008,8 @@ bool pm_save_wakeup_count(unsigned int count)
> >         if (cnt == count && inpr == 0) {
> >                 saved_count = count;
> >                 events_check_enabled = true;
> > +       } else if (cnt == UINT_MAX) {
> > +               pm_system_wakeup();
> >         }
> >         raw_spin_unlock_irqrestore(&events_lock, flags);
> >         return events_check_enabled;
> > --
> > 2.50.0.727.gbf7dc18ff4-goog
> >
> >
Re: [RFC PATCH v1] PM: wakeup: Provide interface for userspace to abort suspend
Posted by Saravana Kannan 2 months, 2 weeks ago
On Fri, Jul 18, 2025 at 12:18 AM Saravana Kannan <saravanak@google.com> wrote:
>
> Once suspend starts, it can take a while before file system sync
> finishes and all the userspace threads are frozen. During this time,
> there can be events that originate in userspace that would require the
> suspend to be aborted.
>
> The only way to abort suspend from userspace as of today is to grab
> and release a kernel wakelock using the /sys/power/wake_lock and
> /sys/power/wake_unlock files. This has the disadvantage of:
>
> * Doing the useless work of creating and destroying wakelocks.
> * If the userspace entity crashes after the wake lock is created, we
>   get a wake lock/memory leak.
>
> To avoid all this and simplify the interface, this patch allows
> canceling a suspend by writing UINT_MAX value to the
> /sys/power/wakeup_count that is meant for tracking wakeup events.
>
> Signed-off-by: Saravana Kannan <saravanak@google.com>
> ---
>
> Rafael,
>
> If the idea looks good to you, I can also update Documentation and sent
> it as a non-RFC patch. I'm not too tied on what file we use to trigger
> an abort from userspace as long as it's possible.
>
> Thanks,
> Saravana
>
>  drivers/base/power/wakeup.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
> index d1283ff1080b..9316de561bcc 100644
> --- a/drivers/base/power/wakeup.c
> +++ b/drivers/base/power/wakeup.c
> @@ -1008,6 +1008,8 @@ bool pm_save_wakeup_count(unsigned int count)
>         if (cnt == count && inpr == 0) {
>                 saved_count = count;
>                 events_check_enabled = true;
> +       } else if (cnt == UINT_MAX) {

Sorry, to match what I said in the commit text, this should be count
== UINT_MAX.

-Saravana

> +               pm_system_wakeup();
>         }
>         raw_spin_unlock_irqrestore(&events_lock, flags);
>         return events_check_enabled;
> --
> 2.50.0.727.gbf7dc18ff4-goog
>