Skip to content

Commit 66f86c3

Browse files
yishimatsuhnaz
authored andcommitted
memory_hotplug: make zone_can_shift() return a boolean value
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 is 2 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: df429ac ("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>
1 parent 1377300 commit 66f86c3

File tree

3 files changed

+21
-15
lines changed

3 files changed

+21
-15
lines changed

drivers/base/memory.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,14 +408,14 @@ static ssize_t show_valid_zones(struct device *dev,
408408
sprintf(buf, "%s", zone->name);
409409

410410
/* MMOP_ONLINE_KERNEL */
411-
zone_shift = zone_can_shift(start_pfn, nr_pages, ZONE_NORMAL);
411+
zone_can_shift(start_pfn, nr_pages, ZONE_NORMAL, &zone_shift);
412412
if (zone_shift) {
413413
strcat(buf, " ");
414414
strcat(buf, (zone + zone_shift)->name);
415415
}
416416

417417
/* MMOP_ONLINE_MOVABLE */
418-
zone_shift = zone_can_shift(start_pfn, nr_pages, ZONE_MOVABLE);
418+
zone_can_shift(start_pfn, nr_pages, ZONE_MOVABLE, &zone_shift);
419419
if (zone_shift) {
420420
strcat(buf, " ");
421421
strcat(buf, (zone + zone_shift)->name);

include/linux/memory_hotplug.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms,
284284
unsigned long map_offset);
285285
extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
286286
unsigned long pnum);
287-
extern int zone_can_shift(unsigned long pfn, unsigned long nr_pages,
288-
enum zone_type target);
287+
extern bool zone_can_shift(unsigned long pfn, unsigned long nr_pages,
288+
enum zone_type target, int *zone_shift);
289289

290290
#endif /* __LINUX_MEMORY_HOTPLUG_H */

mm/memory_hotplug.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,36 +1033,39 @@ static void node_states_set_node(int node, struct memory_notify *arg)
10331033
node_set_state(node, N_MEMORY);
10341034
}
10351035

1036-
int zone_can_shift(unsigned long pfn, unsigned long nr_pages,
1037-
enum zone_type target)
1036+
bool zone_can_shift(unsigned long pfn, unsigned long nr_pages,
1037+
enum zone_type target, int *zone_shift)
10381038
{
10391039
struct zone *zone = page_zone(pfn_to_page(pfn));
10401040
enum zone_type idx = zone_idx(zone);
10411041
int i;
10421042

1043+
*zone_shift = 0;
1044+
10431045
if (idx < target) {
10441046
/* pages must be at end of current zone */
10451047
if (pfn + nr_pages != zone_end_pfn(zone))
1046-
return 0;
1048+
return false;
10471049

10481050
/* no zones in use between current zone and target */
10491051
for (i = idx + 1; i < target; i++)
10501052
if (zone_is_initialized(zone - idx + i))
1051-
return 0;
1053+
return false;
10521054
}
10531055

10541056
if (target < idx) {
10551057
/* pages must be at beginning of current zone */
10561058
if (pfn != zone->zone_start_pfn)
1057-
return 0;
1059+
return false;
10581060

10591061
/* no zones in use between current zone and target */
10601062
for (i = target + 1; i < idx; i++)
10611063
if (zone_is_initialized(zone - idx + i))
1062-
return 0;
1064+
return false;
10631065
}
10641066

1065-
return target - idx;
1067+
*zone_shift = target - idx;
1068+
return true;
10661069
}
10671070

10681071
/* 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
10891092
!can_online_high_movable(zone))
10901093
return -EINVAL;
10911094

1092-
if (online_type == MMOP_ONLINE_KERNEL)
1093-
zone_shift = zone_can_shift(pfn, nr_pages, ZONE_NORMAL);
1094-
else if (online_type == MMOP_ONLINE_MOVABLE)
1095-
zone_shift = zone_can_shift(pfn, nr_pages, ZONE_MOVABLE);
1095+
if (online_type == MMOP_ONLINE_KERNEL) {
1096+
if (!zone_can_shift(pfn, nr_pages, ZONE_NORMAL, &zone_shift))
1097+
return -EINVAL;
1098+
} else if (online_type == MMOP_ONLINE_MOVABLE) {
1099+
if (!zone_can_shift(pfn, nr_pages, ZONE_MOVABLE, &zone_shift))
1100+
return -EINVAL;
1101+
}
10961102

10971103
zone = move_pfn_range(zone_shift, pfn, pfn + nr_pages);
10981104
if (!zone)

0 commit comments

Comments
 (0)