Skip to content

Commit fe12c00

Browse files
yu-chen-surfrafaeljw
authored andcommitted
PM / hibernate: Introduce test_resume mode for hibernation
test_resume mode is to verify if the snapshot data written to swap device can be successfully restored to memory. It is useful to ease the debugging process on hibernation, since this mode can not only bypass the BIOSes/bootloader, but also the system re-initialization. To avoid the risk to break the filesystm on persistent storage, this patch resumes the image with tasks frozen. For example: echo test_resume > /sys/power/disk echo disk > /sys/power/state [ 187.306470] PM: Image saving progress: 70% [ 187.395298] PM: Image saving progress: 80% [ 187.476697] PM: Image saving progress: 90% [ 187.554641] PM: Image saving done. [ 187.558896] PM: Wrote 594600 kbytes in 0.90 seconds (660.66 MB/s) [ 187.566000] PM: S| [ 187.589742] PM: Basic memory bitmaps freed [ 187.594694] PM: Checking hibernation image [ 187.599865] PM: Image signature found, resuming [ 187.605209] PM: Loading hibernation image. [ 187.665753] PM: Basic memory bitmaps created [ 187.691397] PM: Using 3 thread(s) for decompression. [ 187.691397] PM: Loading and decompressing image data (148650 pages)... [ 187.889719] PM: Image loading progress: 0% [ 188.100452] PM: Image loading progress: 10% [ 188.244781] PM: Image loading progress: 20% [ 189.057305] PM: Image loading done. [ 189.068793] PM: Image successfully loaded Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Chen Yu <yu.c.chen@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 406f992 commit fe12c00

File tree

2 files changed

+50
-21
lines changed

2 files changed

+50
-21
lines changed

kernel/power/hibernate.c

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ enum {
5252
#ifdef CONFIG_SUSPEND
5353
HIBERNATION_SUSPEND,
5454
#endif
55+
HIBERNATION_TEST_RESUME,
5556
/* keep last */
5657
__HIBERNATION_AFTER_LAST
5758
};
@@ -647,12 +648,39 @@ static void power_down(void)
647648
cpu_relax();
648649
}
649650

651+
static int load_image_and_restore(void)
652+
{
653+
int error;
654+
unsigned int flags;
655+
656+
pr_debug("PM: Loading hibernation image.\n");
657+
658+
lock_device_hotplug();
659+
error = create_basic_memory_bitmaps();
660+
if (error)
661+
goto Unlock;
662+
663+
error = swsusp_read(&flags);
664+
swsusp_close(FMODE_READ);
665+
if (!error)
666+
hibernation_restore(flags & SF_PLATFORM_MODE);
667+
668+
printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
669+
swsusp_free();
670+
free_basic_memory_bitmaps();
671+
Unlock:
672+
unlock_device_hotplug();
673+
674+
return error;
675+
}
676+
650677
/**
651678
* hibernate - Carry out system hibernation, including saving the image.
652679
*/
653680
int hibernate(void)
654681
{
655682
int error, nr_calls = 0;
683+
bool snapshot_test = false;
656684

657685
if (!hibernation_available()) {
658686
pr_debug("PM: Hibernation not available.\n");
@@ -704,8 +732,12 @@ int hibernate(void)
704732
pr_debug("PM: writing image.\n");
705733
error = swsusp_write(flags);
706734
swsusp_free();
707-
if (!error)
708-
power_down();
735+
if (!error) {
736+
if (hibernation_mode == HIBERNATION_TEST_RESUME)
737+
snapshot_test = true;
738+
else
739+
power_down();
740+
}
709741
in_suspend = 0;
710742
pm_restore_gfp_mask();
711743
} else {
@@ -716,6 +748,12 @@ int hibernate(void)
716748
free_basic_memory_bitmaps();
717749
Thaw:
718750
unlock_device_hotplug();
751+
if (snapshot_test) {
752+
pr_debug("PM: Checking hibernation image\n");
753+
error = swsusp_check();
754+
if (!error)
755+
error = load_image_and_restore();
756+
}
719757
thaw_processes();
720758

721759
/* Don't bother checking whether freezer_test_done is true */
@@ -748,7 +786,6 @@ int hibernate(void)
748786
static int software_resume(void)
749787
{
750788
int error, nr_calls = 0;
751-
unsigned int flags;
752789

753790
/*
754791
* If the user said "noresume".. bail out early.
@@ -844,24 +881,7 @@ static int software_resume(void)
844881
error = freeze_processes();
845882
if (error)
846883
goto Close_Finish;
847-
848-
pr_debug("PM: Loading hibernation image.\n");
849-
850-
lock_device_hotplug();
851-
error = create_basic_memory_bitmaps();
852-
if (error)
853-
goto Thaw;
854-
855-
error = swsusp_read(&flags);
856-
swsusp_close(FMODE_READ);
857-
if (!error)
858-
hibernation_restore(flags & SF_PLATFORM_MODE);
859-
860-
printk(KERN_ERR "PM: Failed to load hibernation image, recovering.\n");
861-
swsusp_free();
862-
free_basic_memory_bitmaps();
863-
Thaw:
864-
unlock_device_hotplug();
884+
error = load_image_and_restore();
865885
thaw_processes();
866886
Finish:
867887
__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
@@ -887,6 +907,7 @@ static const char * const hibernation_modes[] = {
887907
#ifdef CONFIG_SUSPEND
888908
[HIBERNATION_SUSPEND] = "suspend",
889909
#endif
910+
[HIBERNATION_TEST_RESUME] = "test_resume",
890911
};
891912

892913
/*
@@ -933,6 +954,7 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
933954
#ifdef CONFIG_SUSPEND
934955
case HIBERNATION_SUSPEND:
935956
#endif
957+
case HIBERNATION_TEST_RESUME:
936958
break;
937959
case HIBERNATION_PLATFORM:
938960
if (hibernation_ops)
@@ -979,6 +1001,7 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
9791001
#ifdef CONFIG_SUSPEND
9801002
case HIBERNATION_SUSPEND:
9811003
#endif
1004+
case HIBERNATION_TEST_RESUME:
9821005
hibernation_mode = mode;
9831006
break;
9841007
case HIBERNATION_PLATFORM:

kernel/power/swap.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,12 @@ static int swsusp_swap_check(void)
348348
if (res < 0)
349349
blkdev_put(hib_resume_bdev, FMODE_WRITE);
350350

351+
/*
352+
* Update the resume device to the one actually used,
353+
* so the test_resume mode can use it in case it is
354+
* invoked from hibernate() to test the snapshot.
355+
*/
356+
swsusp_resume_device = hib_resume_bdev->bd_dev;
351357
return res;
352358
}
353359

0 commit comments

Comments
 (0)