diff options
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r-- | kernel/power/swsusp.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index b09bd7c0998d..f77f9397a364 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
@@ -70,11 +70,13 @@ | |||
70 | #include "power.h" | 70 | #include "power.h" |
71 | 71 | ||
72 | #ifdef CONFIG_HIGHMEM | 72 | #ifdef CONFIG_HIGHMEM |
73 | unsigned int count_highmem_pages(void); | ||
73 | int save_highmem(void); | 74 | int save_highmem(void); |
74 | int restore_highmem(void); | 75 | int restore_highmem(void); |
75 | #else | 76 | #else |
76 | static int save_highmem(void) { return 0; } | 77 | static int save_highmem(void) { return 0; } |
77 | static int restore_highmem(void) { return 0; } | 78 | static int restore_highmem(void) { return 0; } |
79 | static unsigned int count_highmem_pages(void) { return 0; } | ||
78 | #endif | 80 | #endif |
79 | 81 | ||
80 | extern char resume_file[]; | 82 | extern char resume_file[]; |
@@ -611,6 +613,52 @@ int swsusp_write(struct pbe *pblist, unsigned int nr_pages) | |||
611 | return error; | 613 | return error; |
612 | } | 614 | } |
613 | 615 | ||
616 | /** | ||
617 | * swsusp_shrink_memory - Try to free as much memory as needed | ||
618 | * | ||
619 | * ... but do not OOM-kill anyone | ||
620 | * | ||
621 | * Notice: all userland should be stopped before it is called, or | ||
622 | * livelock is possible. | ||
623 | */ | ||
624 | |||
625 | #define SHRINK_BITE 10000 | ||
626 | |||
627 | int swsusp_shrink_memory(void) | ||
628 | { | ||
629 | long tmp; | ||
630 | struct zone *zone; | ||
631 | unsigned long pages = 0; | ||
632 | unsigned int i = 0; | ||
633 | char *p = "-\\|/"; | ||
634 | |||
635 | printk("Shrinking memory... "); | ||
636 | do { | ||
637 | #ifdef FAST_FREE | ||
638 | tmp = 2 * count_highmem_pages(); | ||
639 | tmp += tmp / 50 + count_data_pages(); | ||
640 | tmp += (tmp + PBES_PER_PAGE - 1) / PBES_PER_PAGE + | ||
641 | PAGES_FOR_IO; | ||
642 | for_each_zone (zone) | ||
643 | if (!is_highmem(zone)) | ||
644 | tmp -= zone->free_pages; | ||
645 | if (tmp > 0) { | ||
646 | tmp = shrink_all_memory(SHRINK_BITE); | ||
647 | if (!tmp) | ||
648 | return -ENOMEM; | ||
649 | pages += tmp; | ||
650 | } | ||
651 | #else | ||
652 | tmp = shrink_all_memory(SHRINK_BITE); | ||
653 | pages += tmp; | ||
654 | #endif | ||
655 | printk("\b%c", p[i++%4]); | ||
656 | } while (tmp > 0); | ||
657 | printk("\bdone (%lu pages freed)\n", pages); | ||
658 | |||
659 | return 0; | ||
660 | } | ||
661 | |||
614 | int swsusp_suspend(void) | 662 | int swsusp_suspend(void) |
615 | { | 663 | { |
616 | int error; | 664 | int error; |
@@ -1030,8 +1078,10 @@ static int read_suspend_image(struct pbe **pblist_ptr) | |||
1030 | /* Allocate memory for the image and read the data from swap */ | 1078 | /* Allocate memory for the image and read the data from swap */ |
1031 | if (!error) | 1079 | if (!error) |
1032 | error = alloc_data_pages(pblist, GFP_ATOMIC, 1); | 1080 | error = alloc_data_pages(pblist, GFP_ATOMIC, 1); |
1033 | if (!error) | 1081 | if (!error) { |
1082 | release_eaten_pages(); | ||
1034 | error = load_image_data(pblist, &handle, nr_pages); | 1083 | error = load_image_data(pblist, &handle, nr_pages); |
1084 | } | ||
1035 | if (!error) | 1085 | if (!error) |
1036 | *pblist_ptr = pblist; | 1086 | *pblist_ptr = pblist; |
1037 | } | 1087 | } |