diff options
Diffstat (limited to 'mm/memory_hotplug.c')
| -rw-r--r-- | mm/memory_hotplug.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 85eb4d342ac5..089cc97aed3c 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
| @@ -389,6 +389,11 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) | |||
| 389 | int nid; | 389 | int nid; |
| 390 | int ret; | 390 | int ret; |
| 391 | struct memory_notify arg; | 391 | struct memory_notify arg; |
| 392 | /* | ||
| 393 | * mutex to protect zone->pageset when it's still shared | ||
| 394 | * in onlined_pages() | ||
| 395 | */ | ||
| 396 | static DEFINE_MUTEX(zone_pageset_mutex); | ||
| 392 | 397 | ||
| 393 | arg.start_pfn = pfn; | 398 | arg.start_pfn = pfn; |
| 394 | arg.nr_pages = nr_pages; | 399 | arg.nr_pages = nr_pages; |
| @@ -415,12 +420,14 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) | |||
| 415 | * This means the page allocator ignores this zone. | 420 | * This means the page allocator ignores this zone. |
| 416 | * So, zonelist must be updated after online. | 421 | * So, zonelist must be updated after online. |
| 417 | */ | 422 | */ |
| 423 | mutex_lock(&zone_pageset_mutex); | ||
| 418 | if (!populated_zone(zone)) | 424 | if (!populated_zone(zone)) |
| 419 | need_zonelists_rebuild = 1; | 425 | need_zonelists_rebuild = 1; |
| 420 | 426 | ||
| 421 | ret = walk_system_ram_range(pfn, nr_pages, &onlined_pages, | 427 | ret = walk_system_ram_range(pfn, nr_pages, &onlined_pages, |
| 422 | online_pages_range); | 428 | online_pages_range); |
| 423 | if (ret) { | 429 | if (ret) { |
| 430 | mutex_unlock(&zone_pageset_mutex); | ||
| 424 | printk(KERN_DEBUG "online_pages %lx at %lx failed\n", | 431 | printk(KERN_DEBUG "online_pages %lx at %lx failed\n", |
| 425 | nr_pages, pfn); | 432 | nr_pages, pfn); |
| 426 | memory_notify(MEM_CANCEL_ONLINE, &arg); | 433 | memory_notify(MEM_CANCEL_ONLINE, &arg); |
| @@ -429,8 +436,12 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) | |||
| 429 | 436 | ||
| 430 | zone->present_pages += onlined_pages; | 437 | zone->present_pages += onlined_pages; |
| 431 | zone->zone_pgdat->node_present_pages += onlined_pages; | 438 | zone->zone_pgdat->node_present_pages += onlined_pages; |
| 439 | if (need_zonelists_rebuild) | ||
| 440 | build_all_zonelists(zone); | ||
| 441 | else | ||
| 442 | zone_pcp_update(zone); | ||
| 432 | 443 | ||
| 433 | zone_pcp_update(zone); | 444 | mutex_unlock(&zone_pageset_mutex); |
| 434 | setup_per_zone_wmarks(); | 445 | setup_per_zone_wmarks(); |
| 435 | calculate_zone_inactive_ratio(zone); | 446 | calculate_zone_inactive_ratio(zone); |
| 436 | if (onlined_pages) { | 447 | if (onlined_pages) { |
| @@ -438,10 +449,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) | |||
| 438 | node_set_state(zone_to_nid(zone), N_HIGH_MEMORY); | 449 | node_set_state(zone_to_nid(zone), N_HIGH_MEMORY); |
| 439 | } | 450 | } |
| 440 | 451 | ||
| 441 | if (need_zonelists_rebuild) | 452 | vm_total_pages = nr_free_pagecache_pages(); |
| 442 | build_all_zonelists(); | ||
| 443 | else | ||
| 444 | vm_total_pages = nr_free_pagecache_pages(); | ||
| 445 | 453 | ||
| 446 | writeback_set_ratelimit(); | 454 | writeback_set_ratelimit(); |
| 447 | 455 | ||
