Skip to content

Commit 1ae64cc

Browse files
committed
PM: sleep: Allow pm_restrict_gfp_mask() stacking
JIRA: https://issues.redhat.com/browse/RHEL-109250 commit 35e4a69 Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Date: Tue Oct 28 21:52:31 2025 +0100 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: 449c9c0 ("PM: hibernate: Restrict GFP mask in hibernation_snapshot()") Fixes: 469d80a ("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> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> Tested-by: Mario Limonciello (AMD) <superm1@kernel.org> Cc: 6.16+ <stable@vger.kernel.org> # 6.16+ Link: https://patch.msgid.link/5935682.DvuYhMxLoT@rafael.j.wysocki Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
1 parent ee680c1 commit 1ae64cc

File tree

2 files changed

+17
-9
lines changed

2 files changed

+17
-9
lines changed

kernel/power/hibernate.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,6 @@ static void power_down(void)
658658

659659
#ifdef CONFIG_SUSPEND
660660
if (hibernation_mode == HIBERNATION_SUSPEND) {
661-
pm_restore_gfp_mask();
662661
error = suspend_devices_and_enter(mem_sleep_current);
663662
if (!error)
664663
goto exit;
@@ -698,9 +697,6 @@ static void power_down(void)
698697
cpu_relax();
699698

700699
exit:
701-
/* Match the pm_restore_gfp_mask() call in hibernate(). */
702-
pm_restrict_gfp_mask();
703-
704700
/* Restore swap signature. */
705701
error = swsusp_unmark();
706702
if (error)

kernel/power/main.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,35 @@
3030
* held, unless the suspend/hibernate code is guaranteed not to run in parallel
3131
* with that modification).
3232
*/
33+
static unsigned int saved_gfp_count;
3334
static gfp_t saved_gfp_mask;
3435

3536
void pm_restore_gfp_mask(void)
3637
{
3738
WARN_ON(!mutex_is_locked(&system_transition_mutex));
38-
if (saved_gfp_mask) {
39-
gfp_allowed_mask = saved_gfp_mask;
40-
saved_gfp_mask = 0;
41-
}
39+
40+
if (WARN_ON(!saved_gfp_count) || --saved_gfp_count)
41+
return;
42+
43+
gfp_allowed_mask = saved_gfp_mask;
44+
saved_gfp_mask = 0;
45+
46+
pm_pr_dbg("GFP mask restored\n");
4247
}
4348

4449
void pm_restrict_gfp_mask(void)
4550
{
4651
WARN_ON(!mutex_is_locked(&system_transition_mutex));
47-
WARN_ON(saved_gfp_mask);
52+
53+
if (saved_gfp_count++) {
54+
WARN_ON((saved_gfp_mask & ~(__GFP_IO | __GFP_FS)) != gfp_allowed_mask);
55+
return;
56+
}
57+
4858
saved_gfp_mask = gfp_allowed_mask;
4959
gfp_allowed_mask &= ~(__GFP_IO | __GFP_FS);
60+
61+
pm_pr_dbg("GFP mask restricted\n");
5062
}
5163

5264
unsigned int lock_system_sleep(void)

0 commit comments

Comments
 (0)