diff options
| author | Bojan Smojver <bojan@rexursive.com> | 2010-09-09 17:06:23 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rjw@sisk.pl> | 2010-10-16 19:57:42 -0400 |
| commit | f996fc9671d088bd5f52a70f18c64bfe3d0e418f (patch) | |
| tree | 3d88b5adfa21fc71cbabb9a891d37b0c1ce1c692 | |
| parent | 05aa55dddb9ee4045c320661068bea78dad6a6e5 (diff) | |
PM / Hibernate: Compress hibernation image with LZO
Compress hibernation image with LZO in order to save on I/O and
therefore time to hibernate/thaw.
[rjw: Added hibernate=nocompress command line option instead of just
nocompress which would be confusing, fixed a couple of compiler
warnings, fixed kerneldoc comments, minor cleanups.]
Signed-off-by: Bojan Smojver <bojan@rexursive.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
| -rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
| -rw-r--r-- | Documentation/power/swsusp.txt | 3 | ||||
| -rw-r--r-- | kernel/power/Kconfig | 2 | ||||
| -rw-r--r-- | kernel/power/hibernate.c | 13 | ||||
| -rw-r--r-- | kernel/power/power.h | 1 | ||||
| -rw-r--r-- | kernel/power/swap.c | 290 |
6 files changed, 306 insertions, 8 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 8dd7248508a9..2c98b18864c5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -2165,6 +2165,11 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 2165 | in <PAGE_SIZE> units (needed only for swap files). | 2165 | in <PAGE_SIZE> units (needed only for swap files). |
| 2166 | See Documentation/power/swsusp-and-swap-files.txt | 2166 | See Documentation/power/swsusp-and-swap-files.txt |
| 2167 | 2167 | ||
| 2168 | hibernate= [HIBERNATION] | ||
| 2169 | noresume Don't check if there's a hibernation image | ||
| 2170 | present during boot. | ||
| 2171 | nocompress Don't compress/decompress hibernation images. | ||
| 2172 | |||
| 2168 | retain_initrd [RAM] Keep initrd memory after extraction | 2173 | retain_initrd [RAM] Keep initrd memory after extraction |
| 2169 | 2174 | ||
| 2170 | rhash_entries= [KNL,NET] | 2175 | rhash_entries= [KNL,NET] |
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index 9d60ab717a7b..ea718891a665 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt | |||
| @@ -66,7 +66,8 @@ swsusp saves the state of the machine into active swaps and then reboots or | |||
| 66 | powerdowns. You must explicitly specify the swap partition to resume from with | 66 | powerdowns. You must explicitly specify the swap partition to resume from with |
| 67 | ``resume='' kernel option. If signature is found it loads and restores saved | 67 | ``resume='' kernel option. If signature is found it loads and restores saved |
| 68 | state. If the option ``noresume'' is specified as a boot parameter, it skips | 68 | state. If the option ``noresume'' is specified as a boot parameter, it skips |
| 69 | the resuming. | 69 | the resuming. If the option ``hibernate=nocompress'' is specified as a boot |
| 70 | parameter, it saves hibernation image without compression. | ||
| 70 | 71 | ||
| 71 | In the meantime while the system is suspended you should not add/remove any | 72 | In the meantime while the system is suspended you should not add/remove any |
| 72 | of the hardware, write to the filesystems, etc. | 73 | of the hardware, write to the filesystems, etc. |
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index ca6066a6952e..cb57eb99215f 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
| @@ -137,6 +137,8 @@ config SUSPEND_FREEZER | |||
| 137 | config HIBERNATION | 137 | config HIBERNATION |
| 138 | bool "Hibernation (aka 'suspend to disk')" | 138 | bool "Hibernation (aka 'suspend to disk')" |
| 139 | depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE | 139 | depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE |
| 140 | select LZO_COMPRESS | ||
| 141 | select LZO_DECOMPRESS | ||
| 140 | select SUSPEND_NVS if HAS_IOMEM | 142 | select SUSPEND_NVS if HAS_IOMEM |
| 141 | ---help--- | 143 | ---help--- |
| 142 | Enable the suspend to disk (STD) functionality, which is usually | 144 | Enable the suspend to disk (STD) functionality, which is usually |
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 8dc31e02ae12..6c9c9dc48c75 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include "power.h" | 29 | #include "power.h" |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | static int nocompress = 0; | ||
| 32 | static int noresume = 0; | 33 | static int noresume = 0; |
| 33 | static char resume_file[256] = CONFIG_PM_STD_PARTITION; | 34 | static char resume_file[256] = CONFIG_PM_STD_PARTITION; |
| 34 | dev_t swsusp_resume_device; | 35 | dev_t swsusp_resume_device; |
| @@ -638,6 +639,8 @@ int hibernate(void) | |||
| 638 | 639 | ||
| 639 | if (hibernation_mode == HIBERNATION_PLATFORM) | 640 | if (hibernation_mode == HIBERNATION_PLATFORM) |
| 640 | flags |= SF_PLATFORM_MODE; | 641 | flags |= SF_PLATFORM_MODE; |
| 642 | if (nocompress) | ||
| 643 | flags |= SF_NOCOMPRESS_MODE; | ||
| 641 | pr_debug("PM: writing image.\n"); | 644 | pr_debug("PM: writing image.\n"); |
| 642 | error = swsusp_write(flags); | 645 | error = swsusp_write(flags); |
| 643 | swsusp_free(); | 646 | swsusp_free(); |
| @@ -1004,6 +1007,15 @@ static int __init resume_offset_setup(char *str) | |||
| 1004 | return 1; | 1007 | return 1; |
| 1005 | } | 1008 | } |
| 1006 | 1009 | ||
| 1010 | static int __init hibernate_setup(char *str) | ||
| 1011 | { | ||
| 1012 | if (!strncmp(str, "noresume", 8)) | ||
| 1013 | noresume = 1; | ||
| 1014 | else if (!strncmp(str, "nocompress", 10)) | ||
| 1015 | nocompress = 1; | ||
| 1016 | return 1; | ||
| 1017 | } | ||
| 1018 | |||
| 1007 | static int __init noresume_setup(char *str) | 1019 | static int __init noresume_setup(char *str) |
| 1008 | { | 1020 | { |
| 1009 | noresume = 1; | 1021 | noresume = 1; |
| @@ -1013,3 +1025,4 @@ static int __init noresume_setup(char *str) | |||
| 1013 | __setup("noresume", noresume_setup); | 1025 | __setup("noresume", noresume_setup); |
| 1014 | __setup("resume_offset=", resume_offset_setup); | 1026 | __setup("resume_offset=", resume_offset_setup); |
| 1015 | __setup("resume=", resume_setup); | 1027 | __setup("resume=", resume_setup); |
| 1028 | __setup("hibernate=", hibernate_setup); | ||
diff --git a/kernel/power/power.h b/kernel/power/power.h index 006270fe382d..c7e42e47eb0b 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
| @@ -134,6 +134,7 @@ extern int swsusp_swap_in_use(void); | |||
| 134 | * the image header. | 134 | * the image header. |
| 135 | */ | 135 | */ |
| 136 | #define SF_PLATFORM_MODE 1 | 136 | #define SF_PLATFORM_MODE 1 |
| 137 | #define SF_NOCOMPRESS_MODE 2 | ||
| 137 | 138 | ||
| 138 | /* kernel/power/hibernate.c */ | 139 | /* kernel/power/hibernate.c */ |
| 139 | extern int swsusp_check(void); | 140 | extern int swsusp_check(void); |
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index e6a5bdf61a37..3dc0552cddfb 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
| @@ -24,6 +24,8 @@ | |||
| 24 | #include <linux/swapops.h> | 24 | #include <linux/swapops.h> |
| 25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/lzo.h> | ||
| 28 | #include <linux/vmalloc.h> | ||
| 27 | 29 | ||
| 28 | #include "power.h" | 30 | #include "power.h" |
| 29 | 31 | ||
| @@ -357,6 +359,18 @@ static int swap_writer_finish(struct swap_map_handle *handle, | |||
| 357 | return error; | 359 | return error; |
| 358 | } | 360 | } |
| 359 | 361 | ||
| 362 | /* We need to remember how much compressed data we need to read. */ | ||
| 363 | #define LZO_HEADER sizeof(size_t) | ||
| 364 | |||
| 365 | /* Number of pages/bytes we'll compress at one time. */ | ||
| 366 | #define LZO_UNC_PAGES 32 | ||
| 367 | #define LZO_UNC_SIZE (LZO_UNC_PAGES * PAGE_SIZE) | ||
| 368 | |||
| 369 | /* Number of pages/bytes we need for compressed data (worst case). */ | ||
| 370 | #define LZO_CMP_PAGES DIV_ROUND_UP(lzo1x_worst_compress(LZO_UNC_SIZE) + \ | ||
| 371 | LZO_HEADER, PAGE_SIZE) | ||
| 372 | #define LZO_CMP_SIZE (LZO_CMP_PAGES * PAGE_SIZE) | ||
| 373 | |||
| 360 | /** | 374 | /** |
| 361 | * save_image - save the suspend image data | 375 | * save_image - save the suspend image data |
| 362 | */ | 376 | */ |
| @@ -404,6 +418,137 @@ static int save_image(struct swap_map_handle *handle, | |||
| 404 | return ret; | 418 | return ret; |
| 405 | } | 419 | } |
| 406 | 420 | ||
| 421 | |||
| 422 | /** | ||
| 423 | * save_image_lzo - Save the suspend image data compressed with LZO. | ||
| 424 | * @handle: Swap mam handle to use for saving the image. | ||
| 425 | * @snapshot: Image to read data from. | ||
| 426 | * @nr_to_write: Number of pages to save. | ||
| 427 | */ | ||
| 428 | static int save_image_lzo(struct swap_map_handle *handle, | ||
| 429 | struct snapshot_handle *snapshot, | ||
| 430 | unsigned int nr_to_write) | ||
| 431 | { | ||
| 432 | unsigned int m; | ||
| 433 | int ret = 0; | ||
| 434 | int nr_pages; | ||
| 435 | int err2; | ||
| 436 | struct bio *bio; | ||
| 437 | struct timeval start; | ||
| 438 | struct timeval stop; | ||
| 439 | size_t off, unc_len, cmp_len; | ||
| 440 | unsigned char *unc, *cmp, *wrk, *page; | ||
| 441 | |||
| 442 | page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); | ||
| 443 | if (!page) { | ||
| 444 | printk(KERN_ERR "PM: Failed to allocate LZO page\n"); | ||
| 445 | return -ENOMEM; | ||
| 446 | } | ||
| 447 | |||
| 448 | wrk = vmalloc(LZO1X_1_MEM_COMPRESS); | ||
| 449 | if (!wrk) { | ||
| 450 | printk(KERN_ERR "PM: Failed to allocate LZO workspace\n"); | ||
| 451 | free_page((unsigned long)page); | ||
| 452 | return -ENOMEM; | ||
| 453 | } | ||
| 454 | |||
| 455 | unc = vmalloc(LZO_UNC_SIZE); | ||
| 456 | if (!unc) { | ||
| 457 | printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n"); | ||
| 458 | vfree(wrk); | ||
| 459 | free_page((unsigned long)page); | ||
| 460 | return -ENOMEM; | ||
| 461 | } | ||
| 462 | |||
| 463 | cmp = vmalloc(LZO_CMP_SIZE); | ||
| 464 | if (!cmp) { | ||
| 465 | printk(KERN_ERR "PM: Failed to allocate LZO compressed\n"); | ||
| 466 | vfree(unc); | ||
| 467 | vfree(wrk); | ||
| 468 | free_page((unsigned long)page); | ||
| 469 | return -ENOMEM; | ||
| 470 | } | ||
| 471 | |||
| 472 | printk(KERN_INFO | ||
| 473 | "PM: Compressing and saving image data (%u pages) ... ", | ||
| 474 | nr_to_write); | ||
| 475 | m = nr_to_write / 100; | ||
| 476 | if (!m) | ||
| 477 | m = 1; | ||
| 478 | nr_pages = 0; | ||
| 479 | bio = NULL; | ||
| 480 | do_gettimeofday(&start); | ||
| 481 | for (;;) { | ||
| 482 | for (off = 0; off < LZO_UNC_SIZE; off += PAGE_SIZE) { | ||
| 483 | ret = snapshot_read_next(snapshot); | ||
| 484 | if (ret < 0) | ||
| 485 | goto out_finish; | ||
| 486 | |||
| 487 | if (!ret) | ||
| 488 | break; | ||
| 489 | |||
| 490 | memcpy(unc + off, data_of(*snapshot), PAGE_SIZE); | ||
| 491 | |||
| 492 | if (!(nr_pages % m)) | ||
| 493 | printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m); | ||
| 494 | nr_pages++; | ||
| 495 | } | ||
| 496 | |||
| 497 | if (!off) | ||
| 498 | break; | ||
| 499 | |||
| 500 | unc_len = off; | ||
| 501 | ret = lzo1x_1_compress(unc, unc_len, | ||
| 502 | cmp + LZO_HEADER, &cmp_len, wrk); | ||
| 503 | if (ret < 0) { | ||
| 504 | printk(KERN_ERR "PM: LZO compression failed\n"); | ||
| 505 | break; | ||
| 506 | } | ||
| 507 | |||
| 508 | if (unlikely(!cmp_len || | ||
| 509 | cmp_len > lzo1x_worst_compress(unc_len))) { | ||
| 510 | printk(KERN_ERR "PM: Invalid LZO compressed length\n"); | ||
| 511 | ret = -1; | ||
| 512 | break; | ||
| 513 | } | ||
| 514 | |||
| 515 | *(size_t *)cmp = cmp_len; | ||
| 516 | |||
| 517 | /* | ||
| 518 | * Given we are writing one page at a time to disk, we copy | ||
| 519 | * that much from the buffer, although the last bit will likely | ||
| 520 | * be smaller than full page. This is OK - we saved the length | ||
| 521 | * of the compressed data, so any garbage at the end will be | ||
| 522 | * discarded when we read it. | ||
| 523 | */ | ||
| 524 | for (off = 0; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) { | ||
| 525 | memcpy(page, cmp + off, PAGE_SIZE); | ||
| 526 | |||
| 527 | ret = swap_write_page(handle, page, &bio); | ||
| 528 | if (ret) | ||
| 529 | goto out_finish; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | |||
| 533 | out_finish: | ||
| 534 | err2 = hib_wait_on_bio_chain(&bio); | ||
| 535 | do_gettimeofday(&stop); | ||
| 536 | if (!ret) | ||
| 537 | ret = err2; | ||
| 538 | if (!ret) | ||
| 539 | printk(KERN_CONT "\b\b\b\bdone\n"); | ||
| 540 | else | ||
| 541 | printk(KERN_CONT "\n"); | ||
| 542 | swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); | ||
| 543 | |||
| 544 | vfree(cmp); | ||
| 545 | vfree(unc); | ||
| 546 | vfree(wrk); | ||
| 547 | free_page((unsigned long)page); | ||
| 548 | |||
| 549 | return ret; | ||
| 550 | } | ||
| 551 | |||
| 407 | /** | 552 | /** |
| 408 | * enough_swap - Make sure we have enough swap to save the image. | 553 | * enough_swap - Make sure we have enough swap to save the image. |
| 409 | * | 554 | * |
| @@ -411,12 +556,16 @@ static int save_image(struct swap_map_handle *handle, | |||
| 411 | * space avaiable from the resume partition. | 556 | * space avaiable from the resume partition. |
| 412 | */ | 557 | */ |
| 413 | 558 | ||
| 414 | static int enough_swap(unsigned int nr_pages) | 559 | static int enough_swap(unsigned int nr_pages, unsigned int flags) |
| 415 | { | 560 | { |
| 416 | unsigned int free_swap = count_swap_pages(root_swap, 1); | 561 | unsigned int free_swap = count_swap_pages(root_swap, 1); |
| 562 | unsigned int required; | ||
| 417 | 563 | ||
| 418 | pr_debug("PM: Free swap pages: %u\n", free_swap); | 564 | pr_debug("PM: Free swap pages: %u\n", free_swap); |
| 419 | return free_swap > nr_pages + PAGES_FOR_IO; | 565 | |
| 566 | required = PAGES_FOR_IO + ((flags & SF_NOCOMPRESS_MODE) ? | ||
| 567 | nr_pages : (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1); | ||
| 568 | return free_swap > required; | ||
| 420 | } | 569 | } |
| 421 | 570 | ||
| 422 | /** | 571 | /** |
| @@ -443,7 +592,7 @@ int swsusp_write(unsigned int flags) | |||
| 443 | printk(KERN_ERR "PM: Cannot get swap writer\n"); | 592 | printk(KERN_ERR "PM: Cannot get swap writer\n"); |
| 444 | return error; | 593 | return error; |
| 445 | } | 594 | } |
| 446 | if (!enough_swap(pages)) { | 595 | if (!enough_swap(pages, flags)) { |
| 447 | printk(KERN_ERR "PM: Not enough free swap\n"); | 596 | printk(KERN_ERR "PM: Not enough free swap\n"); |
| 448 | error = -ENOSPC; | 597 | error = -ENOSPC; |
| 449 | goto out_finish; | 598 | goto out_finish; |
| @@ -458,8 +607,11 @@ int swsusp_write(unsigned int flags) | |||
| 458 | } | 607 | } |
| 459 | header = (struct swsusp_info *)data_of(snapshot); | 608 | header = (struct swsusp_info *)data_of(snapshot); |
| 460 | error = swap_write_page(&handle, header, NULL); | 609 | error = swap_write_page(&handle, header, NULL); |
| 461 | if (!error) | 610 | if (!error) { |
| 462 | error = save_image(&handle, &snapshot, pages - 1); | 611 | error = (flags & SF_NOCOMPRESS_MODE) ? |
| 612 | save_image(&handle, &snapshot, pages - 1) : | ||
| 613 | save_image_lzo(&handle, &snapshot, pages - 1); | ||
| 614 | } | ||
| 463 | out_finish: | 615 | out_finish: |
| 464 | error = swap_writer_finish(&handle, flags, error); | 616 | error = swap_writer_finish(&handle, flags, error); |
| 465 | return error; | 617 | return error; |
| @@ -590,6 +742,127 @@ static int load_image(struct swap_map_handle *handle, | |||
| 590 | } | 742 | } |
| 591 | 743 | ||
| 592 | /** | 744 | /** |
| 745 | * load_image_lzo - Load compressed image data and decompress them with LZO. | ||
| 746 | * @handle: Swap map handle to use for loading data. | ||
| 747 | * @snapshot: Image to copy uncompressed data into. | ||
| 748 | * @nr_to_read: Number of pages to load. | ||
| 749 | */ | ||
| 750 | static int load_image_lzo(struct swap_map_handle *handle, | ||
| 751 | struct snapshot_handle *snapshot, | ||
| 752 | unsigned int nr_to_read) | ||
| 753 | { | ||
| 754 | unsigned int m; | ||
| 755 | int error = 0; | ||
| 756 | struct timeval start; | ||
| 757 | struct timeval stop; | ||
| 758 | unsigned nr_pages; | ||
| 759 | size_t off, unc_len, cmp_len; | ||
| 760 | unsigned char *unc, *cmp, *page; | ||
| 761 | |||
| 762 | page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); | ||
| 763 | if (!page) { | ||
| 764 | printk(KERN_ERR "PM: Failed to allocate LZO page\n"); | ||
| 765 | return -ENOMEM; | ||
| 766 | } | ||
| 767 | |||
| 768 | unc = vmalloc(LZO_UNC_SIZE); | ||
| 769 | if (!unc) { | ||
| 770 | printk(KERN_ERR "PM: Failed to allocate LZO uncompressed\n"); | ||
| 771 | free_page((unsigned long)page); | ||
| 772 | return -ENOMEM; | ||
| 773 | } | ||
| 774 | |||
| 775 | cmp = vmalloc(LZO_CMP_SIZE); | ||
| 776 | if (!cmp) { | ||
| 777 | printk(KERN_ERR "PM: Failed to allocate LZO compressed\n"); | ||
| 778 | vfree(unc); | ||
| 779 | free_page((unsigned long)page); | ||
| 780 | return -ENOMEM; | ||
| 781 | } | ||
| 782 | |||
| 783 | printk(KERN_INFO | ||
| 784 | "PM: Loading and decompressing image data (%u pages) ... ", | ||
| 785 | nr_to_read); | ||
| 786 | m = nr_to_read / 100; | ||
| 787 | if (!m) | ||
| 788 | m = 1; | ||
| 789 | nr_pages = 0; | ||
| 790 | do_gettimeofday(&start); | ||
| 791 | |||
| 792 | error = snapshot_write_next(snapshot); | ||
| 793 | if (error <= 0) | ||
| 794 | goto out_finish; | ||
| 795 | |||
| 796 | for (;;) { | ||
| 797 | error = swap_read_page(handle, page, NULL); /* sync */ | ||
| 798 | if (error) | ||
| 799 | break; | ||
| 800 | |||
| 801 | cmp_len = *(size_t *)page; | ||
| 802 | if (unlikely(!cmp_len || | ||
| 803 | cmp_len > lzo1x_worst_compress(LZO_UNC_SIZE))) { | ||
| 804 | printk(KERN_ERR "PM: Invalid LZO compressed length\n"); | ||
| 805 | error = -1; | ||
| 806 | break; | ||
| 807 | } | ||
| 808 | |||
| 809 | memcpy(cmp, page, PAGE_SIZE); | ||
| 810 | for (off = PAGE_SIZE; off < LZO_HEADER + cmp_len; off += PAGE_SIZE) { | ||
| 811 | error = swap_read_page(handle, page, NULL); /* sync */ | ||
| 812 | if (error) | ||
| 813 | goto out_finish; | ||
| 814 | |||
| 815 | memcpy(cmp + off, page, PAGE_SIZE); | ||
| 816 | } | ||
| 817 | |||
| 818 | unc_len = LZO_UNC_SIZE; | ||
| 819 | error = lzo1x_decompress_safe(cmp + LZO_HEADER, cmp_len, | ||
| 820 | unc, &unc_len); | ||
| 821 | if (error < 0) { | ||
| 822 | printk(KERN_ERR "PM: LZO decompression failed\n"); | ||
| 823 | break; | ||
| 824 | } | ||
| 825 | |||
| 826 | if (unlikely(!unc_len || | ||
| 827 | unc_len > LZO_UNC_SIZE || | ||
| 828 | unc_len & (PAGE_SIZE - 1))) { | ||
| 829 | printk(KERN_ERR "PM: Invalid LZO uncompressed length\n"); | ||
| 830 | error = -1; | ||
| 831 | break; | ||
| 832 | } | ||
| 833 | |||
| 834 | for (off = 0; off < unc_len; off += PAGE_SIZE) { | ||
| 835 | memcpy(data_of(*snapshot), unc + off, PAGE_SIZE); | ||
| 836 | |||
| 837 | if (!(nr_pages % m)) | ||
| 838 | printk("\b\b\b\b%3d%%", nr_pages / m); | ||
| 839 | nr_pages++; | ||
| 840 | |||
| 841 | error = snapshot_write_next(snapshot); | ||
| 842 | if (error <= 0) | ||
| 843 | goto out_finish; | ||
| 844 | } | ||
| 845 | } | ||
| 846 | |||
| 847 | out_finish: | ||
| 848 | do_gettimeofday(&stop); | ||
| 849 | if (!error) { | ||
| 850 | printk("\b\b\b\bdone\n"); | ||
| 851 | snapshot_write_finalize(snapshot); | ||
| 852 | if (!snapshot_image_loaded(snapshot)) | ||
| 853 | error = -ENODATA; | ||
| 854 | } else | ||
| 855 | printk("\n"); | ||
| 856 | swsusp_show_speed(&start, &stop, nr_to_read, "Read"); | ||
| 857 | |||
| 858 | vfree(cmp); | ||
| 859 | vfree(unc); | ||
| 860 | free_page((unsigned long)page); | ||
| 861 | |||
| 862 | return error; | ||
| 863 | } | ||
| 864 | |||
| 865 | /** | ||
| 593 | * swsusp_read - read the hibernation image. | 866 | * swsusp_read - read the hibernation image. |
| 594 | * @flags_p: flags passed by the "frozen" kernel in the image header should | 867 | * @flags_p: flags passed by the "frozen" kernel in the image header should |
| 595 | * be written into this memeory location | 868 | * be written into this memeory location |
| @@ -612,8 +885,11 @@ int swsusp_read(unsigned int *flags_p) | |||
| 612 | goto end; | 885 | goto end; |
| 613 | if (!error) | 886 | if (!error) |
| 614 | error = swap_read_page(&handle, header, NULL); | 887 | error = swap_read_page(&handle, header, NULL); |
| 615 | if (!error) | 888 | if (!error) { |
| 616 | error = load_image(&handle, &snapshot, header->pages - 1); | 889 | error = (*flags_p & SF_NOCOMPRESS_MODE) ? |
| 890 | load_image(&handle, &snapshot, header->pages - 1) : | ||
| 891 | load_image_lzo(&handle, &snapshot, header->pages - 1); | ||
| 892 | } | ||
| 617 | swap_reader_finish(&handle); | 893 | swap_reader_finish(&handle); |
| 618 | end: | 894 | end: |
| 619 | if (!error) | 895 | if (!error) |
