diff options
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r-- | mm/memory_hotplug.c | 68 |
1 files changed, 65 insertions, 3 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index c46887b5a11e..6e7d8b21dbfa 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -34,6 +34,17 @@ | |||
34 | 34 | ||
35 | #include "internal.h" | 35 | #include "internal.h" |
36 | 36 | ||
37 | /* | ||
38 | * online_page_callback contains pointer to current page onlining function. | ||
39 | * Initially it is generic_online_page(). If it is required it could be | ||
40 | * changed by calling set_online_page_callback() for callback registration | ||
41 | * and restore_online_page_callback() for generic callback restore. | ||
42 | */ | ||
43 | |||
44 | static void generic_online_page(struct page *page); | ||
45 | |||
46 | static online_page_callback_t online_page_callback = generic_online_page; | ||
47 | |||
37 | DEFINE_MUTEX(mem_hotplug_mutex); | 48 | DEFINE_MUTEX(mem_hotplug_mutex); |
38 | 49 | ||
39 | void lock_memory_hotplug(void) | 50 | void lock_memory_hotplug(void) |
@@ -361,23 +372,74 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn, | |||
361 | } | 372 | } |
362 | EXPORT_SYMBOL_GPL(__remove_pages); | 373 | EXPORT_SYMBOL_GPL(__remove_pages); |
363 | 374 | ||
364 | void online_page(struct page *page) | 375 | int set_online_page_callback(online_page_callback_t callback) |
376 | { | ||
377 | int rc = -EINVAL; | ||
378 | |||
379 | lock_memory_hotplug(); | ||
380 | |||
381 | if (online_page_callback == generic_online_page) { | ||
382 | online_page_callback = callback; | ||
383 | rc = 0; | ||
384 | } | ||
385 | |||
386 | unlock_memory_hotplug(); | ||
387 | |||
388 | return rc; | ||
389 | } | ||
390 | EXPORT_SYMBOL_GPL(set_online_page_callback); | ||
391 | |||
392 | int restore_online_page_callback(online_page_callback_t callback) | ||
393 | { | ||
394 | int rc = -EINVAL; | ||
395 | |||
396 | lock_memory_hotplug(); | ||
397 | |||
398 | if (online_page_callback == callback) { | ||
399 | online_page_callback = generic_online_page; | ||
400 | rc = 0; | ||
401 | } | ||
402 | |||
403 | unlock_memory_hotplug(); | ||
404 | |||
405 | return rc; | ||
406 | } | ||
407 | EXPORT_SYMBOL_GPL(restore_online_page_callback); | ||
408 | |||
409 | void __online_page_set_limits(struct page *page) | ||
365 | { | 410 | { |
366 | unsigned long pfn = page_to_pfn(page); | 411 | unsigned long pfn = page_to_pfn(page); |
367 | 412 | ||
368 | totalram_pages++; | ||
369 | if (pfn >= num_physpages) | 413 | if (pfn >= num_physpages) |
370 | num_physpages = pfn + 1; | 414 | num_physpages = pfn + 1; |
415 | } | ||
416 | EXPORT_SYMBOL_GPL(__online_page_set_limits); | ||
417 | |||
418 | void __online_page_increment_counters(struct page *page) | ||
419 | { | ||
420 | totalram_pages++; | ||
371 | 421 | ||
372 | #ifdef CONFIG_HIGHMEM | 422 | #ifdef CONFIG_HIGHMEM |
373 | if (PageHighMem(page)) | 423 | if (PageHighMem(page)) |
374 | totalhigh_pages++; | 424 | totalhigh_pages++; |
375 | #endif | 425 | #endif |
426 | } | ||
427 | EXPORT_SYMBOL_GPL(__online_page_increment_counters); | ||
376 | 428 | ||
429 | void __online_page_free(struct page *page) | ||
430 | { | ||
377 | ClearPageReserved(page); | 431 | ClearPageReserved(page); |
378 | init_page_count(page); | 432 | init_page_count(page); |
379 | __free_page(page); | 433 | __free_page(page); |
380 | } | 434 | } |
435 | EXPORT_SYMBOL_GPL(__online_page_free); | ||
436 | |||
437 | static void generic_online_page(struct page *page) | ||
438 | { | ||
439 | __online_page_set_limits(page); | ||
440 | __online_page_increment_counters(page); | ||
441 | __online_page_free(page); | ||
442 | } | ||
381 | 443 | ||
382 | static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages, | 444 | static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages, |
383 | void *arg) | 445 | void *arg) |
@@ -388,7 +450,7 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages, | |||
388 | if (PageReserved(pfn_to_page(start_pfn))) | 450 | if (PageReserved(pfn_to_page(start_pfn))) |
389 | for (i = 0; i < nr_pages; i++) { | 451 | for (i = 0; i < nr_pages; i++) { |
390 | page = pfn_to_page(start_pfn + i); | 452 | page = pfn_to_page(start_pfn + i); |
391 | online_page(page); | 453 | (*online_page_callback)(page); |
392 | onlined_pages++; | 454 | onlined_pages++; |
393 | } | 455 | } |
394 | *(unsigned long *)arg = onlined_pages; | 456 | *(unsigned long *)arg = onlined_pages; |