aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorYasuaki Ishimatsu <yasu.isimatu@gmail.com>2017-01-24 18:17:45 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-02-01 02:33:13 -0500
commit143a9ad4e68cc5c210e6e99e910d6b77cc8a9ec5 (patch)
tree744d19e2edc668ad7acefd1ab1e976a21bd066b7 /mm
parentda1fdb8456ac79533aa09ce61b99a84ac7ca57b9 (diff)
memory_hotplug: make zone_can_shift() return a boolean value
commit 8a1f780e7f28c7c1d640118242cf68d528c456cd upstream. online_{kernel|movable} is used to change the memory zone to ZONE_{NORMAL|MOVABLE} and online the memory. To check that memory zone can be changed, zone_can_shift() is used. Currently the function returns minus integer value, plus integer value and 0. When the function returns minus or plus integer value, it means that the memory zone can be changed to ZONE_{NORNAL|MOVABLE}. But when the function returns 0, there are two meanings. One of the meanings is that the memory zone does not need to be changed. For example, when memory is in ZONE_NORMAL and onlined by online_kernel the memory zone does not need to be changed. Another meaning is that the memory zone cannot be changed. When memory is in ZONE_NORMAL and onlined by online_movable, the memory zone may not be changed to ZONE_MOVALBE due to memory online limitation(see Documentation/memory-hotplug.txt). In this case, memory must not be onlined. The patch changes the return type of zone_can_shift() so that memory online operation fails when memory zone cannot be changed as follows: Before applying patch: # grep -A 35 "Node 2" /proc/zoneinfo Node 2, zone Normal <snip> node_scanned 0 spanned 8388608 present 7864320 managed 7864320 # echo online_movable > memory4097/state # grep -A 35 "Node 2" /proc/zoneinfo Node 2, zone Normal <snip> node_scanned 0 spanned 8388608 present 8388608 managed 8388608 online_movable operation succeeded. But memory is onlined as ZONE_NORMAL, not ZONE_MOVABLE. After applying patch: # grep -A 35 "Node 2" /proc/zoneinfo Node 2, zone Normal <snip> node_scanned 0 spanned 8388608 present 7864320 managed 7864320 # echo online_movable > memory4097/state bash: echo: write error: Invalid argument # grep -A 35 "Node 2" /proc/zoneinfo Node 2, zone Normal <snip> node_scanned 0 spanned 8388608 present 7864320 managed 7864320 online_movable operation failed because of failure of changing the memory zone from ZONE_NORMAL to ZONE_MOVABLE Fixes: df429ac03936 ("memory-hotplug: more general validation of zone during online") Link: http://lkml.kernel.org/r/2f9c3837-33d7-b6e5-59c0-6ca4372b2d84@gmail.com Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Reviewed-by: Reza Arbab <arbab@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/memory_hotplug.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index cad4b9125695..c3a8141ac788 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1033,36 +1033,39 @@ static void node_states_set_node(int node, struct memory_notify *arg)
1033 node_set_state(node, N_MEMORY); 1033 node_set_state(node, N_MEMORY);
1034} 1034}
1035 1035
1036int zone_can_shift(unsigned long pfn, unsigned long nr_pages, 1036bool zone_can_shift(unsigned long pfn, unsigned long nr_pages,
1037 enum zone_type target) 1037 enum zone_type target, int *zone_shift)
1038{ 1038{
1039 struct zone *zone = page_zone(pfn_to_page(pfn)); 1039 struct zone *zone = page_zone(pfn_to_page(pfn));
1040 enum zone_type idx = zone_idx(zone); 1040 enum zone_type idx = zone_idx(zone);
1041 int i; 1041 int i;
1042 1042
1043 *zone_shift = 0;
1044
1043 if (idx < target) { 1045 if (idx < target) {
1044 /* pages must be at end of current zone */ 1046 /* pages must be at end of current zone */
1045 if (pfn + nr_pages != zone_end_pfn(zone)) 1047 if (pfn + nr_pages != zone_end_pfn(zone))
1046 return 0; 1048 return false;
1047 1049
1048 /* no zones in use between current zone and target */ 1050 /* no zones in use between current zone and target */
1049 for (i = idx + 1; i < target; i++) 1051 for (i = idx + 1; i < target; i++)
1050 if (zone_is_initialized(zone - idx + i)) 1052 if (zone_is_initialized(zone - idx + i))
1051 return 0; 1053 return false;
1052 } 1054 }
1053 1055
1054 if (target < idx) { 1056 if (target < idx) {
1055 /* pages must be at beginning of current zone */ 1057 /* pages must be at beginning of current zone */
1056 if (pfn != zone->zone_start_pfn) 1058 if (pfn != zone->zone_start_pfn)
1057 return 0; 1059 return false;
1058 1060
1059 /* no zones in use between current zone and target */ 1061 /* no zones in use between current zone and target */
1060 for (i = target + 1; i < idx; i++) 1062 for (i = target + 1; i < idx; i++)
1061 if (zone_is_initialized(zone - idx + i)) 1063 if (zone_is_initialized(zone - idx + i))
1062 return 0; 1064 return false;
1063 } 1065 }
1064 1066
1065 return target - idx; 1067 *zone_shift = target - idx;
1068 return true;
1066} 1069}
1067 1070
1068/* Must be protected by mem_hotplug_begin() */ 1071/* Must be protected by mem_hotplug_begin() */
@@ -1089,10 +1092,13 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
1089 !can_online_high_movable(zone)) 1092 !can_online_high_movable(zone))
1090 return -EINVAL; 1093 return -EINVAL;
1091 1094
1092 if (online_type == MMOP_ONLINE_KERNEL) 1095 if (online_type == MMOP_ONLINE_KERNEL) {
1093 zone_shift = zone_can_shift(pfn, nr_pages, ZONE_NORMAL); 1096 if (!zone_can_shift(pfn, nr_pages, ZONE_NORMAL, &zone_shift))
1094 else if (online_type == MMOP_ONLINE_MOVABLE) 1097 return -EINVAL;
1095 zone_shift = zone_can_shift(pfn, nr_pages, ZONE_MOVABLE); 1098 } else if (online_type == MMOP_ONLINE_MOVABLE) {
1099 if (!zone_can_shift(pfn, nr_pages, ZONE_MOVABLE, &zone_shift))
1100 return -EINVAL;
1101 }
1096 1102
1097 zone = move_pfn_range(zone_shift, pfn, pfn + nr_pages); 1103 zone = move_pfn_range(zone_shift, pfn, pfn + nr_pages);
1098 if (!zone) 1104 if (!zone)