diff options
Diffstat (limited to 'kernel/power/swsusp.c')
| -rw-r--r-- | kernel/power/swsusp.c | 251 |
1 files changed, 90 insertions, 161 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 12db1d2ad61f..c05f46e7348f 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
| @@ -73,6 +73,14 @@ | |||
| 73 | 73 | ||
| 74 | #include "power.h" | 74 | #include "power.h" |
| 75 | 75 | ||
| 76 | #ifdef CONFIG_HIGHMEM | ||
| 77 | int save_highmem(void); | ||
| 78 | int restore_highmem(void); | ||
| 79 | #else | ||
| 80 | static int save_highmem(void) { return 0; } | ||
| 81 | static int restore_highmem(void) { return 0; } | ||
| 82 | #endif | ||
| 83 | |||
| 76 | #define CIPHER "aes" | 84 | #define CIPHER "aes" |
| 77 | #define MAXKEY 32 | 85 | #define MAXKEY 32 |
| 78 | #define MAXIV 32 | 86 | #define MAXIV 32 |
| @@ -85,18 +93,11 @@ unsigned int nr_copy_pages __nosavedata = 0; | |||
| 85 | /* Suspend pagedir is allocated before final copy, therefore it | 93 | /* Suspend pagedir is allocated before final copy, therefore it |
| 86 | must be freed after resume | 94 | must be freed after resume |
| 87 | 95 | ||
| 88 | Warning: this is evil. There are actually two pagedirs at time of | ||
| 89 | resume. One is "pagedir_save", which is empty frame allocated at | ||
| 90 | time of suspend, that must be freed. Second is "pagedir_nosave", | ||
| 91 | allocated at time of resume, that travels through memory not to | ||
| 92 | collide with anything. | ||
| 93 | |||
| 94 | Warning: this is even more evil than it seems. Pagedirs this file | 96 | Warning: this is even more evil than it seems. Pagedirs this file |
| 95 | talks about are completely different from page directories used by | 97 | talks about are completely different from page directories used by |
| 96 | MMU hardware. | 98 | MMU hardware. |
| 97 | */ | 99 | */ |
| 98 | suspend_pagedir_t *pagedir_nosave __nosavedata = NULL; | 100 | suspend_pagedir_t *pagedir_nosave __nosavedata = NULL; |
| 99 | suspend_pagedir_t *pagedir_save; | ||
| 100 | 101 | ||
| 101 | #define SWSUSP_SIG "S1SUSPEND" | 102 | #define SWSUSP_SIG "S1SUSPEND" |
| 102 | 103 | ||
| @@ -122,8 +123,8 @@ static struct swsusp_info swsusp_info; | |||
| 122 | static unsigned short swapfile_used[MAX_SWAPFILES]; | 123 | static unsigned short swapfile_used[MAX_SWAPFILES]; |
| 123 | static unsigned short root_swap; | 124 | static unsigned short root_swap; |
| 124 | 125 | ||
| 125 | static int write_page(unsigned long addr, swp_entry_t * loc); | 126 | static int write_page(unsigned long addr, swp_entry_t *loc); |
| 126 | static int bio_read_page(pgoff_t page_off, void * page); | 127 | static int bio_read_page(pgoff_t page_off, void *page); |
| 127 | 128 | ||
| 128 | static u8 key_iv[MAXKEY+MAXIV]; | 129 | static u8 key_iv[MAXKEY+MAXIV]; |
| 129 | 130 | ||
| @@ -355,7 +356,7 @@ static void lock_swapdevices(void) | |||
| 355 | * This is a partial improvement, since we will at least return other | 356 | * This is a partial improvement, since we will at least return other |
| 356 | * errors, though we need to eventually fix the damn code. | 357 | * errors, though we need to eventually fix the damn code. |
| 357 | */ | 358 | */ |
| 358 | static int write_page(unsigned long addr, swp_entry_t * loc) | 359 | static int write_page(unsigned long addr, swp_entry_t *loc) |
| 359 | { | 360 | { |
| 360 | swp_entry_t entry; | 361 | swp_entry_t entry; |
| 361 | int error = 0; | 362 | int error = 0; |
| @@ -383,9 +384,9 @@ static int write_page(unsigned long addr, swp_entry_t * loc) | |||
| 383 | static void data_free(void) | 384 | static void data_free(void) |
| 384 | { | 385 | { |
| 385 | swp_entry_t entry; | 386 | swp_entry_t entry; |
| 386 | struct pbe * p; | 387 | struct pbe *p; |
| 387 | 388 | ||
| 388 | for_each_pbe(p, pagedir_nosave) { | 389 | for_each_pbe (p, pagedir_nosave) { |
| 389 | entry = p->swap_address; | 390 | entry = p->swap_address; |
| 390 | if (entry.val) | 391 | if (entry.val) |
| 391 | swap_free(entry); | 392 | swap_free(entry); |
| @@ -492,8 +493,8 @@ static void free_pagedir_entries(void) | |||
| 492 | static int write_pagedir(void) | 493 | static int write_pagedir(void) |
| 493 | { | 494 | { |
| 494 | int error = 0; | 495 | int error = 0; |
| 495 | unsigned n = 0; | 496 | unsigned int n = 0; |
| 496 | struct pbe * pbe; | 497 | struct pbe *pbe; |
| 497 | 498 | ||
| 498 | printk( "Writing pagedir..."); | 499 | printk( "Writing pagedir..."); |
| 499 | for_each_pb_page (pbe, pagedir_nosave) { | 500 | for_each_pb_page (pbe, pagedir_nosave) { |
| @@ -507,6 +508,26 @@ static int write_pagedir(void) | |||
| 507 | } | 508 | } |
| 508 | 509 | ||
| 509 | /** | 510 | /** |
| 511 | * enough_swap - Make sure we have enough swap to save the image. | ||
| 512 | * | ||
| 513 | * Returns TRUE or FALSE after checking the total amount of swap | ||
| 514 | * space avaiable. | ||
| 515 | * | ||
| 516 | * FIXME: si_swapinfo(&i) returns all swap devices information. | ||
| 517 | * We should only consider resume_device. | ||
| 518 | */ | ||
| 519 | |||
| 520 | static int enough_swap(unsigned int nr_pages) | ||
| 521 | { | ||
| 522 | struct sysinfo i; | ||
| 523 | |||
| 524 | si_swapinfo(&i); | ||
| 525 | pr_debug("swsusp: available swap: %lu pages\n", i.freeswap); | ||
| 526 | return i.freeswap > (nr_pages + PAGES_FOR_IO + | ||
| 527 | (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); | ||
| 528 | } | ||
| 529 | |||
| 530 | /** | ||
| 510 | * write_suspend_image - Write entire image and metadata. | 531 | * write_suspend_image - Write entire image and metadata. |
| 511 | * | 532 | * |
| 512 | */ | 533 | */ |
| @@ -514,6 +535,11 @@ static int write_suspend_image(void) | |||
| 514 | { | 535 | { |
| 515 | int error; | 536 | int error; |
| 516 | 537 | ||
| 538 | if (!enough_swap(nr_copy_pages)) { | ||
| 539 | printk(KERN_ERR "swsusp: Not enough free swap\n"); | ||
| 540 | return -ENOSPC; | ||
| 541 | } | ||
| 542 | |||
| 517 | init_header(); | 543 | init_header(); |
| 518 | if ((error = data_write())) | 544 | if ((error = data_write())) |
| 519 | goto FreeData; | 545 | goto FreeData; |
| @@ -533,27 +559,6 @@ static int write_suspend_image(void) | |||
| 533 | goto Done; | 559 | goto Done; |
| 534 | } | 560 | } |
| 535 | 561 | ||
| 536 | /** | ||
| 537 | * enough_swap - Make sure we have enough swap to save the image. | ||
| 538 | * | ||
| 539 | * Returns TRUE or FALSE after checking the total amount of swap | ||
| 540 | * space avaiable. | ||
| 541 | * | ||
| 542 | * FIXME: si_swapinfo(&i) returns all swap devices information. | ||
| 543 | * We should only consider resume_device. | ||
| 544 | */ | ||
| 545 | |||
| 546 | int enough_swap(unsigned nr_pages) | ||
| 547 | { | ||
| 548 | struct sysinfo i; | ||
| 549 | |||
| 550 | si_swapinfo(&i); | ||
| 551 | pr_debug("swsusp: available swap: %lu pages\n", i.freeswap); | ||
| 552 | return i.freeswap > (nr_pages + PAGES_FOR_IO + | ||
| 553 | (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); | ||
| 554 | } | ||
| 555 | |||
| 556 | |||
| 557 | /* It is important _NOT_ to umount filesystems at this point. We want | 562 | /* It is important _NOT_ to umount filesystems at this point. We want |
| 558 | * them synced (in case something goes wrong) but we DO not want to mark | 563 | * them synced (in case something goes wrong) but we DO not want to mark |
| 559 | * filesystem clean: it is not. (And it does not matter, if we resume | 564 | * filesystem clean: it is not. (And it does not matter, if we resume |
| @@ -563,12 +568,15 @@ int swsusp_write(void) | |||
| 563 | { | 568 | { |
| 564 | int error; | 569 | int error; |
| 565 | 570 | ||
| 571 | if ((error = swsusp_swap_check())) { | ||
| 572 | printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n"); | ||
| 573 | return error; | ||
| 574 | } | ||
| 566 | lock_swapdevices(); | 575 | lock_swapdevices(); |
| 567 | error = write_suspend_image(); | 576 | error = write_suspend_image(); |
| 568 | /* This will unlock ignored swap devices since writing is finished */ | 577 | /* This will unlock ignored swap devices since writing is finished */ |
| 569 | lock_swapdevices(); | 578 | lock_swapdevices(); |
| 570 | return error; | 579 | return error; |
| 571 | |||
| 572 | } | 580 | } |
| 573 | 581 | ||
| 574 | 582 | ||
| @@ -576,6 +584,7 @@ int swsusp_write(void) | |||
| 576 | int swsusp_suspend(void) | 584 | int swsusp_suspend(void) |
| 577 | { | 585 | { |
| 578 | int error; | 586 | int error; |
| 587 | |||
| 579 | if ((error = arch_prepare_suspend())) | 588 | if ((error = arch_prepare_suspend())) |
| 580 | return error; | 589 | return error; |
| 581 | local_irq_disable(); | 590 | local_irq_disable(); |
| @@ -587,15 +596,12 @@ int swsusp_suspend(void) | |||
| 587 | */ | 596 | */ |
| 588 | if ((error = device_power_down(PMSG_FREEZE))) { | 597 | if ((error = device_power_down(PMSG_FREEZE))) { |
| 589 | printk(KERN_ERR "Some devices failed to power down, aborting suspend\n"); | 598 | printk(KERN_ERR "Some devices failed to power down, aborting suspend\n"); |
| 590 | local_irq_enable(); | 599 | goto Enable_irqs; |
| 591 | return error; | ||
| 592 | } | 600 | } |
| 593 | 601 | ||
| 594 | if ((error = swsusp_swap_check())) { | 602 | if ((error = save_highmem())) { |
| 595 | printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n"); | 603 | printk(KERN_ERR "swsusp: Not enough free pages for highmem\n"); |
| 596 | device_power_up(); | 604 | goto Restore_highmem; |
| 597 | local_irq_enable(); | ||
| 598 | return error; | ||
| 599 | } | 605 | } |
| 600 | 606 | ||
| 601 | save_processor_state(); | 607 | save_processor_state(); |
| @@ -603,8 +609,10 @@ int swsusp_suspend(void) | |||
| 603 | printk(KERN_ERR "Error %d suspending\n", error); | 609 | printk(KERN_ERR "Error %d suspending\n", error); |
| 604 | /* Restore control flow magically appears here */ | 610 | /* Restore control flow magically appears here */ |
| 605 | restore_processor_state(); | 611 | restore_processor_state(); |
| 612 | Restore_highmem: | ||
| 606 | restore_highmem(); | 613 | restore_highmem(); |
| 607 | device_power_up(); | 614 | device_power_up(); |
| 615 | Enable_irqs: | ||
| 608 | local_irq_enable(); | 616 | local_irq_enable(); |
| 609 | return error; | 617 | return error; |
| 610 | } | 618 | } |
| @@ -636,127 +644,43 @@ int swsusp_resume(void) | |||
| 636 | } | 644 | } |
| 637 | 645 | ||
| 638 | /** | 646 | /** |
| 639 | * On resume, for storing the PBE list and the image, | 647 | * mark_unsafe_pages - mark the pages that cannot be used for storing |
| 640 | * we can only use memory pages that do not conflict with the pages | 648 | * the image during resume, because they conflict with the pages that |
| 641 | * which had been used before suspend. | 649 | * had been used before suspend |
| 642 | * | ||
| 643 | * We don't know which pages are usable until we allocate them. | ||
| 644 | * | ||
| 645 | * Allocated but unusable (ie eaten) memory pages are marked so that | ||
| 646 | * swsusp_free() can release them | ||
| 647 | */ | ||
| 648 | |||
| 649 | unsigned long get_safe_page(gfp_t gfp_mask) | ||
| 650 | { | ||
| 651 | unsigned long m; | ||
| 652 | |||
| 653 | do { | ||
| 654 | m = get_zeroed_page(gfp_mask); | ||
| 655 | if (m && PageNosaveFree(virt_to_page(m))) | ||
| 656 | /* This is for swsusp_free() */ | ||
| 657 | SetPageNosave(virt_to_page(m)); | ||
| 658 | } while (m && PageNosaveFree(virt_to_page(m))); | ||
| 659 | if (m) { | ||
| 660 | /* This is for swsusp_free() */ | ||
| 661 | SetPageNosave(virt_to_page(m)); | ||
| 662 | SetPageNosaveFree(virt_to_page(m)); | ||
| 663 | } | ||
| 664 | return m; | ||
| 665 | } | ||
| 666 | |||
| 667 | /** | ||
| 668 | * check_pagedir - We ensure here that pages that the PBEs point to | ||
| 669 | * won't collide with pages where we're going to restore from the loaded | ||
| 670 | * pages later | ||
| 671 | */ | ||
| 672 | |||
| 673 | static int check_pagedir(struct pbe *pblist) | ||
| 674 | { | ||
| 675 | struct pbe *p; | ||
| 676 | |||
| 677 | /* This is necessary, so that we can free allocated pages | ||
| 678 | * in case of failure | ||
| 679 | */ | ||
| 680 | for_each_pbe (p, pblist) | ||
| 681 | p->address = 0UL; | ||
| 682 | |||
| 683 | for_each_pbe (p, pblist) { | ||
| 684 | p->address = get_safe_page(GFP_ATOMIC); | ||
| 685 | if (!p->address) | ||
| 686 | return -ENOMEM; | ||
| 687 | } | ||
| 688 | return 0; | ||
| 689 | } | ||
| 690 | |||
| 691 | /** | ||
| 692 | * swsusp_pagedir_relocate - It is possible, that some memory pages | ||
| 693 | * occupied by the list of PBEs collide with pages where we're going to | ||
| 694 | * restore from the loaded pages later. We relocate them here. | ||
| 695 | */ | 650 | */ |
| 696 | 651 | ||
| 697 | static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) | 652 | static void mark_unsafe_pages(struct pbe *pblist) |
| 698 | { | 653 | { |
| 699 | struct zone *zone; | 654 | struct zone *zone; |
| 700 | unsigned long zone_pfn; | 655 | unsigned long zone_pfn; |
| 701 | struct pbe *pbpage, *tail, *p; | 656 | struct pbe *p; |
| 702 | void *m; | ||
| 703 | int rel = 0; | ||
| 704 | 657 | ||
| 705 | if (!pblist) /* a sanity check */ | 658 | if (!pblist) /* a sanity check */ |
| 706 | return NULL; | 659 | return; |
| 707 | |||
| 708 | pr_debug("swsusp: Relocating pagedir (%lu pages to check)\n", | ||
| 709 | swsusp_info.pagedir_pages); | ||
| 710 | 660 | ||
| 711 | /* Clear page flags */ | 661 | /* Clear page flags */ |
| 712 | |||
| 713 | for_each_zone (zone) { | 662 | for_each_zone (zone) { |
| 714 | for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) | 663 | for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) |
| 715 | if (pfn_valid(zone_pfn + zone->zone_start_pfn)) | 664 | if (pfn_valid(zone_pfn + zone->zone_start_pfn)) |
| 716 | ClearPageNosaveFree(pfn_to_page(zone_pfn + | 665 | ClearPageNosaveFree(pfn_to_page(zone_pfn + |
| 717 | zone->zone_start_pfn)); | 666 | zone->zone_start_pfn)); |
| 718 | } | 667 | } |
| 719 | 668 | ||
| 720 | /* Mark orig addresses */ | 669 | /* Mark orig addresses */ |
| 721 | |||
| 722 | for_each_pbe (p, pblist) | 670 | for_each_pbe (p, pblist) |
| 723 | SetPageNosaveFree(virt_to_page(p->orig_address)); | 671 | SetPageNosaveFree(virt_to_page(p->orig_address)); |
| 724 | 672 | ||
| 725 | tail = pblist + PB_PAGE_SKIP; | 673 | } |
| 726 | |||
| 727 | /* Relocate colliding pages */ | ||
| 728 | |||
| 729 | for_each_pb_page (pbpage, pblist) { | ||
| 730 | if (PageNosaveFree(virt_to_page((unsigned long)pbpage))) { | ||
| 731 | m = (void *)get_safe_page(GFP_ATOMIC | __GFP_COLD); | ||
| 732 | if (!m) | ||
| 733 | return NULL; | ||
| 734 | memcpy(m, (void *)pbpage, PAGE_SIZE); | ||
| 735 | if (pbpage == pblist) | ||
| 736 | pblist = (struct pbe *)m; | ||
| 737 | else | ||
| 738 | tail->next = (struct pbe *)m; | ||
| 739 | pbpage = (struct pbe *)m; | ||
| 740 | |||
| 741 | /* We have to link the PBEs again */ | ||
| 742 | for (p = pbpage; p < pbpage + PB_PAGE_SKIP; p++) | ||
| 743 | if (p->next) /* needed to save the end */ | ||
| 744 | p->next = p + 1; | ||
| 745 | |||
| 746 | rel++; | ||
| 747 | } | ||
| 748 | tail = pbpage + PB_PAGE_SKIP; | ||
| 749 | } | ||
| 750 | 674 | ||
| 751 | /* This is for swsusp_free() */ | 675 | static void copy_page_backup_list(struct pbe *dst, struct pbe *src) |
| 752 | for_each_pb_page (pbpage, pblist) { | 676 | { |
| 753 | SetPageNosave(virt_to_page(pbpage)); | 677 | /* We assume both lists contain the same number of elements */ |
| 754 | SetPageNosaveFree(virt_to_page(pbpage)); | 678 | while (src) { |
| 679 | dst->orig_address = src->orig_address; | ||
| 680 | dst->swap_address = src->swap_address; | ||
| 681 | dst = dst->next; | ||
| 682 | src = src->next; | ||
| 755 | } | 683 | } |
| 756 | |||
| 757 | printk("swsusp: Relocated %d pages\n", rel); | ||
| 758 | |||
| 759 | return pblist; | ||
| 760 | } | 684 | } |
| 761 | 685 | ||
| 762 | /* | 686 | /* |
| @@ -770,7 +694,7 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) | |||
| 770 | 694 | ||
| 771 | static atomic_t io_done = ATOMIC_INIT(0); | 695 | static atomic_t io_done = ATOMIC_INIT(0); |
| 772 | 696 | ||
| 773 | static int end_io(struct bio * bio, unsigned int num, int err) | 697 | static int end_io(struct bio *bio, unsigned int num, int err) |
| 774 | { | 698 | { |
| 775 | if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) | 699 | if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) |
| 776 | panic("I/O error reading memory image"); | 700 | panic("I/O error reading memory image"); |
| @@ -778,7 +702,7 @@ static int end_io(struct bio * bio, unsigned int num, int err) | |||
| 778 | return 0; | 702 | return 0; |
| 779 | } | 703 | } |
| 780 | 704 | ||
| 781 | static struct block_device * resume_bdev; | 705 | static struct block_device *resume_bdev; |
| 782 | 706 | ||
| 783 | /** | 707 | /** |
| 784 | * submit - submit BIO request. | 708 | * submit - submit BIO request. |
| @@ -791,10 +715,10 @@ static struct block_device * resume_bdev; | |||
| 791 | * Then submit it and wait. | 715 | * Then submit it and wait. |
| 792 | */ | 716 | */ |
| 793 | 717 | ||
| 794 | static int submit(int rw, pgoff_t page_off, void * page) | 718 | static int submit(int rw, pgoff_t page_off, void *page) |
| 795 | { | 719 | { |
| 796 | int error = 0; | 720 | int error = 0; |
| 797 | struct bio * bio; | 721 | struct bio *bio; |
| 798 | 722 | ||
| 799 | bio = bio_alloc(GFP_ATOMIC, 1); | 723 | bio = bio_alloc(GFP_ATOMIC, 1); |
| 800 | if (!bio) | 724 | if (!bio) |
| @@ -823,12 +747,12 @@ static int submit(int rw, pgoff_t page_off, void * page) | |||
| 823 | return error; | 747 | return error; |
| 824 | } | 748 | } |
| 825 | 749 | ||
| 826 | static int bio_read_page(pgoff_t page_off, void * page) | 750 | static int bio_read_page(pgoff_t page_off, void *page) |
| 827 | { | 751 | { |
| 828 | return submit(READ, page_off, page); | 752 | return submit(READ, page_off, page); |
| 829 | } | 753 | } |
| 830 | 754 | ||
| 831 | static int bio_write_page(pgoff_t page_off, void * page) | 755 | static int bio_write_page(pgoff_t page_off, void *page) |
| 832 | { | 756 | { |
| 833 | return submit(WRITE, page_off, page); | 757 | return submit(WRITE, page_off, page); |
| 834 | } | 758 | } |
| @@ -838,7 +762,7 @@ static int bio_write_page(pgoff_t page_off, void * page) | |||
| 838 | * I really don't think that it's foolproof but more than nothing.. | 762 | * I really don't think that it's foolproof but more than nothing.. |
| 839 | */ | 763 | */ |
| 840 | 764 | ||
| 841 | static const char * sanity_check(void) | 765 | static const char *sanity_check(void) |
| 842 | { | 766 | { |
| 843 | dump_info(); | 767 | dump_info(); |
| 844 | if (swsusp_info.version_code != LINUX_VERSION_CODE) | 768 | if (swsusp_info.version_code != LINUX_VERSION_CODE) |
| @@ -864,7 +788,7 @@ static const char * sanity_check(void) | |||
| 864 | 788 | ||
| 865 | static int check_header(void) | 789 | static int check_header(void) |
| 866 | { | 790 | { |
| 867 | const char * reason = NULL; | 791 | const char *reason = NULL; |
| 868 | int error; | 792 | int error; |
| 869 | 793 | ||
| 870 | if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info))) | 794 | if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info))) |
| @@ -895,7 +819,7 @@ static int check_sig(void) | |||
| 895 | * Reset swap signature now. | 819 | * Reset swap signature now. |
| 896 | */ | 820 | */ |
| 897 | error = bio_write_page(0, &swsusp_header); | 821 | error = bio_write_page(0, &swsusp_header); |
| 898 | } else { | 822 | } else { |
| 899 | return -EINVAL; | 823 | return -EINVAL; |
| 900 | } | 824 | } |
| 901 | if (!error) | 825 | if (!error) |
| @@ -912,7 +836,7 @@ static int check_sig(void) | |||
| 912 | 836 | ||
| 913 | static int data_read(struct pbe *pblist) | 837 | static int data_read(struct pbe *pblist) |
| 914 | { | 838 | { |
| 915 | struct pbe * p; | 839 | struct pbe *p; |
| 916 | int error = 0; | 840 | int error = 0; |
| 917 | int i = 0; | 841 | int i = 0; |
| 918 | int mod = swsusp_info.image_pages / 100; | 842 | int mod = swsusp_info.image_pages / 100; |
| @@ -950,7 +874,7 @@ static int data_read(struct pbe *pblist) | |||
| 950 | static int read_pagedir(struct pbe *pblist) | 874 | static int read_pagedir(struct pbe *pblist) |
| 951 | { | 875 | { |
| 952 | struct pbe *pbpage, *p; | 876 | struct pbe *pbpage, *p; |
| 953 | unsigned i = 0; | 877 | unsigned int i = 0; |
| 954 | int error; | 878 | int error; |
| 955 | 879 | ||
| 956 | if (!pblist) | 880 | if (!pblist) |
| @@ -997,20 +921,25 @@ static int read_suspend_image(void) | |||
| 997 | int error = 0; | 921 | int error = 0; |
| 998 | struct pbe *p; | 922 | struct pbe *p; |
| 999 | 923 | ||
| 1000 | if (!(p = alloc_pagedir(nr_copy_pages))) | 924 | if (!(p = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 0))) |
| 1001 | return -ENOMEM; | 925 | return -ENOMEM; |
| 1002 | 926 | ||
| 1003 | if ((error = read_pagedir(p))) | 927 | if ((error = read_pagedir(p))) |
| 1004 | return error; | 928 | return error; |
| 1005 | |||
| 1006 | create_pbe_list(p, nr_copy_pages); | 929 | create_pbe_list(p, nr_copy_pages); |
| 1007 | 930 | mark_unsafe_pages(p); | |
| 1008 | if (!(pagedir_nosave = swsusp_pagedir_relocate(p))) | 931 | pagedir_nosave = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1); |
| 932 | if (pagedir_nosave) { | ||
| 933 | create_pbe_list(pagedir_nosave, nr_copy_pages); | ||
| 934 | copy_page_backup_list(pagedir_nosave, p); | ||
| 935 | } | ||
| 936 | free_pagedir(p); | ||
| 937 | if (!pagedir_nosave) | ||
| 1009 | return -ENOMEM; | 938 | return -ENOMEM; |
| 1010 | 939 | ||
| 1011 | /* Allocate memory for the image and read the data from swap */ | 940 | /* Allocate memory for the image and read the data from swap */ |
| 1012 | 941 | ||
| 1013 | error = check_pagedir(pagedir_nosave); | 942 | error = alloc_data_pages(pagedir_nosave, GFP_ATOMIC, 1); |
| 1014 | 943 | ||
| 1015 | if (!error) | 944 | if (!error) |
| 1016 | error = data_read(pagedir_nosave); | 945 | error = data_read(pagedir_nosave); |
