aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/swsusp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r--kernel/power/swsusp.c52
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
73unsigned int count_highmem_pages(void);
73int save_highmem(void); 74int save_highmem(void);
74int restore_highmem(void); 75int restore_highmem(void);
75#else 76#else
76static int save_highmem(void) { return 0; } 77static int save_highmem(void) { return 0; }
77static int restore_highmem(void) { return 0; } 78static int restore_highmem(void) { return 0; }
79static unsigned int count_highmem_pages(void) { return 0; }
78#endif 80#endif
79 81
80extern char resume_file[]; 82extern 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
627int 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
614int swsusp_suspend(void) 662int 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 }