* [PATCH v1] PM: sleep: Allow pm_restrict_gfp_mask() stacking
@ 2025-10-28 20:52 Rafael J. Wysocki
2025-10-29 15:22 ` Mario Limonciello
2025-10-30 19:49 ` Kenneth Crudup
0 siblings, 2 replies; 4+ messages in thread
From: Rafael J. Wysocki @ 2025-10-28 20:52 UTC (permalink / raw)
To: Linux PM; +Cc: Askar Safin, Mario Limonciello, LKML
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Allow pm_restrict_gfp_mask() to be called many times in a row to avoid
issues with calling dpm_suspend_start() when the GFP mask has been
already restricted.
Only the first invocation of pm_restrict_gfp_mask() will actually
restrict the GFP mask and the subsequent calls will warn if there is
a mismatch between the expected allowed GFP mask and the actual one.
Moreover, if pm_restrict_gfp_mask() is called many times in a row,
pm_restore_gfp_mask() needs to be called matching number of times in
a row to actually restore the GFP mask. Calling it when the GFP mask
has not been restricted will cause it to warn.
This is necessary for the GFP mask restriction starting in
hibernation_snapshot() to continue throughout the entire hibernation
flow until it completes or it is aborted (either by a wakeup event or
by an error).
Fixes: 449c9c02537a1 ("PM: hibernate: Restrict GFP mask in hibernation_snapshot()")
Fixes: 469d80a3712c ("PM: hibernate: Fix hybrid-sleep")
Reported-by: Askar Safin <safinaskar@gmail.com>
Closes: https://lore.kernel.org/linux-pm/20251025050812.421905-1-safinaskar@gmail.com/
Link: https://lore.kernel.org/linux-pm/20251028111730.2261404-1-safinaskar@gmail.com/
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
This supersedes
https://lore.kernel.org/linux-pm/20251026033115.436448-1-superm1@kernel.org/
as it allows the GFP mask to be restricted across the entire hibernation path.
---
kernel/power/hibernate.c | 4 ----
kernel/power/main.c | 22 +++++++++++++++++-----
2 files changed, 17 insertions(+), 9 deletions(-)
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -706,7 +706,6 @@ static void power_down(void)
#ifdef CONFIG_SUSPEND
if (hibernation_mode == HIBERNATION_SUSPEND) {
- pm_restore_gfp_mask();
error = suspend_devices_and_enter(mem_sleep_current);
if (!error)
goto exit;
@@ -746,9 +745,6 @@ static void power_down(void)
cpu_relax();
exit:
- /* Match the pm_restore_gfp_mask() call in hibernate(). */
- pm_restrict_gfp_mask();
-
/* Restore swap signature. */
error = swsusp_unmark();
if (error)
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -31,23 +31,35 @@
* held, unless the suspend/hibernate code is guaranteed not to run in parallel
* with that modification).
*/
+static unsigned int saved_gfp_count;
static gfp_t saved_gfp_mask;
void pm_restore_gfp_mask(void)
{
WARN_ON(!mutex_is_locked(&system_transition_mutex));
- if (saved_gfp_mask) {
- gfp_allowed_mask = saved_gfp_mask;
- saved_gfp_mask = 0;
- }
+
+ if (WARN_ON(!saved_gfp_count) || --saved_gfp_count)
+ return;
+
+ gfp_allowed_mask = saved_gfp_mask;
+ saved_gfp_mask = 0;
+
+ pm_pr_dbg("GFP mask restored\n");
}
void pm_restrict_gfp_mask(void)
{
WARN_ON(!mutex_is_locked(&system_transition_mutex));
- WARN_ON(saved_gfp_mask);
+
+ if (saved_gfp_count++) {
+ WARN_ON((saved_gfp_mask & ~(__GFP_IO | __GFP_FS)) != gfp_allowed_mask);
+ return;
+ }
+
saved_gfp_mask = gfp_allowed_mask;
gfp_allowed_mask &= ~(__GFP_IO | __GFP_FS);
+
+ pm_pr_dbg("GFP mask restricted\n");
}
unsigned int lock_system_sleep(void)
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v1] PM: sleep: Allow pm_restrict_gfp_mask() stacking
2025-10-28 20:52 [PATCH v1] PM: sleep: Allow pm_restrict_gfp_mask() stacking Rafael J. Wysocki
@ 2025-10-29 15:22 ` Mario Limonciello
2025-10-29 16:07 ` Rafael J. Wysocki
2025-10-30 19:49 ` Kenneth Crudup
1 sibling, 1 reply; 4+ messages in thread
From: Mario Limonciello @ 2025-10-29 15:22 UTC (permalink / raw)
To: Rafael J. Wysocki, Linux PM; +Cc: Askar Safin, LKML
On 10/28/25 3:52 PM, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Allow pm_restrict_gfp_mask() to be called many times in a row to avoid
> issues with calling dpm_suspend_start() when the GFP mask has been
> already restricted.
>
> Only the first invocation of pm_restrict_gfp_mask() will actually
> restrict the GFP mask and the subsequent calls will warn if there is
> a mismatch between the expected allowed GFP mask and the actual one.
>
> Moreover, if pm_restrict_gfp_mask() is called many times in a row,
> pm_restore_gfp_mask() needs to be called matching number of times in
> a row to actually restore the GFP mask. Calling it when the GFP mask
> has not been restricted will cause it to warn.
>
> This is necessary for the GFP mask restriction starting in
> hibernation_snapshot() to continue throughout the entire hibernation
> flow until it completes or it is aborted (either by a wakeup event or
> by an error).
>
> Fixes: 449c9c02537a1 ("PM: hibernate: Restrict GFP mask in hibernation_snapshot()")
> Fixes: 469d80a3712c ("PM: hibernate: Fix hybrid-sleep")
> Reported-by: Askar Safin <safinaskar@gmail.com>
> Closes: https://lore.kernel.org/linux-pm/20251025050812.421905-1-safinaskar@gmail.com/
> Link: https://lore.kernel.org/linux-pm/20251028111730.2261404-1-safinaskar@gmail.com/
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Great idea. Looks good to me, and it passes the S4 tests on my side.
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Tested-by: Mario Limonciello (AMD) <superm1@kernel.org>
> ---
>
> This supersedes
>
> https://lore.kernel.org/linux-pm/20251026033115.436448-1-superm1@kernel.org/
>
> as it allows the GFP mask to be restricted across the entire hibernation path.
>
> ---
> kernel/power/hibernate.c | 4 ----
> kernel/power/main.c | 22 +++++++++++++++++-----
> 2 files changed, 17 insertions(+), 9 deletions(-)
>
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -706,7 +706,6 @@ static void power_down(void)
>
> #ifdef CONFIG_SUSPEND
> if (hibernation_mode == HIBERNATION_SUSPEND) {
> - pm_restore_gfp_mask();
> error = suspend_devices_and_enter(mem_sleep_current);
> if (!error)
> goto exit;
> @@ -746,9 +745,6 @@ static void power_down(void)
> cpu_relax();
>
> exit:
> - /* Match the pm_restore_gfp_mask() call in hibernate(). */
> - pm_restrict_gfp_mask();
> -
> /* Restore swap signature. */
> error = swsusp_unmark();
> if (error)
> --- a/kernel/power/main.c
> +++ b/kernel/power/main.c
> @@ -31,23 +31,35 @@
> * held, unless the suspend/hibernate code is guaranteed not to run in parallel
> * with that modification).
> */
> +static unsigned int saved_gfp_count;
> static gfp_t saved_gfp_mask;
>
> void pm_restore_gfp_mask(void)
> {
> WARN_ON(!mutex_is_locked(&system_transition_mutex));
> - if (saved_gfp_mask) {
> - gfp_allowed_mask = saved_gfp_mask;
> - saved_gfp_mask = 0;
> - }
> +
> + if (WARN_ON(!saved_gfp_count) || --saved_gfp_count)
> + return;
> +
> + gfp_allowed_mask = saved_gfp_mask;
> + saved_gfp_mask = 0;
> +
> + pm_pr_dbg("GFP mask restored\n");
> }
>
> void pm_restrict_gfp_mask(void)
> {
> WARN_ON(!mutex_is_locked(&system_transition_mutex));
> - WARN_ON(saved_gfp_mask);
> +
> + if (saved_gfp_count++) {
> + WARN_ON((saved_gfp_mask & ~(__GFP_IO | __GFP_FS)) != gfp_allowed_mask);
> + return;
> + }
> +
> saved_gfp_mask = gfp_allowed_mask;
> gfp_allowed_mask &= ~(__GFP_IO | __GFP_FS);
> +
> + pm_pr_dbg("GFP mask restricted\n");
> }
>
> unsigned int lock_system_sleep(void)
>
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v1] PM: sleep: Allow pm_restrict_gfp_mask() stacking
2025-10-29 15:22 ` Mario Limonciello
@ 2025-10-29 16:07 ` Rafael J. Wysocki
0 siblings, 0 replies; 4+ messages in thread
From: Rafael J. Wysocki @ 2025-10-29 16:07 UTC (permalink / raw)
To: Mario Limonciello; +Cc: Rafael J. Wysocki, Linux PM, Askar Safin, LKML
On Wed, Oct 29, 2025 at 4:22 PM Mario Limonciello <superm1@kernel.org> wrote:
>
> On 10/28/25 3:52 PM, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Allow pm_restrict_gfp_mask() to be called many times in a row to avoid
> > issues with calling dpm_suspend_start() when the GFP mask has been
> > already restricted.
> >
> > Only the first invocation of pm_restrict_gfp_mask() will actually
> > restrict the GFP mask and the subsequent calls will warn if there is
> > a mismatch between the expected allowed GFP mask and the actual one.
> >
> > Moreover, if pm_restrict_gfp_mask() is called many times in a row,
> > pm_restore_gfp_mask() needs to be called matching number of times in
> > a row to actually restore the GFP mask. Calling it when the GFP mask
> > has not been restricted will cause it to warn.
> >
> > This is necessary for the GFP mask restriction starting in
> > hibernation_snapshot() to continue throughout the entire hibernation
> > flow until it completes or it is aborted (either by a wakeup event or
> > by an error).
> >
> > Fixes: 449c9c02537a1 ("PM: hibernate: Restrict GFP mask in hibernation_snapshot()")
> > Fixes: 469d80a3712c ("PM: hibernate: Fix hybrid-sleep")
> > Reported-by: Askar Safin <safinaskar@gmail.com>
> > Closes: https://lore.kernel.org/linux-pm/20251025050812.421905-1-safinaskar@gmail.com/
> > Link: https://lore.kernel.org/linux-pm/20251028111730.2261404-1-safinaskar@gmail.com/
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Great idea. Looks good to me, and it passes the S4 tests on my side.
>
> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
> Tested-by: Mario Limonciello (AMD) <superm1@kernel.org>
Great, thanks!
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v1] PM: sleep: Allow pm_restrict_gfp_mask() stacking
2025-10-28 20:52 [PATCH v1] PM: sleep: Allow pm_restrict_gfp_mask() stacking Rafael J. Wysocki
2025-10-29 15:22 ` Mario Limonciello
@ 2025-10-30 19:49 ` Kenneth Crudup
1 sibling, 0 replies; 4+ messages in thread
From: Kenneth Crudup @ 2025-10-30 19:49 UTC (permalink / raw)
To: Rafael J. Wysocki, Linux PM; +Cc: Askar Safin, Mario Limonciello, LKML
On 10/28/25 13:52, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Allow pm_restrict_gfp_mask() to be called many times in a row to avoid
> issues with calling dpm_suspend_start() when the GFP mask has been
> already restricted.
>
> Only the first invocation of pm_restrict_gfp_mask() will actually
> restrict the GFP mask and the subsequent calls will warn if there is
> a mismatch between the expected allowed GFP mask and the actual one.
>
> Moreover, if pm_restrict_gfp_mask() is called many times in a row,
> pm_restore_gfp_mask() needs to be called matching number of times in
> a row to actually restore the GFP mask. Calling it when the GFP mask
> has not been restricted will cause it to warn.
>
> This is necessary for the GFP mask restriction starting in
> hibernation_snapshot() to continue throughout the entire hibernation
> flow until it completes or it is aborted (either by a wakeup event or
> by an error).
>
> Fixes: 449c9c02537a1 ("PM: hibernate: Restrict GFP mask in hibernation_snapshot()")
> Fixes: 469d80a3712c ("PM: hibernate: Fix hybrid-sleep")
> Reported-by: Askar Safin <safinaskar@gmail.com>
> Closes: https://lore.kernel.org/linux-pm/20251025050812.421905-1-safinaskar@gmail.com/
> Link: https://lore.kernel.org/linux-pm/20251028111730.2261404-1-safinaskar@gmail.com/
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>
> This supersedes
>
> https://lore.kernel.org/linux-pm/20251026033115.436448-1-superm1@kernel.org/
>
> as it allows the GFP mask to be restricted across the entire hibernation path.
Tested-By: Kenneth R. Crudup <kenny@panix.com>
(Helgaas told me about "b4 shazam" and I've been applying all kinds of
interesting patches willy-nilly lately :) )
> ---
> kernel/power/hibernate.c | 4 ----
> kernel/power/main.c | 22 +++++++++++++++++-----
> 2 files changed, 17 insertions(+), 9 deletions(-)
>
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -706,7 +706,6 @@ static void power_down(void)
>
> #ifdef CONFIG_SUSPEND
> if (hibernation_mode == HIBERNATION_SUSPEND) {
> - pm_restore_gfp_mask();
> error = suspend_devices_and_enter(mem_sleep_current);
> if (!error)
> goto exit;
> @@ -746,9 +745,6 @@ static void power_down(void)
> cpu_relax();
>
> exit:
> - /* Match the pm_restore_gfp_mask() call in hibernate(). */
> - pm_restrict_gfp_mask();
> -
> /* Restore swap signature. */
> error = swsusp_unmark();
> if (error)
> --- a/kernel/power/main.c
> +++ b/kernel/power/main.c
> @@ -31,23 +31,35 @@
> * held, unless the suspend/hibernate code is guaranteed not to run in parallel
> * with that modification).
> */
> +static unsigned int saved_gfp_count;
> static gfp_t saved_gfp_mask;
>
> void pm_restore_gfp_mask(void)
> {
> WARN_ON(!mutex_is_locked(&system_transition_mutex));
> - if (saved_gfp_mask) {
> - gfp_allowed_mask = saved_gfp_mask;
> - saved_gfp_mask = 0;
> - }
> +
> + if (WARN_ON(!saved_gfp_count) || --saved_gfp_count)
> + return;
> +
> + gfp_allowed_mask = saved_gfp_mask;
> + saved_gfp_mask = 0;
> +
> + pm_pr_dbg("GFP mask restored\n");
> }
>
> void pm_restrict_gfp_mask(void)
> {
> WARN_ON(!mutex_is_locked(&system_transition_mutex));
> - WARN_ON(saved_gfp_mask);
> +
> + if (saved_gfp_count++) {
> + WARN_ON((saved_gfp_mask & ~(__GFP_IO | __GFP_FS)) != gfp_allowed_mask);
> + return;
> + }
> +
> saved_gfp_mask = gfp_allowed_mask;
> gfp_allowed_mask &= ~(__GFP_IO | __GFP_FS);
> +
> + pm_pr_dbg("GFP mask restricted\n");
> }
>
> unsigned int lock_system_sleep(void)
>
>
>
>
--
Kenneth R. Crudup / Sr. SW Engineer, Scott County Consulting, Orange
County CA
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-10-30 20:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-28 20:52 [PATCH v1] PM: sleep: Allow pm_restrict_gfp_mask() stacking Rafael J. Wysocki
2025-10-29 15:22 ` Mario Limonciello
2025-10-29 16:07 ` Rafael J. Wysocki
2025-10-30 19:49 ` Kenneth Crudup
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox