diff options
Diffstat (limited to 'kernel')
| -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 273a5b1d70..7e8492fd14 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
| @@ -16,7 +16,6 @@ struct swsusp_info { | |||
| 16 | int cpus; | 16 | int cpus; |
| 17 | unsigned long image_pages; | 17 | unsigned long image_pages; |
| 18 | unsigned long pages; | 18 | unsigned long pages; |
| 19 | swp_entry_t start; | ||
| 20 | } __attribute__((aligned(PAGE_SIZE))); | 19 | } __attribute__((aligned(PAGE_SIZE))); |
| 21 | 20 | ||
| 22 | 21 | ||
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 0479c9be7d..55a18d26ab 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
| @@ -93,7 +93,7 @@ extern char resume_file[]; | |||
| 93 | 93 | ||
| 94 | static struct swsusp_header { | 94 | static struct swsusp_header { |
| 95 | char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)]; | 95 | char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)]; |
| 96 | swp_entry_t swsusp_info; | 96 | swp_entry_t image; |
| 97 | char orig_sig[10]; | 97 | char orig_sig[10]; |
| 98 | char sig[10]; | 98 | char sig[10]; |
| 99 | } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; | 99 | } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; |
| @@ -106,7 +106,7 @@ static struct swsusp_info swsusp_info; | |||
| 106 | 106 | ||
| 107 | static unsigned short root_swap = 0xffff; | 107 | static unsigned short root_swap = 0xffff; |
| 108 | 108 | ||
| 109 | static int mark_swapfiles(swp_entry_t prev) | 109 | static int mark_swapfiles(swp_entry_t start) |
| 110 | { | 110 | { |
| 111 | int error; | 111 | int error; |
| 112 | 112 | ||
| @@ -117,7 +117,7 @@ static int mark_swapfiles(swp_entry_t prev) | |||
| 117 | !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { | 117 | !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { |
| 118 | memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); | 118 | memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); |
| 119 | memcpy(swsusp_header.sig,SWSUSP_SIG, 10); | 119 | memcpy(swsusp_header.sig,SWSUSP_SIG, 10); |
| 120 | swsusp_header.swsusp_info = prev; | 120 | swsusp_header.image = start; |
| 121 | error = rw_swap_page_sync(WRITE, | 121 | error = rw_swap_page_sync(WRITE, |
| 122 | swp_entry(root_swap, 0), | 122 | swp_entry(root_swap, 0), |
| 123 | virt_to_page((unsigned long) | 123 | virt_to_page((unsigned long) |
| @@ -423,22 +423,7 @@ static void init_header(unsigned int nr_pages) | |||
| 423 | swsusp_info.cpus = num_online_cpus(); | 423 | swsusp_info.cpus = num_online_cpus(); |
| 424 | swsusp_info.image_pages = nr_pages; | 424 | swsusp_info.image_pages = nr_pages; |
| 425 | swsusp_info.pages = nr_pages + | 425 | swsusp_info.pages = nr_pages + |
| 426 | ((nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT); | 426 | ((nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1; |
| 427 | } | ||
| 428 | |||
| 429 | static int close_swap(void) | ||
| 430 | { | ||
| 431 | swp_entry_t entry; | ||
| 432 | int error; | ||
| 433 | |||
| 434 | dump_info(); | ||
| 435 | error = write_page((unsigned long)&swsusp_info, &entry); | ||
| 436 | if (!error) { | ||
| 437 | printk( "S" ); | ||
| 438 | error = mark_swapfiles(entry); | ||
| 439 | printk( "|\n" ); | ||
| 440 | } | ||
| 441 | return error; | ||
| 442 | } | 427 | } |
| 443 | 428 | ||
| 444 | /** | 429 | /** |
| @@ -522,6 +507,7 @@ int swsusp_write(struct pbe *pblist, unsigned int nr_pages) | |||
| 522 | { | 507 | { |
| 523 | struct swap_map_page *swap_map; | 508 | struct swap_map_page *swap_map; |
| 524 | struct swap_map_handle handle; | 509 | struct swap_map_handle handle; |
| 510 | swp_entry_t start; | ||
| 525 | int error; | 511 | int error; |
| 526 | 512 | ||
| 527 | if ((error = swsusp_swap_check())) { | 513 | if ((error = swsusp_swap_check())) { |
| @@ -539,18 +525,23 @@ int swsusp_write(struct pbe *pblist, unsigned int nr_pages) | |||
| 539 | return -ENOMEM; | 525 | return -ENOMEM; |
| 540 | init_swap_map_handle(&handle, swap_map); | 526 | init_swap_map_handle(&handle, swap_map); |
| 541 | 527 | ||
| 542 | error = save_image_metadata(pblist, &handle); | 528 | error = swap_map_write_page(&handle, (unsigned long)&swsusp_info); |
| 529 | if (!error) | ||
| 530 | error = save_image_metadata(pblist, &handle); | ||
| 543 | if (!error) | 531 | if (!error) |
| 544 | error = save_image_data(pblist, &handle, nr_pages); | 532 | error = save_image_data(pblist, &handle, nr_pages); |
| 545 | if (error) | 533 | if (error) |
| 546 | goto Free_image_entries; | 534 | goto Free_image_entries; |
| 547 | 535 | ||
| 548 | swap_map = reverse_swap_map(swap_map); | 536 | swap_map = reverse_swap_map(swap_map); |
| 549 | error = save_swap_map(swap_map, &swsusp_info.start); | 537 | error = save_swap_map(swap_map, &start); |
| 550 | if (error) | 538 | if (error) |
| 551 | goto Free_map_entries; | 539 | goto Free_map_entries; |
| 552 | 540 | ||
| 553 | error = close_swap(); | 541 | dump_info(); |
| 542 | printk( "S" ); | ||
| 543 | error = mark_swapfiles(start); | ||
| 544 | printk( "|\n" ); | ||
| 554 | if (error) | 545 | if (error) |
| 555 | goto Free_map_entries; | 546 | goto Free_map_entries; |
| 556 | 547 | ||
| @@ -840,70 +831,28 @@ static inline int swap_map_read_page(struct swap_map_handle *handle, void *buf) | |||
| 840 | return error; | 831 | return error; |
| 841 | } | 832 | } |
| 842 | 833 | ||
| 843 | /* | 834 | static int check_header(void) |
| 844 | * Sanity check if this image makes sense with this kernel/swap context | ||
| 845 | * I really don't think that it's foolproof but more than nothing.. | ||
| 846 | */ | ||
| 847 | |||
| 848 | static const char *sanity_check(void) | ||
| 849 | { | 835 | { |
| 836 | char *reason = NULL; | ||
| 837 | |||
| 850 | dump_info(); | 838 | dump_info(); |
| 851 | if (swsusp_info.version_code != LINUX_VERSION_CODE) | 839 | if (swsusp_info.version_code != LINUX_VERSION_CODE) |
| 852 | return "kernel version"; | 840 | reason = "kernel version"; |
| 853 | if (swsusp_info.num_physpages != num_physpages) | 841 | if (swsusp_info.num_physpages != num_physpages) |
| 854 | return "memory size"; | 842 | reason = "memory size"; |
| 855 | if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) | 843 | if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) |
| 856 | return "system type"; | 844 | reason = "system type"; |
| 857 | if (strcmp(swsusp_info.uts.release,system_utsname.release)) | 845 | if (strcmp(swsusp_info.uts.release,system_utsname.release)) |
| 858 | return "kernel release"; | 846 | reason = "kernel release"; |
| 859 | if (strcmp(swsusp_info.uts.version,system_utsname.version)) | 847 | if (strcmp(swsusp_info.uts.version,system_utsname.version)) |
| 860 | return "version"; | 848 | reason = "version"; |
| 861 | if (strcmp(swsusp_info.uts.machine,system_utsname.machine)) | 849 | if (strcmp(swsusp_info.uts.machine,system_utsname.machine)) |
| 862 | return "machine"; | 850 | reason = "machine"; |
| 863 | #if 0 | 851 | if (reason) { |
| 864 | /* We can't use number of online CPUs when we use hotplug to remove them ;-))) */ | 852 | printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason); |
| 865 | if (swsusp_info.cpus != num_possible_cpus()) | ||
| 866 | return "number of cpus"; | ||
| 867 | #endif | ||
| 868 | return NULL; | ||
| 869 | } | ||
| 870 | |||
| 871 | static int check_header(void) | ||
| 872 | { | ||
| 873 | const char *reason = NULL; | ||
| 874 | int error; | ||
| 875 | |||
| 876 | if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info))) | ||
| 877 | return error; | ||
| 878 | |||
| 879 | /* Is this same machine? */ | ||
| 880 | if ((reason = sanity_check())) { | ||
| 881 | printk(KERN_ERR "swsusp: Resume mismatch: %s\n",reason); | ||
| 882 | return -EPERM; | 853 | return -EPERM; |
| 883 | } | 854 | } |
| 884 | return error; | 855 | return 0; |
| 885 | } | ||
| 886 | |||
| 887 | static int check_sig(void) | ||
| 888 | { | ||
| 889 | int error; | ||
| 890 | |||
| 891 | memset(&swsusp_header, 0, sizeof(swsusp_header)); | ||
| 892 | if ((error = bio_read_page(0, &swsusp_header))) | ||
| 893 | return error; | ||
| 894 | if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { | ||
| 895 | memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); | ||
| 896 | |||
| 897 | /* | ||
| 898 | * Reset swap signature now. | ||
| 899 | */ | ||
| 900 | error = bio_write_page(0, &swsusp_header); | ||
| 901 | } else { | ||
| 902 | return -EINVAL; | ||
| 903 | } | ||
| 904 | if (!error) | ||
| 905 | pr_debug("swsusp: Signature found, resuming\n"); | ||
| 906 | return error; | ||
| 907 | } | 856 | } |
| 908 | 857 | ||
| 909 | /** | 858 | /** |
| @@ -989,33 +938,29 @@ static int load_image_metadata(struct pbe *pblist, struct swap_map_handle *handl | |||
| 989 | return error; | 938 | return error; |
| 990 | } | 939 | } |
| 991 | 940 | ||
| 992 | static int check_suspend_image(void) | 941 | int swsusp_read(struct pbe **pblist_ptr) |
| 993 | { | ||
| 994 | int error = 0; | ||
| 995 | |||
| 996 | if ((error = check_sig())) | ||
| 997 | return error; | ||
| 998 | |||
| 999 | if ((error = check_header())) | ||
| 1000 | return error; | ||
| 1001 | |||
| 1002 | return 0; | ||
| 1003 | } | ||
| 1004 | |||
