aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorminskey guo <chaohong_guo@linux.intel.com>2010-05-24 17:32:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-25 11:07:00 -0400
commitcf23422b9d76215316855253da491d4c9f294372 (patch)
tree5663d2519d83d830d24dffdf2571d58d3e55d3f6
parent8b25c6d2231b978ccce9c401e771932bde79aa9f (diff)
cpu/mem hotplug: enable CPUs online before local memory online
Enable users to online CPUs even if the CPUs belongs to a numa node which doesn't have onlined local memory. The zonlists(pg_data_t.node_zonelists[]) of a numa node are created either in system boot/init period, or at the time of local memory online. For a numa node without onlined local memory, its zonelists are not initialized at present. As a result, any memory allocation operations executed by CPUs within this node will fail. In fact, an out-of-memory error is triggered when attempt to online CPUs before memory comes to online. This patch tries to create zonelists for such numa nodes, so that the memory allocation for this node can be fallback'ed to other nodes. [akpm@linux-foundation.org: remove unneeded export] [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: minskey guo<chaohong.guo@intel.com> Cc: Minchan Kim <minchan.kim@gmail.com> Cc: Yasunori Goto <y-goto@jp.fujitsu.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Christoph Lameter <cl@linux-foundation.org> Cc: Tejun Heo <tj@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/memory_hotplug.h1
-rw-r--r--kernel/cpu.c25
-rw-r--r--mm/memory_hotplug.c23
3 files changed, 49 insertions, 0 deletions
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 35b07b773e6c..864035fb8f8a 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -202,6 +202,7 @@ static inline int is_mem_section_removable(unsigned long pfn,
202} 202}
203#endif /* CONFIG_MEMORY_HOTREMOVE */ 203#endif /* CONFIG_MEMORY_HOTREMOVE */
204 204
205extern int mem_online_node(int nid);
205extern int add_memory(int nid, u64 start, u64 size); 206extern int add_memory(int nid, u64 start, u64 size);
206extern int arch_add_memory(int nid, u64 start, u64 size); 207extern int arch_add_memory(int nid, u64 start, u64 size);
207extern int remove_memory(u64 start, u64 size); 208extern int remove_memory(u64 start, u64 size);
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 545777574779..a3fbcc0a0abc 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -326,6 +326,12 @@ out_notify:
326int __cpuinit cpu_up(unsigned int cpu) 326int __cpuinit cpu_up(unsigned int cpu)
327{ 327{
328 int err = 0; 328 int err = 0;
329
330#ifdef CONFIG_MEMORY_HOTPLUG
331 int nid;
332 pg_data_t *pgdat;
333#endif
334
329 if (!cpu_possible(cpu)) { 335 if (!cpu_possible(cpu)) {
330 printk(KERN_ERR "can't online cpu %d because it is not " 336 printk(KERN_ERR "can't online cpu %d because it is not "
331 "configured as may-hotadd at boot time\n", cpu); 337 "configured as may-hotadd at boot time\n", cpu);
@@ -336,6 +342,25 @@ int __cpuinit cpu_up(unsigned int cpu)
336 return -EINVAL; 342 return -EINVAL;
337 } 343 }
338 344
345#ifdef CONFIG_MEMORY_HOTPLUG
346 nid = cpu_to_node(cpu);
347 if (!node_online(nid)) {
348 err = mem_online_node(nid);
349 if (err)
350 return err;
351 }
352
353 pgdat = NODE_DATA(nid);
354 if (!pgdat) {
355 printk(KERN_ERR
356 "Can't online cpu %d due to NULL pgdat\n", cpu);
357 return -ENOMEM;
358 }
359
360 if (pgdat->node_zonelists->_zonerefs->zone == NULL)
361 build_all_zonelists();
362#endif
363
339 cpu_maps_update_begin(); 364 cpu_maps_update_begin();
340 365
341 if (cpu_hotplug_disabled) { 366 if (cpu_hotplug_disabled) {
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index be211a582930..85eb4d342ac5 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -482,6 +482,29 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
482} 482}
483 483
484 484
485/*
486 * called by cpu_up() to online a node without onlined memory.
487 */
488int mem_online_node(int nid)
489{
490 pg_data_t *pgdat;
491 int ret;
492
493 lock_system_sleep();
494 pgdat = hotadd_new_pgdat(nid, 0);
495 if (pgdat) {
496 ret = -ENOMEM;
497 goto out;
498 }
499 node_set_online(nid);
500 ret = register_one_node(nid);
501 BUG_ON(ret);
502
503out:
504 unlock_system_sleep();
505 return ret;
506}
507
485/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */ 508/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
486int __ref add_memory(int nid, u64 start, u64 size) 509int __ref add_memory(int nid, u64 start, u64 size)
487{ 510{