powerpc: Fix bootmem reservation on uninitialized node

careful_allocation() was calling into the bootmem allocator for
nodes which had not been fully initialized and caused a previous
bug: http://patchwork.ozlabs.org/patch/10528/ So, I merged a
few broken out loops in do_init_bootmem() to fix it. That changed
the code ordering.

I think this bug is triggered by having reserved areas for a node
which are spanned by another node's contents. In the
mark_reserved_regions_for_nid() code, we attempt to reserve the
area for a node before we have allocated the NODE_DATA() for that
nid. We do this since I reordered that loop. I suck.

This is causing crashes at bootup on some systems, as reported
by Jon Tollefson.

This may only present on some systems that have 16GB pages
reserved. But, it can probably happen on any system that is
trying to reserve large swaths of memory that happen to span other
nodes' contents.

This commit ensures that we do not touch bootmem for any node which
has not been initialized, and also removes a compile warning about
an unused variable.

Signed-off-by: Dave Hansen <dave@linux.vnet.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by

Dave Hansen and committed by
Paul Mackerras
a4c74ddd 48f797de

+11 -5
+11 -5
arch/powerpc/mm/numa.c
··· 901 if (end_pfn > node_ar.end_pfn) 902 reserve_size = (node_ar.end_pfn << PAGE_SHIFT) 903 - (start_pfn << PAGE_SHIFT); 904 - dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, 905 - reserve_size, node_ar.nid); 906 - reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, 907 - reserve_size, BOOTMEM_DEFAULT); 908 /* 909 * if reserved region is contained in the active region 910 * then done. ··· 936 void __init do_init_bootmem(void) 937 { 938 int nid; 939 - unsigned int i; 940 941 min_low_pfn = 0; 942 max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
··· 901 if (end_pfn > node_ar.end_pfn) 902 reserve_size = (node_ar.end_pfn << PAGE_SHIFT) 903 - (start_pfn << PAGE_SHIFT); 904 + /* 905 + * Only worry about *this* node, others may not 906 + * yet have valid NODE_DATA(). 907 + */ 908 + if (node_ar.nid == nid) { 909 + dbg("reserve_bootmem %lx %lx nid=%d\n", 910 + physbase, reserve_size, node_ar.nid); 911 + reserve_bootmem_node(NODE_DATA(node_ar.nid), 912 + physbase, reserve_size, 913 + BOOTMEM_DEFAULT); 914 + } 915 /* 916 * if reserved region is contained in the active region 917 * then done. ··· 929 void __init do_init_bootmem(void) 930 { 931 int nid; 932 933 min_low_pfn = 0; 934 max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;