mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v7 0/2] PM: Support aborting sleep during filesystem sync
@ 2025-11-19 17:14 Samuel Wu
  2025-11-19 17:14 ` [PATCH v7 1/2] PM: Add framework to abort during fs_sync Samuel Wu
                   ` (2 more replies)
  0 siblings, 3 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

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()

Changes in v7:
- Switched to polling for wakeup/fs_sync finishing per Rafael's patch in v6
- Added header files for wait queue and atomics (modify Rafael's patch)
- Cleaned up wq on error in pm_start_workqueues (modify Rafael's patch)
- Changed atomic_add_return(-1, cnt) == 0 to atomic_dec_and_test(cnt) (modify
  Rafael's patch)
- v6 link: https://lore.kernel.org/all/20251030210110.298612-1-wusamuel@google.com/

Changes in v6:
- Use spin_lock_irq() in thread context
- Use dedicated ordered workqueue for sync work items
- Use a counter instead of two bools for synchronization
- Queue fs_sync if it's not already pending on workqueue
- pm_wakeup_clear(0) is prequisite to this feature, so move it within function
- Updated commit text for motive of back-to-back fs syncs
- Tighter lock/unlock around setup, checks, and loop
- Fix function definitions for CONFIG_PM_SLEEP=n
- v5 link: https://lore.kernel.org/all/20251017233907.2305303-1-wusamuel@google.com/

Changes in v5:
- Update spin_lock() to spin_lock_irqsave() since abort can be in IRQ context
- Updated changelog description to be more precise regarding continuing abort
  sleep before fs_sync() is complete
- Rename abort_sleep_during_fs_sync() to pm_stop_waiting_for_fs_sync()
- Simplify from a goto to do-while in pm_sleep_fs_sync()
- v4 link: https://lore.kernel.org/all/20250911185314.2377124-1-wusamuel@google.com

Changes in v4:
- Removed patch 1/3 of v3 as it is already picked up on linux-pm
- Squashed patches 2/3 and 3/3 from v3 into this single patch
- Added abort during fs_sync functionality to hibernate in addition to suspend
- Moved variables and functions for abort from power/suspend.c to power/main.c
- Renamed suspend_fs_sync_with_abort() to pm_sleep_fs_sync()
- Renamed suspend_abort_fs_sync() to abort_sleep_during_fs_sync()
- v3 link: https://lore.kernel.org/all/20250821004237.2712312-1-wusamuel@google.com/

Changes in v3:
- Split v2 patch into 3 patches
- Moved pm_wakeup_clear() outside of if(sync_on_suspend_enabled) condition
- Updated documentation and comments within kernel/power/suspend.c
- v2 link: https://lore.kernel.org/all/20250812232126.1814253-1-wusamuel@google.com/

Changes in v2:
- Added documentation for suspend_abort_fs_sync()
- Made suspend_fs_sync_lock and suspend_fs_sync_complete declaration static
- v1 link: https://lore.kernel.org/all/20250815004635.3684650-1-wusamuel@google.com

 kernel/power/hibernate.c |  6 +++-
 kernel/power/main.c      | 77 ++++++++++++++++++++++++++++++++++++----
 kernel/power/power.h     |  1 +
 kernel/power/suspend.c   |  6 +++-
 kernel/power/user.c      |  4 ++-
 5 files changed, 84 insertions(+), 10 deletions(-)

--
2.52.0.rc1.455.g30608eb744-goog


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [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

end of thread, other threads:[~2025-11-20 21:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH v7 0/2] PM: Support aborting sleep during filesystem sync Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®