* [PATCH v7 1/2] PM: Add framework to abort during fs_sync
2025-11-19 17:14 [PATCH v7 0/2] PM: Support aborting sleep during filesystem sync Samuel Wu
@ 2025-11-19 17:14 ` Samuel Wu
2025-11-19 17:14 ` [PATCH v7 2/2] PM: Call pm_sleep_fs_sync() instead of ksys_sync_helper() Samuel Wu
2025-11-20 21:35 ` [PATCH v7 0/2] PM: Support aborting sleep during filesystem sync Rafael J. Wysocki
2 siblings, 0 replies; 4+ messages in thread
From: Samuel Wu @ 2025-11-19 17:14 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek
Cc: tuhaowen, Samuel Wu, Saravana Kannan, Rafael J. Wysocki,
kernel-team, linux-pm, linux-kernel
Add helper function pm_sleep_fs_sync() and related data structures to
setup a framework that allows for aborting suspend and hibernate during
their filesystem sync phase.
Suggested-by: Saravana Kannan <saravanak@google.com>
Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Samuel Wu <wusamuel@google.com>
---
kernel/power/main.c | 79 ++++++++++++++++++++++++++++++++++++++++----
kernel/power/power.h | 1 +
2 files changed, 74 insertions(+), 6 deletions(-)
diff --git a/kernel/power/main.c b/kernel/power/main.c
index a6cbc3f4347a..03b2c5495c77 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -18,6 +18,8 @@
#include <linux/suspend.h>
#include <linux/syscalls.h>
#include <linux/pm_runtime.h>
+#include <linux/atomic.h>
+#include <linux/wait.h>
#include "power.h"
@@ -92,6 +94,61 @@ void ksys_sync_helper(void)
}
EXPORT_SYMBOL_GPL(ksys_sync_helper);
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_HIBERNATION)
+/* Wakeup events handling resolution while syncing file systems in jiffies */
+#define PM_FS_SYNC_WAKEUP_RESOLUTION 5
+
+static atomic_t pm_fs_sync_count = ATOMIC_INIT(0);
+static struct workqueue_struct *pm_fs_sync_wq;
+static DECLARE_WAIT_QUEUE_HEAD(pm_fs_sync_wait);
+
+static bool pm_fs_sync_completed(void)
+{
+ return atomic_read(&pm_fs_sync_count) == 0;
+}
+
+static void pm_fs_sync_work_fn(struct work_struct *work)
+{
+ ksys_sync_helper();
+
+ if (atomic_dec_and_test(&pm_fs_sync_count))
+ wake_up(&pm_fs_sync_wait);
+}
+static DECLARE_WORK(pm_fs_sync_work, pm_fs_sync_work_fn);
+
+/**
+ * pm_sleep_fs_sync() - Sync file systems in an interruptible way
+ *
+ * Return: 0 on successful file system sync, or -EBUSY if the file system sync
+ * was aborted.
+ */
+int pm_sleep_fs_sync(void)
+{
+ pm_wakeup_clear(0);
+
+ /*
+ * Take back-to-back sleeps into account by queuing a subsequent fs sync
+ * only if the previous fs sync is running or is not queued. Multiple fs
+ * syncs increase the likelihood of saving the latest files immediately
+ * before sleep.
+ */
+ if (!work_pending(&pm_fs_sync_work)) {
+ atomic_inc(&pm_fs_sync_count);
+ queue_work(pm_fs_sync_wq, &pm_fs_sync_work);
+ }
+
+ while (!pm_fs_sync_completed()) {
+ if (pm_wakeup_pending())
+ return -EBUSY;
+
+ wait_event_timeout(pm_fs_sync_wait, pm_fs_sync_completed(),
+ PM_FS_SYNC_WAKEUP_RESOLUTION);
+ }
+
+ return 0;
+}
+#endif /* CONFIG_SUSPEND || CONFIG_HIBERNATION */
+
/* Routines for PM-transition notifications */
static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
@@ -231,10 +288,10 @@ static ssize_t mem_sleep_store(struct kobject *kobj, struct kobj_attribute *attr
power_attr(mem_sleep);
/*
- * sync_on_suspend: invoke ksys_sync_helper() before suspend.
+ * sync_on_suspend: Sync file systems before suspend.
*
- * show() returns whether ksys_sync_helper() is invoked before suspend.
- * store() accepts 0 or 1. 0 disables ksys_sync_helper() and 1 enables it.
+ * show() returns whether file systems sync before suspend is enabled.
+ * store() accepts 0 or 1. 0 disables file systems sync and 1 enables it.
*/
bool sync_on_suspend_enabled = !IS_ENABLED(CONFIG_SUSPEND_SKIP_SYNC);
@@ -1066,16 +1123,26 @@ static const struct attribute_group *attr_groups[] = {
struct workqueue_struct *pm_wq;
EXPORT_SYMBOL_GPL(pm_wq);
-static int __init pm_start_workqueue(void)
+static int __init pm_start_workqueues(void)
{
pm_wq = alloc_workqueue("pm", WQ_FREEZABLE | WQ_UNBOUND, 0);
+ if (!pm_wq)
+ return -ENOMEM;
- return pm_wq ? 0 : -ENOMEM;
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_HIBERNATION)
+ pm_fs_sync_wq = alloc_ordered_workqueue("pm_fs_sync", 0);
+ if (!pm_fs_sync_wq) {
+ destroy_workqueue(pm_wq);
+ return -ENOMEM;
+ }
+#endif
+
+ return 0;
}
static int __init pm_init(void)
{
- int error = pm_start_workqueue();
+ int error = pm_start_workqueues();
if (error)
return error;
hibernate_image_size_init();
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 7ccd709af93f..75b63843886e 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -19,6 +19,7 @@ struct swsusp_info {
} __aligned(PAGE_SIZE);
#if defined(CONFIG_SUSPEND) || defined(CONFIG_HIBERNATION)
+extern int pm_sleep_fs_sync(void);
extern bool filesystem_freeze_enabled;
#endif
--
2.52.0.rc1.455.g30608eb744-goog
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH v7 2/2] PM: Call pm_sleep_fs_sync() instead of ksys_sync_helper()
2025-11-19 17:14 [PATCH v7 0/2] PM: Support aborting sleep during filesystem sync Samuel Wu
2025-11-19 17:14 ` [PATCH v7 1/2] PM: Add framework to abort during fs_sync Samuel Wu
@ 2025-11-19 17:14 ` Samuel Wu
2025-11-20 21:35 ` [PATCH v7 0/2] PM: Support aborting sleep during filesystem sync Rafael J. Wysocki
2 siblings, 0 replies; 4+ messages in thread
From: Samuel Wu @ 2025-11-19 17:14 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Pavel Machek
Cc: tuhaowen, Samuel Wu, Saravana Kannan, Rafael J. Wysocki,
kernel-team, linux-pm, linux-kernel
Replace the direct calls to ksys_sync_helper() with the new
pm_sleep_fs_sync() in suspend, hibernation, and snapshot code paths.
This enables the new polling mechanism that allows for the filesystem
sync phase to be interrupted.
Suggested-by: Saravana Kannan <saravanak@google.com>
Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Samuel Wu <wusamuel@google.com>
---
kernel/power/hibernate.c | 6 +++++-
kernel/power/suspend.c | 6 +++++-
kernel/power/user.c | 4 +++-
3 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 26e45f86b955..af8d07bafe02 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -820,7 +820,10 @@ int hibernate(void)
if (error)
goto Restore;
- ksys_sync_helper();
+ error = pm_sleep_fs_sync();
+ if (error)
+ goto Notify;
+
filesystems_freeze(filesystem_freeze_enabled);
error = freeze_processes();
@@ -891,6 +894,7 @@ int hibernate(void)
freezer_test_done = false;
Exit:
filesystems_thaw();
+ Notify:
pm_notifier_call_chain(PM_POST_HIBERNATION);
Restore:
pm_restore_console();
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index d9461447e37b..2da4482bb6eb 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -593,7 +593,11 @@ static int enter_state(suspend_state_t state)
if (sync_on_suspend_enabled) {
trace_suspend_resume(TPS("sync_filesystems"), 0, true);
- ksys_sync_helper();
+
+ error = pm_sleep_fs_sync();
+ if (error)
+ goto Unlock;
+
trace_suspend_resume(TPS("sync_filesystems"), 0, false);
}
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 3f9e3efb9f6e..4401cfe26e5c 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -278,7 +278,9 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
if (data->frozen)
break;
- ksys_sync_helper();
+ error = pm_sleep_fs_sync();
+ if (error)
+ break;
error = freeze_processes();
if (error)
--
2.52.0.rc1.455.g30608eb744-goog
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH v7 0/2] PM: Support aborting sleep during filesystem sync
2025-11-19 17:14 [PATCH v7 0/2] PM: Support aborting sleep during filesystem sync Samuel Wu
2025-11-19 17:14 ` [PATCH v7 1/2] PM: Add framework to abort during fs_sync Samuel Wu
2025-11-19 17:14 ` [PATCH v7 2/2] PM: Call pm_sleep_fs_sync() instead of ksys_sync_helper() Samuel Wu
@ 2025-11-20 21:35 ` Rafael J. Wysocki
2 siblings, 0 replies; 4+ messages in thread
From: Rafael J. Wysocki @ 2025-11-20 21:35 UTC (permalink / raw)
To: Samuel Wu
Cc: Rafael J. Wysocki, Len Brown, Pavel Machek, tuhaowen,
Saravana Kannan, Rafael J. Wysocki, kernel-team, linux-pm,
linux-kernel
On Wed, Nov 19, 2025 at 6:14 PM Samuel Wu <wusamuel@google.com> wrote:
>
> At the start of suspend and hibernate, filesystems will sync to save the
> current state of the device. However, the long tail of the filesystem
> sync can take upwards of 25 seconds. If during this filesystem sync
> there is some wakeup signal, it will not be processed until the sync is
> complete; from a user's perspective, this looks like the device is
> unresponsive to any form of input.
>
> This patch adds functionality to handle a sleep abort signal when in
> the filesystem sync phase of suspend or hibernate. This topic was first
> discussed by Saravana Kannan at LPC 2024 [1], where the general
> consensus was to allow filesystem sync on a parallel thread. In case of
> a wakeup signal, the suspend process will stop waiting on an in-progress
> filesystem sync, and instead abort suspend before the filesystem sync is
> complete.
>
> Furthermore, in the case of the back-to-back sleeps, a subsequent
> filesystem sync is enqueued to ensure the latest files are synced right
> before sleep. The framework still allows for an early abort in this case.
>
> [1]: https://lpc.events/event/18/contributions/1845/
>
> Suggested-by: Saravana Kannan <saravanak@google.com>
> Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Signed-off-by: Samuel Wu <wusamuel@google.com>
>
> Samuel Wu (2):
> PM: Add framework to abort during fs_sync
> PM: Call pm_sleep_fs_sync() instead of ksys_sync_helper()
Both patches applied as 6.19 material with updated subjects and
changelogs, thanks!
^ permalink raw reply [flat|nested] 4+ messages in thread