Merge commit 'v2.6.34-rc7' into tracing/core
[safe/jmp/linux-2.6] / kernel / power / snapshot.c
index 2b1a7bc..be861c2 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/console.h>
 #include <linux/highmem.h>
 #include <linux/list.h>
+#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -233,7 +234,7 @@ static void *chain_alloc(struct chain_allocator *ca, unsigned int size)
 
 #define BM_END_OF_MAP  (~0UL)
 
-#define BM_BITS_PER_BLOCK      (PAGE_SIZE << 3)
+#define BM_BITS_PER_BLOCK      (PAGE_SIZE * BITS_PER_BYTE)
 
 struct bm_block {
        struct list_head hook;  /* hook into a list of bitmap blocks */
@@ -275,7 +276,7 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free);
 
 /**
  *     create_bm_block_list - create a list of block bitmap objects
- *     @nr_blocks - number of blocks to allocate
+ *     @pages - number of pages to track
  *     @list - list to put the allocated blocks into
  *     @ca - chain allocator to be used for allocating memory
  */
@@ -619,7 +620,7 @@ __register_nosave_region(unsigned long start_pfn, unsigned long end_pfn,
                BUG_ON(!region);
        } else
                /* This allocation cannot fail */
-               region = alloc_bootmem_low(sizeof(struct nosave_region));
+               region = alloc_bootmem(sizeof(struct nosave_region));
        region->start_pfn = start_pfn;
        region->end_pfn = end_pfn;
        list_add_tail(&region->list, &nosave_regions);
@@ -853,7 +854,7 @@ static unsigned int count_highmem_pages(void)
        struct zone *zone;
        unsigned int n = 0;
 
-       for_each_zone(zone) {
+       for_each_populated_zone(zone) {
                unsigned long pfn, max_zone_pfn;
 
                if (!is_highmem(zone))
@@ -916,7 +917,7 @@ static unsigned int count_data_pages(void)
        unsigned long pfn, max_zone_pfn;
        unsigned int n = 0;
 
-       for_each_zone(zone) {
+       for_each_populated_zone(zone) {
                if (is_highmem(zone))
                        continue;
 
@@ -1010,7 +1011,7 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
        struct zone *zone;
        unsigned long pfn;
 
-       for_each_zone(zone) {
+       for_each_populated_zone(zone) {
                unsigned long max_zone_pfn;
 
                mark_free_pages(zone);
@@ -1065,7 +1066,7 @@ void swsusp_free(void)
        struct zone *zone;
        unsigned long pfn, max_zone_pfn;
 
-       for_each_zone(zone) {
+       for_each_populated_zone(zone) {
                max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
                for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
                        if (pfn_valid(pfn)) {
@@ -1181,7 +1182,7 @@ static void free_unnecessary_pages(void)
 
        memory_bm_position_reset(&copy_bm);
 
-       while (to_free_normal > 0 && to_free_highmem > 0) {
+       while (to_free_normal > 0 || to_free_highmem > 0) {
                unsigned long pfn = memory_bm_next_pfn(&copy_bm);
                struct page *page = pfn_to_page(pfn);
 
@@ -1204,6 +1205,36 @@ static void free_unnecessary_pages(void)
 }
 
 /**
+ * minimum_image_size - Estimate the minimum acceptable size of an image
+ * @saveable: Number of saveable pages in the system.
+ *
+ * We want to avoid attempting to free too much memory too hard, so estimate the
+ * minimum acceptable size of a hibernation image to use as the lower limit for
+ * preallocating memory.
+ *
+ * We assume that the minimum image size should be proportional to
+ *
+ * [number of saveable pages] - [number of pages that can be freed in theory]
+ *
+ * where the second term is the sum of (1) reclaimable slab pages, (2) active
+ * and (3) inactive anonymouns pages, (4) active and (5) inactive file pages,
+ * minus mapped file pages.
+ */
+static unsigned long minimum_image_size(unsigned long saveable)
+{
+       unsigned long size;
+
+       size = global_page_state(NR_SLAB_RECLAIMABLE)
+               + global_page_state(NR_ACTIVE_ANON)
+               + global_page_state(NR_INACTIVE_ANON)
+               + global_page_state(NR_ACTIVE_FILE)
+               + global_page_state(NR_INACTIVE_FILE)
+               - global_page_state(NR_FILE_MAPPED);
+
+       return saveable <= size ? 0 : saveable - size;
+}
+
+/**
  * hibernate_preallocate_memory - Preallocate memory for hibernation image
  *
  * To create a hibernation image it is necessary to make a copy of every page
@@ -1220,8 +1251,8 @@ static void free_unnecessary_pages(void)
  *
  * If image_size is set below the number following from the above formula,
  * the preallocation of memory is continued until the total number of saveable
- * pages in the system is below the requested image size or it is impossible to
- * allocate more memory, whichever happens first.
+ * pages in the system is below the requested image size or the minimum
+ * acceptable image size returned by minimum_image_size(), whichever is greater.
  */
 int hibernate_preallocate_memory(void)
 {
@@ -1282,6 +1313,11 @@ int hibernate_preallocate_memory(void)
                goto out;
        }
 
+       /* Estimate the minimum size of the image. */
+       pages = minimum_image_size(saveable);
+       if (size < pages)
+               size = min_t(unsigned long, pages, max_size);
+
        /*
         * Let the memory management subsystem know that we're going to need a
         * large number of page frames to allocate and make it free some memory.
@@ -1294,8 +1330,8 @@ int hibernate_preallocate_memory(void)
         * The number of saveable pages in memory was too high, so apply some
         * pressure to decrease it.  First, make room for the largest possible
         * image and fail if that doesn't work.  Next, try to decrease the size
-        * of the image as much as indicated by image_size using allocations
-        * from highmem and non-highmem zones separately.
+        * of the image as much as indicated by 'size' using allocations from
+        * highmem and non-highmem zones separately.
         */
        pages_highmem = preallocate_image_highmem(highmem / 2);
        alloc = (count - max_size) - pages_highmem;
@@ -1362,7 +1398,7 @@ static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
        struct zone *zone;
        unsigned int free = alloc_normal;
 
-       for_each_zone(zone)
+       for_each_populated_zone(zone)
                if (!is_highmem(zone))
                        free += zone_page_state(zone, NR_FREE_PAGES);
 
@@ -1465,7 +1501,7 @@ asmlinkage int swsusp_save(void)
 {
        unsigned int nr_pages, nr_highmem;
 
-       printk(KERN_INFO "PM: Creating hibernation image: \n");
+       printk(KERN_INFO "PM: Creating hibernation image:\n");
 
        drain_local_pages(NULL);
        nr_pages = count_data_pages();
@@ -1653,7 +1689,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm)
        unsigned long pfn, max_zone_pfn;
 
        /* Clear page flags */
-       for_each_zone(zone) {
+       for_each_populated_zone(zone) {
                max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
                for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
                        if (pfn_valid(pfn))