History

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

Chen Yu committed 10 years ago

Commit fe12c001 parent 406f9922 files · +50 −21Browse files

Unified · Split

2 files
  1. kernel/power/hibernate.c +44 −21
  2. kernel/power/swap.c +6 −0
kernel/power/hibernate.c+44−21
@@ -52,6 +52,7 @@ enum { · 51 unmodified lines
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) · 589 unmodified lines
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) · 45 unmodified lines
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) · 4 unmodified lines
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) · 26 unmodified lines
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) · 89 unmodified lines
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[] = { · 19 unmodified lines
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, · 40 unmodified lines
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, · 40 unmodified lines
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+6−0
@@ -348,6 +348,12 @@ static int swsusp_swap_check(void) · 347 unmodified lines
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