From bd5cfb8977fbb49d9350f7c81cf1516142e35a6a Mon Sep 17 00:00:00 2001 From: Xishi Qiu Date: Mon, 13 Oct 2014 15:55:07 -0700 Subject: [PATCH] arch/x86/mm/numa.c: fix boot failure when all nodes are hotpluggable If all the nodes are marked hotpluggable, alloc node data will fail. Because __next_mem_range_rev() will skip the hotpluggable memory regions. numa_clear_kernel_node_hotplug() is called after alloc node data. numa_init() ... ret = init_func(); // this will mark hotpluggable flag from SRAT ... memblock_set_bottom_up(false); ... ret = numa_register_memblks(&numa_meminfo); // this will alloc node data(pglist_data) ... numa_clear_kernel_node_hotplug(); // in case all the nodes are hotpluggable ... numa_register_memblks() setup_node_data() memblock_find_in_range_node() __memblock_find_range_top_down() for_each_mem_range_rev() __next_mem_range_rev() This patch moves numa_clear_kernel_node_hotplug() into numa_register_memblks(), clear kernel node hotpluggable flag before alloc node data, then alloc node data won't fail even all the nodes are hotpluggable. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Xishi Qiu Cc: Dave Jones Cc: Tang Chen Cc: Gu Zheng Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86/mm/numa.c | 89 +++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index a32b706c401a..4e1e5709fe17 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -478,6 +478,42 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi) return true; } +static void __init numa_clear_kernel_node_hotplug(void) +{ + int i, nid; + nodemask_t numa_kernel_nodes = NODE_MASK_NONE; + unsigned long start, end; + struct memblock_region *r; + + /* + * At this time, all memory regions reserved by memblock are + * used by the kernel. Set the nid in memblock.reserved will + * mark out all the nodes the kernel resides in. + */ + for (i = 0; i < numa_meminfo.nr_blks; i++) { + struct numa_memblk *mb = &numa_meminfo.blk[i]; + + memblock_set_node(mb->start, mb->end - mb->start, + &memblock.reserved, mb->nid); + } + + /* Mark all kernel nodes. */ + for_each_memblock(reserved, r) + node_set(r->nid, numa_kernel_nodes); + + /* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */ + for (i = 0; i < numa_meminfo.nr_blks; i++) { + nid = numa_meminfo.blk[i].nid; + if (!node_isset(nid, numa_kernel_nodes)) + continue; + + start = numa_meminfo.blk[i].start; + end = numa_meminfo.blk[i].end; + + memblock_clear_hotplug(start, end - start); + } +} + static int __init numa_register_memblks(struct numa_meminfo *mi) { unsigned long uninitialized_var(pfn_align); @@ -495,6 +531,15 @@ static int __init numa_register_memblks(struct numa_meminfo *mi) &memblock.memory, mb->nid); } + /* + * At very early time, the kernel have to use some memory such as + * loading the kernel image. We cannot prevent this anyway. So any + * node the kernel resides in should be un-hotpluggable. + * + * And when we come here, alloc node data won't fail. + */ + numa_clear_kernel_node_hotplug(); + /* * If sections array is gonna be used for pfn -> nid mapping, check * whether its granularity is fine enough. @@ -554,41 +599,6 @@ static void __init numa_init_array(void) } } -static void __init numa_clear_kernel_node_hotplug(void) -{ - int i, nid; - nodemask_t numa_kernel_nodes = NODE_MASK_NONE; - unsigned long start, end; - struct memblock_region *r; - - /* - * At this time, all memory regions reserved by memblock are - * used by the kernel. Set the nid in memblock.reserved will - * mark out all the nodes the kernel resides in. - */ - for (i = 0; i < numa_meminfo.nr_blks; i++) { - struct numa_memblk *mb = &numa_meminfo.blk[i]; - memblock_set_node(mb->start, mb->end - mb->start, - &memblock.reserved, mb->nid); - } - - /* Mark all kernel nodes. */ - for_each_memblock(reserved, r) - node_set(r->nid, numa_kernel_nodes); - - /* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */ - for (i = 0; i < numa_meminfo.nr_blks; i++) { - nid = numa_meminfo.blk[i].nid; - if (!node_isset(nid, numa_kernel_nodes)) - continue; - - start = numa_meminfo.blk[i].start; - end = numa_meminfo.blk[i].end; - - memblock_clear_hotplug(start, end - start); - } -} - static int __init numa_init(int (*init_func)(void)) { int i; @@ -643,15 +653,6 @@ static int __init numa_init(int (*init_func)(void)) } numa_init_array(); - /* - * At very early time, the kernel have to use some memory such as - * loading the kernel image. We cannot prevent this anyway. So any - * node the kernel resides in should be un-hotpluggable. - * - * And when we come here, numa_init() won't fail. - */ - numa_clear_kernel_node_hotplug(); - return 0; } -- 2.34.1