aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 16:11:15 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 16:11:15 -0500
commitf6e858a00af788bab0fd4c0b7f5cd788000edc18 (patch)
treef9403ca3671be9821dbf83e726e61dbe75fbca6b /mm/memory_hotplug.c
parent193c0d682525987db59ac3a24531a77e4947aa95 (diff)
parent98870901cce098bbe94d90d2c41d8d1fa8d94392 (diff)
Merge branch 'akpm' (Andrew's patch-bomb)
Merge misc VM changes from Andrew Morton: "The rest of most-of-MM. The other MM bits await a slab merge. This patch includes the addition of a huge zero_page. Not a performance boost but it an save large amounts of physical memory in some situations. Also a bunch of Fujitsu engineers are working on memory hotplug. Which, as it turns out, was badly broken. About half of their patches are included here; the remainder are 3.8 material." However, this merge disables CONFIG_MOVABLE_NODE, which was totally broken. We don't add new features with "default y", nor do we add Kconfig questions that are incomprehensible to most people without any help text. Does the feature even make sense without compaction or memory hotplug? * akpm: (54 commits) mm/bootmem.c: remove unused wrapper function reserve_bootmem_generic() mm/memory.c: remove unused code from do_wp_page() asm-generic, mm: pgtable: consolidate zero page helpers mm/hugetlb.c: fix warning on freeing hwpoisoned hugepage hwpoison, hugetlbfs: fix RSS-counter warning hwpoison, hugetlbfs: fix "bad pmd" warning in unmapping hwpoisoned hugepage mm: protect against concurrent vma expansion memcg: do not check for mm in __mem_cgroup_count_vm_event tmpfs: support SEEK_DATA and SEEK_HOLE (reprise) mm: provide more accurate estimation of pages occupied by memmap fs/buffer.c: remove redundant initialization in alloc_page_buffers() fs/buffer.c: do not inline exported function writeback: fix a typo in comment mm: introduce new field "managed_pages" to struct zone mm, oom: remove statically defined arch functions of same name mm, oom: remove redundant sleep in pagefault oom handler mm, oom: cleanup pagefault oom handler memory_hotplug: allow online/offline memory to result movable node numa: add CONFIG_MOVABLE_NODE for movable-dedicated node mm, memcg: avoid unnecessary function call when memcg is disabled ...
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r--mm/memory_hotplug.c113
1 files changed, 98 insertions, 15 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index c3e66ae411fd..518baa896e83 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -106,6 +106,7 @@ static void get_page_bootmem(unsigned long info, struct page *page,
106void __ref put_page_bootmem(struct page *page) 106void __ref put_page_bootmem(struct page *page)
107{ 107{
108 unsigned long type; 108 unsigned long type;
109 static DEFINE_MUTEX(ppb_lock);
109 110
110 type = (unsigned long) page->lru.next; 111 type = (unsigned long) page->lru.next;
111 BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE || 112 BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
@@ -115,7 +116,14 @@ void __ref put_page_bootmem(struct page *page)
115 ClearPagePrivate(page); 116 ClearPagePrivate(page);
116 set_page_private(page, 0); 117 set_page_private(page, 0);
117 INIT_LIST_HEAD(&page->lru); 118 INIT_LIST_HEAD(&page->lru);
119
120 /*
121 * Please refer to comment for __free_pages_bootmem()
122 * for why we serialize here.
123 */
124 mutex_lock(&ppb_lock);
118 __free_pages_bootmem(page, 0); 125 __free_pages_bootmem(page, 0);
126 mutex_unlock(&ppb_lock);
119 } 127 }
120 128
121} 129}
@@ -581,11 +589,19 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
581 return 0; 589 return 0;
582} 590}
583 591
592#ifdef CONFIG_MOVABLE_NODE
593/* when CONFIG_MOVABLE_NODE, we allow online node don't have normal memory */
594static bool can_online_high_movable(struct zone *zone)
595{
596 return true;
597}
598#else /* #ifdef CONFIG_MOVABLE_NODE */
584/* ensure every online node has NORMAL memory */ 599/* ensure every online node has NORMAL memory */
585static bool can_online_high_movable(struct zone *zone) 600static bool can_online_high_movable(struct zone *zone)
586{ 601{
587 return node_state(zone_to_nid(zone), N_NORMAL_MEMORY); 602 return node_state(zone_to_nid(zone), N_NORMAL_MEMORY);
588} 603}
604#endif /* #ifdef CONFIG_MOVABLE_NODE */
589 605
590/* check which state of node_states will be changed when online memory */ 606/* check which state of node_states will be changed when online memory */
591static void node_states_check_changes_online(unsigned long nr_pages, 607static void node_states_check_changes_online(unsigned long nr_pages,
@@ -595,13 +611,15 @@ static void node_states_check_changes_online(unsigned long nr_pages,
595 enum zone_type zone_last = ZONE_NORMAL; 611 enum zone_type zone_last = ZONE_NORMAL;
596 612
597 /* 613 /*
598 * If we have HIGHMEM, node_states[N_NORMAL_MEMORY] contains nodes 614 * If we have HIGHMEM or movable node, node_states[N_NORMAL_MEMORY]
599 * which have 0...ZONE_NORMAL, set zone_last to ZONE_NORMAL. 615 * contains nodes which have zones of 0...ZONE_NORMAL,
616 * set zone_last to ZONE_NORMAL.
600 * 617 *
601 * If we don't have HIGHMEM, node_states[N_NORMAL_MEMORY] contains nodes 618 * If we don't have HIGHMEM nor movable node,
602 * which have 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE. 619 * node_states[N_NORMAL_MEMORY] contains nodes which have zones of
620 * 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE.
603 */ 621 */
604 if (N_HIGH_MEMORY == N_NORMAL_MEMORY) 622 if (N_MEMORY == N_NORMAL_MEMORY)
605 zone_last = ZONE_MOVABLE; 623 zone_last = ZONE_MOVABLE;
606 624
607 /* 625 /*
@@ -615,12 +633,34 @@ static void node_states_check_changes_online(unsigned long nr_pages,
615 else 633 else
616 arg->status_change_nid_normal = -1; 634 arg->status_change_nid_normal = -1;
617 635
636#ifdef CONFIG_HIGHMEM
637 /*
638 * If we have movable node, node_states[N_HIGH_MEMORY]
639 * contains nodes which have zones of 0...ZONE_HIGHMEM,
640 * set zone_last to ZONE_HIGHMEM.
641 *
642 * If we don't have movable node, node_states[N_NORMAL_MEMORY]
643 * contains nodes which have zones of 0...ZONE_MOVABLE,
644 * set zone_last to ZONE_MOVABLE.
645 */
646 zone_last = ZONE_HIGHMEM;
647 if (N_MEMORY == N_HIGH_MEMORY)
648 zone_last = ZONE_MOVABLE;
649
650 if (zone_idx(zone) <= zone_last && !node_state(nid, N_HIGH_MEMORY))
651 arg->status_change_nid_high = nid;
652 else
653 arg->status_change_nid_high = -1;
654#else
655 arg->status_change_nid_high = arg->status_change_nid_normal;
656#endif
657
618 /* 658 /*
619 * if the node don't have memory befor online, we will need to 659 * if the node don't have memory befor online, we will need to
620 * set the node to node_states[N_HIGH_MEMORY] after the memory 660 * set the node to node_states[N_MEMORY] after the memory
621 * is online. 661 * is online.
622 */ 662 */
623 if (!node_state(nid, N_HIGH_MEMORY)) 663 if (!node_state(nid, N_MEMORY))
624 arg->status_change_nid = nid; 664 arg->status_change_nid = nid;
625 else 665 else
626 arg->status_change_nid = -1; 666 arg->status_change_nid = -1;
@@ -631,7 +671,10 @@ static void node_states_set_node(int node, struct memory_notify *arg)
631 if (arg->status_change_nid_normal >= 0) 671 if (arg->status_change_nid_normal >= 0)
632 node_set_state(node, N_NORMAL_MEMORY); 672 node_set_state(node, N_NORMAL_MEMORY);
633 673
634 node_set_state(node, N_HIGH_MEMORY); 674 if (arg->status_change_nid_high >= 0)
675 node_set_state(node, N_HIGH_MEMORY);
676
677 node_set_state(node, N_MEMORY);
635} 678}
636 679
637 680
@@ -713,6 +756,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
713 return ret; 756 return ret;
714 } 757 }
715 758
759 zone->managed_pages += onlined_pages;
716 zone->present_pages += onlined_pages; 760 zone->present_pages += onlined_pages;
717 zone->zone_pgdat->node_present_pages += onlined_pages; 761 zone->zone_pgdat->node_present_pages += onlined_pages;
718 if (onlined_pages) { 762 if (onlined_pages) {
@@ -1066,6 +1110,13 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
1066 return offlined; 1110 return offlined;
1067} 1111}
1068 1112
1113#ifdef CONFIG_MOVABLE_NODE
1114/* when CONFIG_MOVABLE_NODE, we allow online node don't have normal memory */
1115static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
1116{
1117 return true;
1118}
1119#else /* #ifdef CONFIG_MOVABLE_NODE */
1069/* ensure the node has NORMAL memory if it is still online */ 1120/* ensure the node has NORMAL memory if it is still online */
1070static bool can_offline_normal(struct zone *zone, unsigned long nr_pages) 1121static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
1071{ 1122{
@@ -1089,6 +1140,7 @@ static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
1089 */ 1140 */
1090 return present_pages == 0; 1141 return present_pages == 0;
1091} 1142}
1143#endif /* #ifdef CONFIG_MOVABLE_NODE */
1092 1144
1093/* check which state of node_states will be changed when offline memory */ 1145/* check which state of node_states will be changed when offline memory */
1094static void node_states_check_changes_offline(unsigned long nr_pages, 1146static void node_states_check_changes_offline(unsigned long nr_pages,
@@ -1099,13 +1151,15 @@ static void node_states_check_changes_offline(unsigned long nr_pages,
1099 enum zone_type zt, zone_last = ZONE_NORMAL; 1151 enum zone_type zt, zone_last = ZONE_NORMAL;
1100 1152
1101 /* 1153 /*
1102 * If we have HIGHMEM, node_states[N_NORMAL_MEMORY] contains nodes 1154 * If we have HIGHMEM or movable node, node_states[N_NORMAL_MEMORY]
1103 * which have 0...ZONE_NORMAL, set zone_last to ZONE_NORMAL. 1155 * contains nodes which have zones of 0...ZONE_NORMAL,
1156 * set zone_last to ZONE_NORMAL.
1104 * 1157 *
1105 * If we don't have HIGHMEM, node_states[N_NORMAL_MEMORY] contains nodes 1158 * If we don't have HIGHMEM nor movable node,
1106 * which have 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE. 1159 * node_states[N_NORMAL_MEMORY] contains nodes which have zones of
1160 * 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE.
1107 */ 1161 */
1108 if (N_HIGH_MEMORY == N_NORMAL_MEMORY) 1162 if (N_MEMORY == N_NORMAL_MEMORY)
1109 zone_last = ZONE_MOVABLE; 1163 zone_last = ZONE_MOVABLE;
1110 1164
1111 /* 1165 /*
@@ -1122,6 +1176,30 @@ static void node_states_check_changes_offline(unsigned long nr_pages,
1122 else 1176 else
1123 arg->status_change_nid_normal = -1; 1177 arg->status_change_nid_normal = -1;
1124 1178
1179#ifdef CONFIG_HIGHMEM
1180 /*
1181 * If we have movable node, node_states[N_HIGH_MEMORY]
1182 * contains nodes which have zones of 0...ZONE_HIGHMEM,
1183 * set zone_last to ZONE_HIGHMEM.
1184 *
1185 * If we don't have movable node, node_states[N_NORMAL_MEMORY]
1186 * contains nodes which have zones of 0...ZONE_MOVABLE,
1187 * set zone_last to ZONE_MOVABLE.
1188 */
1189 zone_last = ZONE_HIGHMEM;
1190 if (N_MEMORY == N_HIGH_MEMORY)
1191 zone_last = ZONE_MOVABLE;
1192
1193 for (; zt <= zone_last; zt++)
1194 present_pages += pgdat->node_zones[zt].present_pages;
1195 if (zone_idx(zone) <= zone_last && nr_pages >= present_pages)
1196 arg->status_change_nid_high = zone_to_nid(zone);
1197 else
1198 arg->status_change_nid_high = -1;
1199#else
1200 arg->status_change_nid_high = arg->status_change_nid_normal;
1201#endif
1202
1125 /* 1203 /*
1126 * node_states[N_HIGH_MEMORY] contains nodes which have 0...ZONE_MOVABLE 1204 * node_states[N_HIGH_MEMORY] contains nodes which have 0...ZONE_MOVABLE
1127 */ 1205 */
@@ -1146,9 +1224,13 @@ static void node_states_clear_node(int node, struct memory_notify *arg)
1146 if (arg->status_change_nid_normal >= 0) 1224 if (arg->status_change_nid_normal >= 0)
1147 node_clear_state(node, N_NORMAL_MEMORY); 1225 node_clear_state(node, N_NORMAL_MEMORY);
1148 1226
1149 if ((N_HIGH_MEMORY != N_NORMAL_MEMORY) && 1227 if ((N_MEMORY != N_NORMAL_MEMORY) &&
1150 (arg->status_change_nid >= 0)) 1228 (arg->status_change_nid_high >= 0))
1151 node_clear_state(node, N_HIGH_MEMORY); 1229 node_clear_state(node, N_HIGH_MEMORY);
1230
1231 if ((N_MEMORY != N_HIGH_MEMORY) &&
1232 (arg->status_change_nid >= 0))
1233 node_clear_state(node, N_MEMORY);
1152} 1234}
1153 1235
1154static int __ref __offline_pages(unsigned long start_pfn, 1236static int __ref __offline_pages(unsigned long start_pfn,
@@ -1248,6 +1330,7 @@ repeat:
1248 /* reset pagetype flags and makes migrate type to be MOVABLE */ 1330 /* reset pagetype flags and makes migrate type to be MOVABLE */
1249 undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE); 1331 undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
1250 /* removal success */ 1332 /* removal success */
1333 zone->managed_pages -= offlined_pages;
1251 zone->present_pages -= offlined_pages; 1334 zone->present_pages -= offlined_pages;
1252 zone->zone_pgdat->node_present_pages -= offlined_pages; 1335 zone->zone_pgdat->node_present_pages -= offlined_pages;
1253 totalram_pages -= offlined_pages; 1336 totalram_pages -= offlined_pages;