diff options
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r-- | mm/memory_hotplug.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index be211a582930..a4cfcdc00455 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -415,12 +415,14 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) | |||
415 | * This means the page allocator ignores this zone. | 415 | * This means the page allocator ignores this zone. |
416 | * So, zonelist must be updated after online. | 416 | * So, zonelist must be updated after online. |
417 | */ | 417 | */ |
418 | mutex_lock(&zonelists_mutex); | ||
418 | if (!populated_zone(zone)) | 419 | if (!populated_zone(zone)) |
419 | need_zonelists_rebuild = 1; | 420 | need_zonelists_rebuild = 1; |
420 | 421 | ||
421 | ret = walk_system_ram_range(pfn, nr_pages, &onlined_pages, | 422 | ret = walk_system_ram_range(pfn, nr_pages, &onlined_pages, |
422 | online_pages_range); | 423 | online_pages_range); |
423 | if (ret) { | 424 | if (ret) { |
425 | mutex_unlock(&zonelists_mutex); | ||
424 | printk(KERN_DEBUG "online_pages %lx at %lx failed\n", | 426 | printk(KERN_DEBUG "online_pages %lx at %lx failed\n", |
425 | nr_pages, pfn); | 427 | nr_pages, pfn); |
426 | memory_notify(MEM_CANCEL_ONLINE, &arg); | 428 | memory_notify(MEM_CANCEL_ONLINE, &arg); |
@@ -429,8 +431,12 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) | |||
429 | 431 | ||
430 | zone->present_pages += onlined_pages; | 432 | zone->present_pages += onlined_pages; |
431 | zone->zone_pgdat->node_present_pages += onlined_pages; | 433 | zone->zone_pgdat->node_present_pages += onlined_pages; |
434 | if (need_zonelists_rebuild) | ||
435 | build_all_zonelists(zone); | ||
436 | else | ||
437 | zone_pcp_update(zone); | ||
432 | 438 | ||
433 | zone_pcp_update(zone); | 439 | mutex_unlock(&zonelists_mutex); |
434 | setup_per_zone_wmarks(); | 440 | setup_per_zone_wmarks(); |
435 | calculate_zone_inactive_ratio(zone); | 441 | calculate_zone_inactive_ratio(zone); |
436 | if (onlined_pages) { | 442 | if (onlined_pages) { |
@@ -438,10 +444,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) | |||
438 | node_set_state(zone_to_nid(zone), N_HIGH_MEMORY); | 444 | node_set_state(zone_to_nid(zone), N_HIGH_MEMORY); |
439 | } | 445 | } |
440 | 446 | ||
441 | if (need_zonelists_rebuild) | 447 | vm_total_pages = nr_free_pagecache_pages(); |
442 | build_all_zonelists(); | ||
443 | else | ||
444 | vm_total_pages = nr_free_pagecache_pages(); | ||
445 | 448 | ||
446 | writeback_set_ratelimit(); | 449 | writeback_set_ratelimit(); |
447 | 450 | ||
@@ -482,6 +485,29 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat) | |||
482 | } | 485 | } |
483 | 486 | ||
484 | 487 | ||
488 | /* | ||
489 | * called by cpu_up() to online a node without onlined memory. | ||
490 | */ | ||
491 | int mem_online_node(int nid) | ||
492 | { | ||
493 | pg_data_t *pgdat; | ||
494 | int ret; | ||
495 | |||
496 | lock_system_sleep(); | ||
497 | pgdat = hotadd_new_pgdat(nid, 0); | ||
498 | if (pgdat) { | ||
499 | ret = -ENOMEM; | ||
500 | goto out; | ||
501 | } | ||
502 | node_set_online(nid); | ||
503 | ret = register_one_node(nid); | ||
504 | BUG_ON(ret); | ||
505 | |||
506 | out: | ||
507 | unlock_system_sleep(); | ||
508 | return ret; | ||
509 | } | ||
510 | |||
485 | /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */ | 511 | /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */ |
486 | int __ref add_memory(int nid, u64 start, u64 size) | 512 | int __ref add_memory(int nid, u64 start, u64 size) |
487 | { | 513 | { |