[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4dd9d86f-7c20-40fa-838c-b7634bbebf9a@kernel.org>
Date: Wed, 29 Oct 2025 10:22:18 -0500
From: Mario Limonciello <superm1@...nel.org>
To: "Rafael J. Wysocki" <rafael@...nel.org>,
Linux PM <linux-pm@...r.kernel.org>
Cc: Askar Safin <safinaskar@...il.com>, LKML <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v1] PM: sleep: Allow pm_restrict_gfp_mask() stacking
On 10/28/25 3:52 PM, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@...el.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@...il.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@...el.com>
Great idea. Looks good to me, and it passes the S4 tests on my side.
Reviewed-by: Mario Limonciello (AMD) <superm1@...nel.org>
Tested-by: Mario Limonciello (AMD) <superm1@...nel.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)
>
>
>
Powered by blists - more mailing lists