]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blobdiff - kernel/power/snapshot.c
x86 vdso: fix build locale dependency
[mirror_ubuntu-kernels.git] / kernel / power / snapshot.c
index ccc95ac07bedbc8cbfed19b06a3eca9848b11723..72a020cabb4c5238f395c1aa6420a630dc8b49dc 100644 (file)
@@ -635,7 +635,7 @@ __register_nosave_region(unsigned long start_pfn, unsigned long end_pfn,
        region->end_pfn = end_pfn;
        list_add_tail(&region->list, &nosave_regions);
  Report:
-       printk("swsusp: Registered nosave memory region: %016lx - %016lx\n",
+       printk(KERN_INFO "PM: Registered nosave memory: %016lx - %016lx\n",
                start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
 }
 
@@ -704,7 +704,7 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
        list_for_each_entry(region, &nosave_regions, list) {
                unsigned long pfn;
 
-               printk("swsusp: Marking nosave pages: %016lx - %016lx\n",
+               pr_debug("PM: Marking nosave pages: %016lx - %016lx\n",
                                region->start_pfn << PAGE_SHIFT,
                                region->end_pfn << PAGE_SHIFT);
 
@@ -749,7 +749,7 @@ int create_basic_memory_bitmaps(void)
        free_pages_map = bm2;
        mark_nosave_pages(forbidden_pages_map);
 
-       printk("swsusp: Basic memory bitmaps created\n");
+       pr_debug("PM: Basic memory bitmaps created\n");
 
        return 0;
 
@@ -784,7 +784,7 @@ void free_basic_memory_bitmaps(void)
        memory_bm_free(bm2, PG_UNSAFE_CLEAR);
        kfree(bm2);
 
-       printk("swsusp: Basic memory bitmaps freed\n");
+       pr_debug("PM: Basic memory bitmaps freed\n");
 }
 
 /**
@@ -872,12 +872,11 @@ unsigned int count_highmem_pages(void)
 }
 #else
 static inline void *saveable_highmem_page(unsigned long pfn) { return NULL; }
-static inline unsigned int count_highmem_pages(void) { return 0; }
 #endif /* CONFIG_HIGHMEM */
 
 /**
- *     saveable - Determine whether a non-highmem page should be included in
- *     the suspend image.
+ *     saveable_page - Determine whether a non-highmem page should be included
+ *     in the suspend image.
  *
  *     We should save the page if it isn't Nosave, and is not in the range
  *     of pages statically defined as 'unsaveable', and it isn't a part of
@@ -898,7 +897,8 @@ static struct page *saveable_page(unsigned long pfn)
        if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page))
                return NULL;
 
-       if (PageReserved(page) && pfn_is_nosave(pfn))
+       if (PageReserved(page)
+           && (!kernel_page_present(page) || pfn_is_nosave(pfn)))
                return NULL;
 
        return page;
@@ -939,6 +939,25 @@ static inline void do_copy_page(long *dst, long *src)
                *dst++ = *src++;
 }
 
+
+/**
+ *     safe_copy_page - check if the page we are going to copy is marked as
+ *             present in the kernel page tables (this always is the case if
+ *             CONFIG_DEBUG_PAGEALLOC is not set and in that case
+ *             kernel_page_present() always returns 'true').
+ */
+static void safe_copy_page(void *dst, struct page *s_page)
+{
+       if (kernel_page_present(s_page)) {
+               do_copy_page(dst, page_address(s_page));
+       } else {
+               kernel_map_pages(s_page, 1, 1);
+               do_copy_page(dst, page_address(s_page));
+               kernel_map_pages(s_page, 1, 0);
+       }
+}
+
+
 #ifdef CONFIG_HIGHMEM
 static inline struct page *
 page_is_saveable(struct zone *zone, unsigned long pfn)
@@ -947,8 +966,7 @@ page_is_saveable(struct zone *zone, unsigned long pfn)
                        saveable_highmem_page(pfn) : saveable_page(pfn);
 }
 
-static inline void
-copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
+static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
 {
        struct page *s_page, *d_page;
        void *src, *dst;
@@ -962,29 +980,26 @@ copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
                kunmap_atomic(src, KM_USER0);
                kunmap_atomic(dst, KM_USER1);
        } else {
-               src = page_address(s_page);
                if (PageHighMem(d_page)) {
                        /* Page pointed to by src may contain some kernel
                         * data modified by kmap_atomic()
                         */
-                       do_copy_page(buffer, src);
+                       safe_copy_page(buffer, s_page);
                        dst = kmap_atomic(pfn_to_page(dst_pfn), KM_USER0);
                        memcpy(dst, buffer, PAGE_SIZE);
                        kunmap_atomic(dst, KM_USER0);
                } else {
-                       dst = page_address(d_page);
-                       do_copy_page(dst, src);
+                       safe_copy_page(page_address(d_page), s_page);
                }
        }
 }
 #else
 #define page_is_saveable(zone, pfn)    saveable_page(pfn)
 
-static inline void
-copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
+static inline void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
 {
-       do_copy_page(page_address(pfn_to_page(dst_pfn)),
-                       page_address(pfn_to_page(src_pfn)));
+       safe_copy_page(page_address(pfn_to_page(dst_pfn)),
+                               pfn_to_page(src_pfn));
 }
 #endif /* CONFIG_HIGHMEM */
 
@@ -1005,11 +1020,12 @@ copy_data_pages(struct memory_bitmap *copy_bm, struct memory_bitmap *orig_bm)
        }
        memory_bm_position_reset(orig_bm);
        memory_bm_position_reset(copy_bm);
-       do {
+       for(;;) {
                pfn = memory_bm_next_pfn(orig_bm);
-               if (likely(pfn != BM_END_OF_MAP))
-                       copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
-       } while (pfn != BM_END_OF_MAP);
+               if (unlikely(pfn == BM_END_OF_MAP))
+                       break;
+               copy_data_page(memory_bm_next_pfn(copy_bm), pfn);
+       }
 }
 
 /* Total number of image pages */
@@ -1088,7 +1104,7 @@ static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
        }
 
        nr_pages += count_pages_for_highmem(nr_highmem);
-       pr_debug("swsusp: Normal pages needed: %u + %u + %u, available pages: %u\n",
+       pr_debug("PM: Normal pages needed: %u + %u + %u, available pages: %u\n",
                nr_pages, PAGES_FOR_IO, meta, free);
 
        return free > nr_pages + PAGES_FOR_IO + meta;
@@ -1201,27 +1217,27 @@ asmlinkage int swsusp_save(void)
 {
        unsigned int nr_pages, nr_highmem;
 
-       printk("swsusp: critical section: \n");
+       printk(KERN_INFO "PM: Creating hibernation image: \n");
 
-       drain_local_pages();
+       drain_local_pages(NULL);
        nr_pages = count_data_pages();
        nr_highmem = count_highmem_pages();
-       printk("swsusp: Need to copy %u pages\n", nr_pages + nr_highmem);
+       printk(KERN_INFO "PM: Need to copy %u pages\n", nr_pages + nr_highmem);
 
        if (!enough_free_mem(nr_pages, nr_highmem)) {
-               printk(KERN_ERR "swsusp: Not enough free memory\n");
+               printk(KERN_ERR "PM: Not enough free memory\n");
                return -ENOMEM;
        }
 
        if (swsusp_alloc(&orig_bm, &copy_bm, nr_pages, nr_highmem)) {
-               printk(KERN_ERR "swsusp: Memory allocation failed\n");
+               printk(KERN_ERR "PM: Memory allocation failed\n");
                return -ENOMEM;
        }
 
        /* During allocating of suspend pagedir, new cold pages may appear.
         * Kill them.
         */
-       drain_local_pages();
+       drain_local_pages(NULL);
        copy_data_pages(&copy_bm, &orig_bm);
 
        /*
@@ -1234,7 +1250,8 @@ asmlinkage int swsusp_save(void)
        nr_copy_pages = nr_pages;
        nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE);
 
-       printk("swsusp: critical section: done (%d pages copied)\n", nr_pages);
+       printk(KERN_INFO "PM: Hibernation image created (%d pages copied)\n",
+               nr_pages);
 
        return 0;
 }
@@ -1263,12 +1280,17 @@ static char *check_image_kernel(struct swsusp_info *info)
 }
 #endif /* CONFIG_ARCH_HIBERNATION_HEADER */
 
+unsigned long snapshot_get_image_size(void)
+{
+       return nr_copy_pages + nr_meta_pages + 1;
+}
+
 static int init_header(struct swsusp_info *info)
 {
        memset(info, 0, sizeof(struct swsusp_info));
        info->num_physpages = num_physpages;
        info->image_pages = nr_copy_pages;
-       info->pages = nr_copy_pages + nr_meta_pages + 1;
+       info->pages = snapshot_get_image_size();
        info->size = info->pages;
        info->size <<= PAGE_SHIFT;
        return init_header_complete(info);
@@ -1428,7 +1450,7 @@ static int check_header(struct swsusp_info *info)
        if (!reason && info->num_physpages != num_physpages)
                reason = "memory size";
        if (reason) {
-               printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason);
+               printk(KERN_ERR "PM: Image mismatch: %s\n", reason);
                return -EPERM;
        }
        return 0;