memory hotplug: alloc page from other node in memory online
authorShaohua Li <shaohua.li@intel.com>
Tue, 22 Sep 2009 00:01:19 +0000 (17:01 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Sep 2009 14:17:26 +0000 (07:17 -0700)
To initialize hotadded node, some pages are allocated.  At that time, the
node hasn't memory, this makes the allocation always fail.  In such case,
let's allocate pages from other nodes.

Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Yakui Zhao <yakui.zhao@intel.com>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/page_cgroup.c
mm/sparse-vmemmap.c
mm/sparse.c

index f22b4ebbd8dc7a94680844ce214c5ff2fd2c1467..3d535d59482668012bd67c21b18cb59a909e1007 100644 (file)
@@ -116,10 +116,16 @@ static int __init_refok init_section_page_cgroup(unsigned long pfn)
                nid = page_to_nid(pfn_to_page(pfn));
                table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION;
                VM_BUG_ON(!slab_is_available());
-               base = kmalloc_node(table_size,
+               if (node_state(nid, N_HIGH_MEMORY)) {
+                       base = kmalloc_node(table_size,
                                GFP_KERNEL | __GFP_NOWARN, nid);
-               if (!base)
-                       base = vmalloc_node(table_size, nid);
+                       if (!base)
+                               base = vmalloc_node(table_size, nid);
+               } else {
+                       base = kmalloc(table_size, GFP_KERNEL | __GFP_NOWARN);
+                       if (!base)
+                               base = vmalloc(table_size);
+               }
        } else {
                /*
                 * We don't have to allocate page_cgroup again, but
index a13ea6401ae7428d967d15a3c5a0cf5472ee2240..d9714bdcb4a387199a5875d9745999942a3aa4f8 100644 (file)
@@ -48,8 +48,14 @@ void * __meminit vmemmap_alloc_block(unsigned long size, int node)
 {
        /* If the main allocator is up use that, fallback to bootmem. */
        if (slab_is_available()) {
-               struct page *page = alloc_pages_node(node,
+               struct page *page;
+
+               if (node_state(node, N_HIGH_MEMORY))
+                       page = alloc_pages_node(node,
                                GFP_KERNEL | __GFP_ZERO, get_order(size));
+               else
+                       page = alloc_pages(GFP_KERNEL | __GFP_ZERO,
+                               get_order(size));
                if (page)
                        return page_address(page);
                return NULL;
index da432d9f0ae825eb4e050ed8168c1600c6a793da..6ce4aab69e9974aea1838092efc26601ea7598b4 100644 (file)
@@ -62,9 +62,12 @@ static struct mem_section noinline __init_refok *sparse_index_alloc(int nid)
        unsigned long array_size = SECTIONS_PER_ROOT *
                                   sizeof(struct mem_section);
 
-       if (slab_is_available())
-               section = kmalloc_node(array_size, GFP_KERNEL, nid);
-       else
+       if (slab_is_available()) {
+               if (node_state(nid, N_HIGH_MEMORY))
+                       section = kmalloc_node(array_size, GFP_KERNEL, nid);
+               else
+                       section = kmalloc(array_size, GFP_KERNEL);
+       } else
                section = alloc_bootmem_node(NODE_DATA(nid), array_size);
 
        if (section)