* [PATCH] PM: hibernate: Freeze kernel threads after image preallocation
@ 2026-09-20 14:35 Florian Schmaus via B4 Relay
2026-09-21 19:19 ` Mario Limonciello
0 siblings, 1 reply; 2+ messages in thread
From: Florian Schmaus via B4 Relay @ 2026-09-20 14:35 UTC (permalink / raw)
To: Rafael J. Wysocki, Pavel Machek, Len Brown, Matthew Leach,
Mario Limonciello (AMD)
Cc: Rafael J. Wysocki, linux-pm, linux-kernel, Florian Schmaus
From: Florian Schmaus <flo@geekplace.eu>
Commit 783c81098445 ("PM: hibernate: call preallocate_image() after freeze
prepare") moved hibernate_preallocate_memory() after dpm_prepare() so
that device drivers have the opportunity to release pinned/unswappable
memory during their ->prepare() callback before memory is preallocated
for the snapshot image.
However, that commit also placed hibernate_preallocate_memory() after
freeze_kernel_threads(). While it was assumed during review that swap
I/O submitted via submit_bio() is synchronous and would not depend on
frozen kernel threads, this does not hold in practice. Calling
hibernate_preallocate_memory() with kernel threads frozen leads to
intermittent deadlocks during hibernation.
Inside hibernate_preallocate_memory(), shrink_all_memory() is invoked with
.may_writepage = 1 and .may_swap = 1 to aggressively reclaim and swap out
pages. Any writeback or swap I/O that relies on freezable kernel threads,
block device helpers, or WQ_FREEZABLE workqueues (such as those in storage
drivers, device mapper, or filesystems) deadlocks waiting on tasks that
are stuck in the refrigerator.
Fix this by reordering hibernation_snapshot():
1. Call dpm_prepare(PMSG_FREEZE) first, allowing device drivers to release
pinned resources while kernel threads are still active.
2. Call hibernate_preallocate_memory() second, performing page reclaim and
swapout while storage layers, workqueues, and kernel threads are alive.
3. Call freeze_kernel_threads() third, only after all memory preallocation
and swap I/O have completed.
Additionally, restore the call to swsusp_free() in the cleanup path so
that preallocated image memory is properly freed if freeze_kernel_threads()
fails or if TEST_FREEZER is enabled.
Fixes: 783c81098445 ("PM: hibernate: call preallocate_image() after freeze prepare")
Signed-off-by: Florian Schmaus <flo@geekplace.eu>
---
During the review of commit 783c81098445 ("PM: hibernate: call
preallocate_image() after freeze prepare") [1], concerns were raised
regarding whether memory reclaim and swap I/O could deadlock if kernel
threads were already frozen.
At the time, it was thought that pageout to swap would not depend on
frozen threads. However, on Linux 7.2, I ran into reliable issues with
suspend-to-disk hanging during hibernation. Reordering the sequence so
that kernel threads are frozen after image preallocation (as done in
this patch) fixes the issue for me.
This patch restores the ordering where kernel threads are frozen only after
memory preallocation and swap I/O have completed, while keeping the
benefit of calling dpm_prepare() beforehand so drivers can release pinned
pages.
[1] https://patch.msgid.link/20260403-hibernation-fixes-v3-1-31bc9fa3ba2d@collabora.com
---
kernel/power/hibernate.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index d2479c69d71a..c13f68ab7f6e 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -408,9 +408,18 @@ int hibernation_snapshot(int platform_mode)
if (error)
goto Close;
+ error = dpm_prepare(PMSG_FREEZE);
+ if (error)
+ goto Complete;
+
+ /* Preallocate image memory before freezing kernel threads and shutting down devices. */
+ error = hibernate_preallocate_memory();
+ if (error)
+ goto Complete;
+
error = freeze_kernel_threads();
if (error)
- goto Close;
+ goto Cleanup;
if (hibernation_test(TEST_FREEZER)) {
@@ -422,15 +431,6 @@ int hibernation_snapshot(int platform_mode)
goto Thaw;
}
- error = dpm_prepare(PMSG_FREEZE);
- if (error)
- goto Complete;
-
- /* Preallocate image memory before shutting down devices. */
- error = hibernate_preallocate_memory();
- if (error)
- goto Complete;
-
console_suspend_all();
pm_restrict_gfp_mask();
@@ -464,10 +464,12 @@ int hibernation_snapshot(int platform_mode)
platform_end(platform_mode);
return error;
- Complete:
- dpm_complete(PMSG_RECOVER);
Thaw:
thaw_kernel_threads();
+ Cleanup:
+ swsusp_free();
+ Complete:
+ dpm_complete(PMSG_RECOVER);
goto Close;
}
---
base-commit: 40288c9206c17eb66a603262e06a58d300d0f279
change-id: 20260915-fix-hibernation-aad94ce17506
Best regards,
--
Florian Schmaus <flo@geekplace.eu>
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] PM: hibernate: Freeze kernel threads after image preallocation
2026-09-20 14:35 [PATCH] PM: hibernate: Freeze kernel threads after image preallocation Florian Schmaus via B4 Relay
@ 2026-09-21 19:19 ` Mario Limonciello
0 siblings, 0 replies; 2+ messages in thread
From: Mario Limonciello @ 2026-09-21 19:19 UTC (permalink / raw)
To: flo, Rafael J. Wysocki, Pavel Machek, Len Brown, Matthew Leach
Cc: Rafael J. Wysocki, linux-pm, linux-kernel
On 9/20/26 09:35, Florian Schmaus via B4 Relay wrote:
> From: Florian Schmaus <flo@geekplace.eu>
>
> Commit 783c81098445 ("PM: hibernate: call preallocate_image() after freeze
> prepare") moved hibernate_preallocate_memory() after dpm_prepare() so
> that device drivers have the opportunity to release pinned/unswappable
> memory during their ->prepare() callback before memory is preallocated
> for the snapshot image.
>
> However, that commit also placed hibernate_preallocate_memory() after
> freeze_kernel_threads(). While it was assumed during review that swap
> I/O submitted via submit_bio() is synchronous and would not depend on
> frozen kernel threads, this does not hold in practice. Calling
> hibernate_preallocate_memory() with kernel threads frozen leads to
> intermittent deadlocks during hibernation.
>
> Inside hibernate_preallocate_memory(), shrink_all_memory() is invoked with
> .may_writepage = 1 and .may_swap = 1 to aggressively reclaim and swap out
> pages. Any writeback or swap I/O that relies on freezable kernel threads,
> block device helpers, or WQ_FREEZABLE workqueues (such as those in storage
> drivers, device mapper, or filesystems) deadlocks waiting on tasks that
> are stuck in the refrigerator.
>
> Fix this by reordering hibernation_snapshot():
> 1. Call dpm_prepare(PMSG_FREEZE) first, allowing device drivers to release
> pinned resources while kernel threads are still active.
> 2. Call hibernate_preallocate_memory() second, performing page reclaim and
> swapout while storage layers, workqueues, and kernel threads are alive.
> 3. Call freeze_kernel_threads() third, only after all memory preallocation
> and swap I/O have completed.
>
> Additionally, restore the call to swsusp_free() in the cleanup path so
> that preallocated image memory is properly freed if freeze_kernel_threads()
> fails or if TEST_FREEZER is enabled.
>
> Fixes: 783c81098445 ("PM: hibernate: call preallocate_image() after freeze prepare")
> Signed-off-by: Florian Schmaus <flo@geekplace.eu>
> ---
> During the review of commit 783c81098445 ("PM: hibernate: call
> preallocate_image() after freeze prepare") [1], concerns were raised
> regarding whether memory reclaim and swap I/O could deadlock if kernel
> threads were already frozen.
>
> At the time, it was thought that pageout to swap would not depend on
> frozen threads. However, on Linux 7.2, I ran into reliable issues with
> suspend-to-disk hanging during hibernation. Reordering the sequence so
> that kernel threads are frozen after image preallocation (as done in
> this patch) fixes the issue for me.
>
> This patch restores the ordering where kernel threads are frozen only after
> memory preallocation and swap I/O have completed, while keeping the
> benefit of calling dpm_prepare() beforehand so drivers can release pinned
> pages.
>
> [1] https://patch.msgid.link/20260403-hibernation-fixes-v3-1-31bc9fa3ba2d@collabora.com
> ---
> kernel/power/hibernate.c | 26 ++++++++++++++------------
> 1 file changed, 14 insertions(+), 12 deletions(-)
>
> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> index d2479c69d71a..c13f68ab7f6e 100644
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -408,9 +408,18 @@ int hibernation_snapshot(int platform_mode)
> if (error)
> goto Close;
>
> + error = dpm_prepare(PMSG_FREEZE);
> + if (error)
> + goto Complete;
> +
> + /* Preallocate image memory before freezing kernel threads and shutting down devices. */
> + error = hibernate_preallocate_memory();
> + if (error)
> + goto Complete;
> +
> error = freeze_kernel_threads();
> if (error)
> - goto Close;
> + goto Cleanup;
>
> if (hibernation_test(TEST_FREEZER)) {
>
> @@ -422,15 +431,6 @@ int hibernation_snapshot(int platform_mode)
> goto Thaw;
> }
>
> - error = dpm_prepare(PMSG_FREEZE);
> - if (error)
> - goto Complete;
> -
> - /* Preallocate image memory before shutting down devices. */
> - error = hibernate_preallocate_memory();
> - if (error)
> - goto Complete;
> -
> console_suspend_all();
> pm_restrict_gfp_mask();
>
> @@ -464,10 +464,12 @@ int hibernation_snapshot(int platform_mode)
> platform_end(platform_mode);
> return error;
>
> - Complete:
> - dpm_complete(PMSG_RECOVER);
> Thaw:
> thaw_kernel_threads();
> + Cleanup:
> + swsusp_free();
> + Complete:
> + dpm_complete(PMSG_RECOVER);
> goto Close;
> }
>
>
> ---
> base-commit: 40288c9206c17eb66a603262e06a58d300d0f279
> change-id: 20260915-fix-hibernation-aad94ce17506
>
> Best regards,
> --
> Florian Schmaus <flo@geekplace.eu>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-21 19:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-20 14:35 [PATCH] PM: hibernate: Freeze kernel threads after image preallocation Florian Schmaus via B4 Relay
2026-09-21 19:19 ` Mario Limonciello
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®