[PATCH] sparsemem base: teach discontig about sparse ranges
authorDave Hansen <haveblue@us.ibm.com>
Thu, 23 Jun 2005 07:07:41 +0000 (00:07 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 23 Jun 2005 16:45:01 +0000 (09:45 -0700)
discontig.c has some assumptions that mem_map[]s inside of a node are
contiguous.  Teach it to make sure that each region that it's bringing online
is actually made up of valid ranges of ram.

Written-by: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/mm/discontig.c
arch/i386/mm/init.c
include/asm-i386/page.h

index dcc71f969b01089a0b09969f014588de606ff61c..088ca4722183a6339e8d1a65ea0837be5d8e3488 100644 (file)
@@ -216,6 +216,7 @@ static unsigned long calculate_numa_remap_pages(void)
 {
        int nid;
        unsigned long size, reserve_pages = 0;
+       unsigned long pfn;
 
        for_each_online_node(nid) {
                /*
@@ -234,6 +235,19 @@ static unsigned long calculate_numa_remap_pages(void)
                size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
                /* now the roundup is correct, convert to PAGE_SIZE pages */
                size = size * PTRS_PER_PTE;
+
+               /*
+                * Validate the region we are allocating only contains valid
+                * pages.
+                */
+               for (pfn = node_end_pfn[nid] - size;
+                    pfn < node_end_pfn[nid]; pfn++)
+                       if (!page_is_ram(pfn))
+                               break;
+
+               if (pfn != node_end_pfn[nid])
+                       size = 0;
+
                printk("Reserving %ld pages of KVA for lmem_map of node %d\n",
                                size, nid);
                node_remap_size[nid] = size;
index 8766c771bb45371ab1f67e94112616ba86521a9e..666ca79fb50a01cccdbf6a7b8f1ae0ccc066de78 100644 (file)
@@ -191,7 +191,7 @@ static inline int page_kills_ppro(unsigned long pagenr)
 
 extern int is_available_memory(efi_memory_desc_t *);
 
-static inline int page_is_ram(unsigned long pagenr)
+int page_is_ram(unsigned long pagenr)
 {
        int i;
        unsigned long addr, end;
index 41400d342d442c5d47f2abdf738b91d42bd2d80f..8f3dded01bffc61d234a31b0d712e48406368ab7 100644 (file)
@@ -120,6 +120,8 @@ static __inline__ int get_order(unsigned long size)
 
 extern int sysctl_legacy_va_layout;
 
+extern int page_is_ram(unsigned long pagenr);
+
 #endif /* __ASSEMBLY__ */
 
 #ifdef __ASSEMBLY__