aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r--mm/memory_hotplug.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 821dee596377..030ce8a5bb0e 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -26,6 +26,8 @@
26#include <linux/migrate.h> 26#include <linux/migrate.h>
27#include <linux/page-isolation.h> 27#include <linux/page-isolation.h>
28#include <linux/pfn.h> 28#include <linux/pfn.h>
29#include <linux/suspend.h>
30#include <linux/mm_inline.h>
29 31
30#include <asm/tlbflush.h> 32#include <asm/tlbflush.h>
31 33
@@ -70,7 +72,9 @@ static void get_page_bootmem(unsigned long info, struct page *page, int type)
70 atomic_inc(&page->_count); 72 atomic_inc(&page->_count);
71} 73}
72 74
73void put_page_bootmem(struct page *page) 75/* reference to __meminit __free_pages_bootmem is valid
76 * so use __ref to tell modpost not to generate a warning */
77void __ref put_page_bootmem(struct page *page)
74{ 78{
75 int type; 79 int type;
76 80
@@ -447,7 +451,8 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
447} 451}
448#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ 452#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
449 453
450static pg_data_t *hotadd_new_pgdat(int nid, u64 start) 454/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
455static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
451{ 456{
452 struct pglist_data *pgdat; 457 struct pglist_data *pgdat;
453 unsigned long zones_size[MAX_NR_ZONES] = {0}; 458 unsigned long zones_size[MAX_NR_ZONES] = {0};
@@ -484,14 +489,18 @@ int __ref add_memory(int nid, u64 start, u64 size)
484 struct resource *res; 489 struct resource *res;
485 int ret; 490 int ret;
486 491
492 lock_system_sleep();
493
487 res = register_memory_resource(start, size); 494 res = register_memory_resource(start, size);
495 ret = -EEXIST;
488 if (!res) 496 if (!res)
489 return -EEXIST; 497 goto out;
490 498
491 if (!node_online(nid)) { 499 if (!node_online(nid)) {
492 pgdat = hotadd_new_pgdat(nid, start); 500 pgdat = hotadd_new_pgdat(nid, start);
501 ret = -ENOMEM;
493 if (!pgdat) 502 if (!pgdat)
494 return -ENOMEM; 503 goto out;
495 new_pgdat = 1; 504 new_pgdat = 1;
496 } 505 }
497 506
@@ -514,7 +523,8 @@ int __ref add_memory(int nid, u64 start, u64 size)
514 BUG_ON(ret); 523 BUG_ON(ret);
515 } 524 }
516 525
517 return ret; 526 goto out;
527
518error: 528error:
519 /* rollback pgdat allocation and others */ 529 /* rollback pgdat allocation and others */
520 if (new_pgdat) 530 if (new_pgdat)
@@ -522,6 +532,8 @@ error:
522 if (res) 532 if (res)
523 release_memory_resource(res); 533 release_memory_resource(res);
524 534
535out:
536 unlock_system_sleep();
525 return ret; 537 return ret;
526} 538}
527EXPORT_SYMBOL_GPL(add_memory); 539EXPORT_SYMBOL_GPL(add_memory);
@@ -663,6 +675,9 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
663 if (!ret) { /* Success */ 675 if (!ret) { /* Success */
664 list_add_tail(&page->lru, &source); 676 list_add_tail(&page->lru, &source);
665 move_pages--; 677 move_pages--;
678 inc_zone_page_state(page, NR_ISOLATED_ANON +
679 page_is_file_cache(page));
680
666 } else { 681 } else {
667 /* Becasue we don't have big zone->lock. we should 682 /* Becasue we don't have big zone->lock. we should
668 check this again here. */ 683 check this again here. */
@@ -685,7 +700,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
685 if (list_empty(&source)) 700 if (list_empty(&source))
686 goto out; 701 goto out;
687 /* this function returns # of failed pages */ 702 /* this function returns # of failed pages */
688 ret = migrate_pages(&source, hotremove_migrate_alloc, 0); 703 ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1);
689 704
690out: 705out:
691 return ret; 706 return ret;
@@ -738,7 +753,7 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
738 return offlined; 753 return offlined;
739} 754}
740 755
741int offline_pages(unsigned long start_pfn, 756static int offline_pages(unsigned long start_pfn,
742 unsigned long end_pfn, unsigned long timeout) 757 unsigned long end_pfn, unsigned long timeout)
743{ 758{
744 unsigned long pfn, nr_pages, expire; 759 unsigned long pfn, nr_pages, expire;
@@ -758,6 +773,8 @@ int offline_pages(unsigned long start_pfn,
758 if (!test_pages_in_a_zone(start_pfn, end_pfn)) 773 if (!test_pages_in_a_zone(start_pfn, end_pfn))
759 return -EINVAL; 774 return -EINVAL;
760 775
776 lock_system_sleep();
777
761 zone = page_zone(pfn_to_page(start_pfn)); 778 zone = page_zone(pfn_to_page(start_pfn));
762 node = zone_to_nid(zone); 779 node = zone_to_nid(zone);
763 nr_pages = end_pfn - start_pfn; 780 nr_pages = end_pfn - start_pfn;
@@ -765,7 +782,7 @@ int offline_pages(unsigned long start_pfn,
765 /* set above range as isolated */ 782 /* set above range as isolated */
766 ret = start_isolate_page_range(start_pfn, end_pfn); 783 ret = start_isolate_page_range(start_pfn, end_pfn);
767 if (ret) 784 if (ret)
768 return ret; 785 goto out;
769 786
770 arg.start_pfn = start_pfn; 787 arg.start_pfn = start_pfn;
771 arg.nr_pages = nr_pages; 788 arg.nr_pages = nr_pages;
@@ -838,11 +855,16 @@ repeat:
838 855
839 setup_per_zone_wmarks(); 856 setup_per_zone_wmarks();
840 calculate_zone_inactive_ratio(zone); 857 calculate_zone_inactive_ratio(zone);
858 if (!node_present_pages(node)) {
859 node_clear_state(node, N_HIGH_MEMORY);
860 kswapd_stop(node);
861 }
841 862
842 vm_total_pages = nr_free_pagecache_pages(); 863 vm_total_pages = nr_free_pagecache_pages();
843 writeback_set_ratelimit(); 864 writeback_set_ratelimit();
844 865
845 memory_notify(MEM_OFFLINE, &arg); 866 memory_notify(MEM_OFFLINE, &arg);
867 unlock_system_sleep();
846 return 0; 868 return 0;
847 869
848failed_removal: 870failed_removal:
@@ -852,6 +874,8 @@ failed_removal:
852 /* pushback to free area */ 874 /* pushback to free area */
853 undo_isolate_page_range(start_pfn, end_pfn); 875 undo_isolate_page_range(start_pfn, end_pfn);
854 876
877out:
878 unlock_system_sleep();
855 return ret; 879 return ret;
856} 880}
857 881