Patch "memory_hotplug: make zone_can_shift() return a boolean value" has been added to the 4.9-stable tree
Subsystems (4)
This is a note to let you know that I've just added the patch titled
memory_hotplug: make zone_can_shift() return a boolean value
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
memory_hotplug-make-zone_can_shift-return-a-boolean-value.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
8a1f780e7f28c7c1d640118242cf68d528c456cdMon Sep 17 00:00:00 2001
From: Yasuaki Ishimatsu <[email protected]>
Date: Tue, 24 Jan 2017 15:17:45 -0800
Subject: memory_hotplug: make zone_can_shift() return a boolean value
From: Yasuaki Ishimatsu <[email protected]>
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
--- drivers/base/memory.c | 4 ++-- include/linux/memory_hotplug.h | 4 ++-- mm/memory_hotplug.c | 28 +++++++++++++++++----------- 3 files changed, 21 insertions(+), 15 deletions(-)
drivers/base/memory.c +2 -2
@@ -410,14 +410,14 @@ static ssize_t show_valid_zones(struct dsprintf (buf,"%s" , zone->name);/* MMOP_ONLINE_KERNEL */ - zone_shift =zone_can_shift (start_pfn, nr_pages,ZONE_NORMAL ); +zone_can_shift (start_pfn, nr_pages,ZONE_NORMAL , &zone_shift);if (zone_shift) {strcat (buf," " );strcat (buf, (zone + zone_shift)->name); }/* MMOP_ONLINE_MOVABLE */ - zone_shift =zone_can_shift (start_pfn, nr_pages,ZONE_MOVABLE ); +zone_can_shift (start_pfn, nr_pages,ZONE_MOVABLE , &zone_shift);if (zone_shift) {strcat (buf," " );strcat (buf, (zone + zone_shift)->name);
include/linux/memory_hotplug.h +2 -2
@@ -284,7 +284,7 @@ extern void sparse_remove_one_section(st unsigned long map_offset);extern struct page *sparse_decode_mem_map (unsigned long coded_mem_map,unsigned long pnum); -extern int zone_can_shift (unsigned long pfn,unsigned long nr_pages, -enum zone_type target); +extern bool zone_can_shift (unsigned long pfn,unsigned long nr_pages, +enum zone_type target,int *zone_shift);#endif /* __LINUX_MEMORY_HOTPLUG_H */
mm/memory_hotplug.c +17 -11
@@ -1033,36 +1033,39 @@ static void node_states_set_node(int nodnode_set_state (node,N_MEMORY ); } -int zone_can_shift (unsigned long pfn,unsigned long nr_pages, -enum zone_type target) +bool zone_can_shift (unsigned long pfn,unsigned long nr_pages, +enum zone_type target,int *zone_shift) {struct zone *zone =page_zone (pfn_to_page (pfn));enum zone_type idx =zone_idx (zone);int i; + *zone_shift =0 ; +if (idx < target) {/* pages must be at end of current zone */ if (pfn + nr_pages !=zone_end_pfn (zone)) -return 0 ; +return false;/* no zones in use between current zone and target */ for (i = idx +1 ; i < target; i++)if (zone_is_initialized (zone - idx + i)) -return 0 ; +return false; }if (target < idx) {/* pages must be at beginning of current zone */ if (pfn != zone->zone_start_pfn) -return 0 ; +return false;/* no zones in use between current zone and target */ for (i = target +1 ; i < idx; i++)if (zone_is_initialized (zone - idx + i)) -return 0 ; +return false; } -return target - idx; + *zone_shift = target - idx; +return true; }/* Must be protected by mem_hotplug_begin() */
@@ -1089,10 +1092,13 @@ int __ref online_pages(unsigned long pfn !can_online_high_movable(zone))return -EINVAL ; -if (online_type ==MMOP_ONLINE_KERNEL ) - zone_shift =zone_can_shift (pfn, nr_pages,ZONE_NORMAL ); -else if (online_type ==MMOP_ONLINE_MOVABLE ) - zone_shift =zone_can_shift (pfn, nr_pages,ZONE_MOVABLE ); +if (online_type ==MMOP_ONLINE_KERNEL ) { +if (!zone_can_shift (pfn, nr_pages,ZONE_NORMAL , &zone_shift)) +return -EINVAL ; + }else if (online_type ==MMOP_ONLINE_MOVABLE ) { +if (!zone_can_shift (pfn, nr_pages,ZONE_MOVABLE , &zone_shift)) +return -EINVAL ; + } zone =move_pfn_range (zone_shift, pfn, pfn + nr_pages);if (!zone)
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/memory_hotplug-make-zone_can_shift-return-a-boolean-value.patch