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.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;