aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
authorAndi Kleen <andi@firstfloor.org>2009-11-17 17:06:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-11-17 20:40:33 -0500
commit6ad696d2cf535772dff659298ec7e7260e344595 (patch)
tree2f4d4d088a7bc8203473dcb96a1d1f0591f3de94 /mm/memory_hotplug.c
parent9398180097e359646d46083c3e079a54e20bee82 (diff)
mm: allow memory hotplug and hibernation in the same kernel
Allow memory hotplug and hibernation in the same kernel Memory hotplug and hibernation were exclusive in Kconfig. This is obviously a problem for distribution kernels who want to support both in the same image. After some discussions with Rafael and others the only problem is with parallel memory hotadd or removal while a hibernation operation is in process. It was also working for s390 before. This patch removes the Kconfig level exclusion, and simply makes the memory add / remove functions grab the pm_mutex to exclude against hibernation. Fixes a regression - old kernels didn't exclude memory hotadd and hibernation. Signed-off-by: Andi Kleen <ak@linux.intel.com> Cc: Gerald Schaefer <gerald.schaefer@de.ibm.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Yasunori Goto <y-goto@jp.fujitsu.com> Acked-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r--mm/memory_hotplug.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 380aef45c2cf..2047465cd27c 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -26,6 +26,7 @@
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>
29 30
30#include <asm/tlbflush.h> 31#include <asm/tlbflush.h>
31 32
@@ -485,14 +486,18 @@ int __ref add_memory(int nid, u64 start, u64 size)
485 struct resource *res; 486 struct resource *res;
486 int ret; 487 int ret;
487 488
489 lock_system_sleep();
490
488 res = register_memory_resource(start, size); 491 res = register_memory_resource(start, size);
492 ret = -EEXIST;
489 if (!res) 493 if (!res)
490 return -EEXIST; 494 goto out;
491 495
492 if (!node_online(nid)) { 496 if (!node_online(nid)) {
493 pgdat = hotadd_new_pgdat(nid, start); 497 pgdat = hotadd_new_pgdat(nid, start);
498 ret = -ENOMEM;
494 if (!pgdat) 499 if (!pgdat)
495 return -ENOMEM; 500 goto out;
496 new_pgdat = 1; 501 new_pgdat = 1;
497 } 502 }
498 503
@@ -515,7 +520,8 @@ int __ref add_memory(int nid, u64 start, u64 size)
515 BUG_ON(ret); 520 BUG_ON(ret);
516 } 521 }
517 522
518 return ret; 523 goto out;
524
519error: 525error:
520 /* rollback pgdat allocation and others */ 526 /* rollback pgdat allocation and others */
521 if (new_pgdat) 527 if (new_pgdat)
@@ -523,6 +529,8 @@ error:
523 if (res) 529 if (res)
524 release_memory_resource(res); 530 release_memory_resource(res);
525 531
532out:
533 unlock_system_sleep();
526 return ret; 534 return ret;
527} 535}
528EXPORT_SYMBOL_GPL(add_memory); 536EXPORT_SYMBOL_GPL(add_memory);
@@ -759,6 +767,8 @@ int offline_pages(unsigned long start_pfn,
759 if (!test_pages_in_a_zone(start_pfn, end_pfn)) 767 if (!test_pages_in_a_zone(start_pfn, end_pfn))
760 return -EINVAL; 768 return -EINVAL;
761 769
770 lock_system_sleep();
771
762 zone = page_zone(pfn_to_page(start_pfn)); 772 zone = page_zone(pfn_to_page(start_pfn));
763 node = zone_to_nid(zone); 773 node = zone_to_nid(zone);
764 nr_pages = end_pfn - start_pfn; 774 nr_pages = end_pfn - start_pfn;
@@ -766,7 +776,7 @@ int offline_pages(unsigned long start_pfn,
766 /* set above range as isolated */ 776 /* set above range as isolated */
767 ret = start_isolate_page_range(start_pfn, end_pfn); 777 ret = start_isolate_page_range(start_pfn, end_pfn);
768 if (ret) 778 if (ret)
769 return ret; 779 goto out;
770 780
771 arg.start_pfn = start_pfn; 781 arg.start_pfn = start_pfn;
772 arg.nr_pages = nr_pages; 782 arg.nr_pages = nr_pages;
@@ -844,6 +854,7 @@ repeat:
844 writeback_set_ratelimit(); 854 writeback_set_ratelimit();
845 855
846 memory_notify(MEM_OFFLINE, &arg); 856 memory_notify(MEM_OFFLINE, &arg);
857 unlock_system_sleep();
847 return 0; 858 return 0;
848 859
849failed_removal: 860failed_removal:
@@ -853,6 +864,8 @@ failed_removal:
853 /* pushback to free area */ 864 /* pushback to free area */
854 undo_isolate_page_range(start_pfn, end_pfn); 865 undo_isolate_page_range(start_pfn, end_pfn);
855 866
867out:
868 unlock_system_sleep();
856 return ret; 869 return ret;
857} 870}
858 871