test_resume writes an image and loads it straight back without powering off. When the load fails nothing gives the image's swap slots back. They stay allocated for as long as the system runs, and swapoff on that device cannot finish, since the slots belong to no process. Tested by forcing the restore to fail in test_resume mode. Fixes: fe12c00d21bb ("PM / hibernate: Introduce test_resume mode for hibernation") Assisted-by: Claude:claude-fable-5 Signed-off-by: Youngjun Park --- kernel/power/hibernate.c | 6 +++++- kernel/power/power.h | 1 + kernel/power/swap.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index d2479c69d71a..907d791b85ad 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -857,8 +857,12 @@ int hibernate(void) if (snapshot_test) { pm_pr_dbg("Checking hibernation image\n"); error = swsusp_check(false); - if (!error) + if (!error) { error = load_image_and_restore(); + /* The image was not used, so free its slots. */ + if (error) + swsusp_free_image_slots(); + } } thaw_processes(); diff --git a/kernel/power/power.h b/kernel/power/power.h index 75b63843886e..9c398cddd0c3 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -171,6 +171,7 @@ extern void hibernate_release(void); extern sector_t alloc_swapdev_block(int swap); extern void free_all_swap_pages(int swap); extern int swsusp_swap_in_use(void); +void swsusp_free_image_slots(void); /* * Flags that can be passed from the hibernatig hernel to the "boot" kernel in diff --git a/kernel/power/swap.c b/kernel/power/swap.c index c78f1593600b..dc65ec409207 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -1612,6 +1612,18 @@ int swsusp_check(bool exclusive) return error; } +/** + * swsusp_free_image_slots - Give back the swap slots the image was written to. + * + * For a path that writes an image and then does not resume from it. Until + * the slots are given back they stay allocated, and swapoff on that device + * cannot finish either. + */ +void swsusp_free_image_slots(void) +{ + free_all_swap_pages(root_swap); +} + /** * swsusp_close - close resume device. */ -- 2.48.1