aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2008-06-11 20:46:51 +0000
committerRafael J. Wysocki <rjw@sisk.pl>2008-06-11 20:46:51 +0000
commit9457df86578d7884382a59218b72364635db4d3d (patch)
tree1bddc4e523bd2b0f0c34c048479a3df60cc9502d
parent5be998fab03075034ceb1fb29d6af206dea7c07f (diff)
downloadsuspend-utils-9457df86578d7884382a59218b72364635db4d3d.tar.gz
Allow the user to reboot and try again if the freezing of tasks fails during
resume from hibernation.
-rw-r--r--resume.c123
1 files changed, 73 insertions, 50 deletions
diff --git a/resume.c b/resume.c
index 4755b3a..47835f0 100644
--- a/resume.c
+++ b/resume.c
@@ -218,63 +218,51 @@ static void pause_resume(int pause)
splash.restore_abort(&savedtrm);
}
-static int read_image(int dev, int fd, struct swsusp_header *swsusp_header)
+static void reboot_question(char *message)
+{
+ char c;
+ char full_message[SPLASH_GENERIC_MESSAGE_SIZE];
+ char *warning =
+ "\n\tYou can now boot the system and lose the saved state\n"
+ "\tor reboot and try again.\n\n"
+ "\t[Notice that if you decide to reboot, you MUST NOT mount\n"
+ "\tany filesystems before a successful resume.\n"
+ "\tResuming after some filesystems have been mounted\n"
+ "\twill badly damage these filesystems.]\n\n"
+ "\tDo you want to continue booting (Y/n)?";
+
+ snprintf(full_message, SPLASH_GENERIC_MESSAGE_SIZE, "%s\n%s",
+ message, warning);
+ c = splash.dialog(full_message);
+ if (c == 'n' || c == 'N') {
+ reboot();
+ fprintf(stderr, "%s: Reboot failed, please reboot manually.\n",
+ my_name);
+ while(1)
+ sleep(10);
+ }
+}
+
+static int read_image(int dev, int fd, loff_t start)
{
- ssize_t size = sizeof(struct swsusp_header);
- unsigned int shift = (resume_offset + 1) * page_size - size;
struct image_header_info *header;
int ret, error;
char c;
header = getmem(page_size);
- error = read_or_verify_image(dev, fd, header, swsusp_header->image, 0);
+ error = read_or_verify_image(dev, fd, header, start, 0);
if (error) {
- c = splash.dialog(
+ reboot_question(
"\nThe system snapshot image could not be read.\n\n"
-#ifdef CONFIG_ENCRYPT
- "\tThis might be a result of booting a wrong kernel\n"
- "\tor typing in a wrong passphrase.\n\n"
-#else
- "\tThis might be a result of booting a wrong kernel.\n\n"
-#endif
- "\tYou can continue to boot the system and lose the saved state\n"
- "\tor reboot and try again.\n\n"
- "\t[Notice that you may not mount any filesystem between\n"
- "\tnow and successful resume. That would badly damage\n"
- "\taffected filesystems.]\n\n"
- "\tDo you want to continue boot (Y/n)? ");
- ret = (c == 'n' || c == 'N');
- if (ret) {
- close(fd);
- reboot();
- fprintf(stderr, "%s: Reboot failed, please reboot manually.\n",
- my_name);
- while(1)
- sleep(1);
- }
+ "\tThis might be a result of booting a wrong "
+ "kernel.\n"
+ );
} else {
if (header->flags & PLATFORM_SUSPEND)
use_platform_suspend = 1;
}
- /* Reset swap signature now */
- memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
- if (lseek(fd, shift, SEEK_SET) != shift) {
- error = -EIO;
- } else {
- ret = write(fd, swsusp_header, size);
- if (ret != size) {
- error = ret < 0 ? -errno : -EIO;
- fprintf(stderr,
- "%s: Could not restore the partition header\n",
- my_name);
- }
- }
-
- fsync(fd);
- close(fd);
-
if (error) {
char message[SPLASH_GENERIC_MESSAGE_SIZE];
@@ -292,6 +280,33 @@ static int read_image(int dev, int fd, struct swsusp_header *swsusp_header)
return error;
}
+static int reset_signature(int fd, struct swsusp_header *swsusp_header)
+{
+ ssize_t ret, size = sizeof(struct swsusp_header);
+ unsigned int shift = (resume_offset + 1) * page_size - size;
+ int error = 0;
+
+ /* Reset swap signature now */
+ memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
+
+ if (lseek(fd, shift, SEEK_SET) != shift) {
+ fprintf(stderr, "%s: Could not lseek() to the swap header",
+ my_name);
+ return -EIO;
+ }
+
+ ret = write(fd, swsusp_header, size);
+ if (ret == size) {
+ fsync(fd);
+ } else {
+ fprintf(stderr, "%s: Could not restore the swap header",
+ my_name);
+ error = -EIO;
+ }
+
+ return error;
+}
+
/* Parse the command line and/or configuration file */
static inline int get_config(int argc, char *argv[])
{
@@ -488,18 +503,26 @@ int main(int argc, char *argv[])
splash_prepare(&splash, splash_param);
splash.progress(5);
- error = read_image(dev, resume_dev, &swsusp_header);
+ error = read_image(dev, resume_dev, swsusp_header.image);
if (error) {
- fprintf(stderr, "%s: Could not read the image\n", my_name);
error = -error;
- goto Close_splash;
+ fprintf(stderr, "%s: Could not read the image\n", my_name);
+ } else if (freeze(dev)) {
+ error = errno;
+ reboot_question("Processes could not be frozen, "
+ "cannot continue resuming.\n");
}
- if (freeze(dev)) {
- error = errno;
- fprintf(stderr, "%s: Could not freeze processes\n", my_name);
+ if (reset_signature(resume_dev, &swsusp_header))
+ fprintf(stderr, "%s: Swap signature has not been restored.\n"
+ "\tRun mkswap on the resume partition/file.\n",
+ my_name);
+
+ close(resume_dev);
+
+ if (error)
goto Close_splash;
- }
+
if (use_platform_suspend) {
int err = platform_prepare(dev);