diff options
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/power.h | 1 | ||||
-rw-r--r-- | kernel/power/swsusp.c | 190 |
2 files changed, 65 insertions, 126 deletions
diff --git a/kernel/power/power.h b/kernel/power/power.h index 273a5b1d70be..7e8492fd1423 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -16,7 +16,6 @@ struct swsusp_info { int cpus; unsigned long image_pages; unsigned long pages; - swp_entry_t start; } __attribute__((aligned(PAGE_SIZE))); diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 0479c9be7d71..55a18d26abed 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -93,7 +93,7 @@ extern char resume_file[]; static struct swsusp_header { char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)]; - swp_entry_t swsusp_info; + swp_entry_t image; char orig_sig[10]; char sig[10]; } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; @@ -106,7 +106,7 @@ static struct swsusp_info swsusp_info; static unsigned short root_swap = 0xffff; -static int mark_swapfiles(swp_entry_t prev) +static int mark_swapfiles(swp_entry_t start) { int error; @@ -117,7 +117,7 @@ static int mark_swapfiles(swp_entry_t prev) !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); memcpy(swsusp_header.sig,SWSUSP_SIG, 10); - swsusp_header.swsusp_info = prev; + swsusp_header.image = start; error = rw_swap_page_sync(WRITE, swp_entry(root_swap, 0), virt_to_page((unsigned long) @@ -423,22 +423,7 @@ static void init_header(unsigned int nr_pages) swsusp_info.cpus = num_online_cpus(); swsusp_info.image_pages = nr_pages; swsusp_info.pages = nr_pages + - ((nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT); -} - -static int close_swap(void) -{ - swp_entry_t entry; - int error; - - dump_info(); - error = write_page((unsigned long)&swsusp_info, &entry); - if (!error) { - printk( "S" ); - error = mark_swapfiles(entry); - printk( "|\n" ); - } - return error; + ((nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1; } /** @@ -522,6 +507,7 @@ int swsusp_write(struct pbe *pblist, unsigned int nr_pages) { struct swap_map_page *swap_map; struct swap_map_handle handle; + swp_entry_t start; int error; if ((error = swsusp_swap_check())) { @@ -539,18 +525,23 @@ int swsusp_write(struct pbe *pblist, unsigned int nr_pages) return -ENOMEM; init_swap_map_handle(&handle, swap_map); - error = save_image_metadata(pblist, &handle); + error = swap_map_write_page(&handle, (unsigned long)&swsusp_info); + if (!error) + error = save_image_metadata(pblist, &handle); if (!error) error = save_image_data(pblist, &handle, nr_pages); if (error) goto Free_image_entries; swap_map = reverse_swap_map(swap_map); - error = save_swap_map(swap_map, &swsusp_info.start); + error = save_swap_map(swap_map, &start); if (error) goto Free_map_entries; - error = close_swap(); + dump_info(); + printk( "S" ); + error = mark_swapfiles(start); + printk( "|\n" ); if (error) goto Free_map_entries; @@ -840,70 +831,28 @@ static inline int swap_map_read_page(struct swap_map_handle *handle, void *buf) return error; } -/* - * Sanity check if this image makes sense with this kernel/swap context - * I really don't think that it's foolproof but more than nothing.. - */ - -static const char *sanity_check(void) +static int check_header(void) { + char *reason = NULL; + dump_info(); if (swsusp_info.version_code != LINUX_VERSION_CODE) - return "kernel version"; + reason = "kernel version"; if (swsusp_info.num_physpages != num_physpages) - return "memory size"; + reason = "memory size"; if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) - return "system type"; + reason = "system type"; if (strcmp(swsusp_info.uts.release,system_utsname.release)) - return "kernel release"; + reason = "kernel release"; if (strcmp(swsusp_info.uts.version,system_utsname.version)) - return "version"; + reason = "version"; if (strcmp(swsusp_info.uts.machine,system_utsname.machine)) - return "machine"; -#if 0 - /* We can't use number of online CPUs when we use hotplug to remove them ;-))) */ - if (swsusp_info.cpus != num_possible_cpus()) - return "number of cpus"; -#endif - return NULL; -} - -static int check_header(void) -{ - const char *reason = NULL; - int error; - - if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info))) - return error; - - /* Is this same machine? */ - if ((reason = sanity_check())) { - printk(KERN_ERR "swsusp: Resume mismatch: %s\n",reason); + reason = "machine"; + if (reason) { + printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason); return -EPERM; } - return error; -} - -static int check_sig(void) -{ - int error; - - memset(&swsusp_header, 0, sizeof(swsusp_header)); - if ((error = bio_read_page(0, &swsusp_header))) - return error; - if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { - memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); - - /* - * Reset swap signature now. - */ - error = bio_write_page(0, &swsusp_header); - } else { - return -EINVAL; - } - if (!error) - pr_debug("swsusp: Signature found, resuming\n"); - return error; + return 0; } /** @@ -989,33 +938,29 @@ static int load_image_metadata(struct pbe *pblist, struct swap_map_handle *handl return error; } -static int check_suspend_image(void) -{ - int error = 0; - - if ((error = check_sig())) - return error; - - if ((error = check_header())) - return error; - - return 0; -} - -static int read_suspend_image(struct pbe **pblist_ptr) +int swsusp_read(struct pbe **pblist_ptr) { - int error = 0; + int error; struct pbe *p, *pblist; struct swap_map_handle handle; - unsigned int nr_pages = swsusp_info.image_pages; + unsigned int nr_pages; + if (IS_ERR(resume_bdev)) { + pr_debug("swsusp: block device not initialised\n"); + return PTR_ERR(resume_bdev); + } + + error = get_swap_map_reader(&handle, swsusp_header.image); + if (!error) + error = swap_map_read_page(&handle, &swsusp_info); + if (!error) + error = check_header(); + if (error) + return error; + nr_pages = swsusp_info.image_pages; p = alloc_pagedir(nr_pages, GFP_ATOMIC, 0); if (!p) return -ENOMEM; - error = get_swap_map_reader(&handle, swsusp_info.start); - if (error) - /* The PBE list at p will be released by swsusp_free() */ - return error; error = load_image_metadata(p, &handle); if (!error) { mark_unsafe_pages(p); @@ -1037,11 +982,18 @@ static int read_suspend_image(struct pbe **pblist_ptr) *pblist_ptr = pblist; } release_swap_map_reader(&handle); + + blkdev_put(resume_bdev); + + if (!error) + pr_debug("swsusp: Reading resume file was successful\n"); + else + pr_debug("swsusp: Error %d resuming\n", error); return error; } /** - * swsusp_check - Check for saved image in swap + * swsusp_check - Check for swsusp signature in the resume device */ int swsusp_check(void) @@ -1051,39 +1003,27 @@ int swsusp_check(void) resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); if (!IS_ERR(resume_bdev)) { set_blocksize(resume_bdev, PAGE_SIZE); - error = check_suspend_image(); + memset(&swsusp_header, 0, sizeof(swsusp_header)); + if ((error = bio_read_page(0, &swsusp_header))) + return error; + if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { + memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); + /* Reset swap signature now */ + error = bio_write_page(0, &swsusp_header); + } else { + return -EINVAL; + } if (error) - blkdev_put(resume_bdev); - } else + blkdev_put(resume_bdev); + else + pr_debug("swsusp: Signature found, resuming\n"); + } else { error = PTR_ERR(resume_bdev); - - if (!error) - pr_debug("swsusp: resume file found\n"); - else - pr_debug("swsusp: Error %d check for resume file\n", error); - return error; -} - -/** - * swsusp_read - Read saved image from swap. - */ - -int swsusp_read(struct pbe **pblist_ptr) -{ - int error; - - if (IS_ERR(resume_bdev)) { - pr_debug("swsusp: block device not initialised\n"); - return PTR_ERR(resume_bdev); } - error = read_suspend_image(pblist_ptr); - blkdev_put(resume_bdev); + if (error) + pr_debug("swsusp: Error %d check for resume file\n", error); - if (!error) - pr_debug("swsusp: Reading resume file was successful\n"); - else - pr_debug("swsusp: Error %d resuming\n", error); return error; } |