Re: [PATCH v3 3/5] page_alloc: Introduce zone_movable_limit[] to keep movable limit for nodes
From: Jiang Liu <hidden>
Date: 2012-12-12 00:50:16
Also in:
lkml
On 2012-12-11 19:28, Simon Jeons wrote:
On Tue, 2012-12-11 at 11:32 +0800, Tang Chen wrote:quoted
On 12/11/2012 11:07 AM, Jianguo Wu wrote:quoted
On 2012/12/11 10:33, Tang Chen wrote:quoted
This patch introduces a new array zone_movable_limit[] to store the ZONE_MOVABLE limit from movablecore_map boot option for all nodes. The function sanitize_zone_movable_limit() will find out to which node the ranges in movable_map.map[] belongs, and calculates the low boundary of ZONE_MOVABLE for each node.What's the difference between zone_movable_limit[nid] and zone_movable_pfn[nid]?
zone_movable_limit[] is a temporary storage for zone_moveable_pfn[]. It's used to handle a special case if user specifies both movablecore_map and movablecore/kernelcore on the kernel command line.
quoted
quoted
quoted
Signed-off-by: Tang Chen<redacted> Signed-off-by: Jiang Liu<redacted> Reviewed-by: Wen Congyang<redacted> Reviewed-by: Lai Jiangshan<redacted> Tested-by: Lin Feng<redacted> --- mm/page_alloc.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 77 insertions(+), 0 deletions(-)diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 1c91d16..4853619 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c@@ -206,6 +206,7 @@ static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES]; static unsigned long __initdata required_kernelcore; static unsigned long __initdata required_movablecore; static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES]; +static unsigned long __meminitdata zone_movable_limit[MAX_NUMNODES]; /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */ int movable_zone;@@ -4340,6 +4341,77 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid, return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn); } +/** + * sanitize_zone_movable_limit - Sanitize the zone_movable_limit array. + * + * zone_movable_limit is initialized as 0. This function will try to get + * the first ZONE_MOVABLE pfn of each node from movablecore_map, and + * assigne them to zone_movable_limit. + * zone_movable_limit[nid] == 0 means no limit for the node. + * + * Note: Each range is represented as [start_pfn, end_pfn) + */ +static void __meminit sanitize_zone_movable_limit(void) +{ + int map_pos = 0, i, nid; + unsigned long start_pfn, end_pfn; + + if (!movablecore_map.nr_map) + return; + + /* Iterate all ranges from minimum to maximum */ + for_each_mem_pfn_range(i, MAX_NUMNODES,&start_pfn,&end_pfn,&nid) { + /* + * If we have found lowest pfn of ZONE_MOVABLE of the node + * specified by user, just go on to check next range. + */ + if (zone_movable_limit[nid]) + continue; + +#ifdef CONFIG_ZONE_DMA + /* Skip DMA memory. */ + if (start_pfn< arch_zone_highest_possible_pfn[ZONE_DMA]) + start_pfn = arch_zone_highest_possible_pfn[ZONE_DMA]; +#endif + +#ifdef CONFIG_ZONE_DMA32 + /* Skip DMA32 memory. */ + if (start_pfn< arch_zone_highest_possible_pfn[ZONE_DMA32]) + start_pfn = arch_zone_highest_possible_pfn[ZONE_DMA32]; +#endif + +#ifdef CONFIG_HIGHMEM + /* Skip lowmem if ZONE_MOVABLE is highmem. */ + if (zone_movable_is_highmem()&&Hi Tang, I think zone_movable_is_highmem() is not work correctly here. sanitize_zone_movable_limit zone_movable_is_highmem<--using movable_zone here find_zone_movable_pfns_for_nodes find_usable_zone_for_movable<--movable_zone is specified here I think Jiang Liu's patch works fine for highmem, please refer to: http://marc.info/?l=linux-mm&m=135476085816087&w=2Hi Wu, Yes, I forgot movable_zone think. Thanks for reminding me. :) But Liu's patch you just mentioned, I didn't use it because I don't think we should skip kernelcore when movablecore_map is specified. If these 2 options are not conflict, we should satisfy them both. :) Of course, I also think Liu's suggestion is wonderful. But I think we need more discussion on it. :) I'll fix it soon. Thanks. :)quoted
Thanks, Jianguo Wuquoted
+ start_pfn< arch_zone_lowest_possible_pfn[ZONE_HIGHMEM]) + start_pfn = arch_zone_lowest_possible_pfn[ZONE_HIGHMEM]; +#endif + + if (start_pfn>= end_pfn) + continue; + + while (map_pos< movablecore_map.nr_map) { + if (end_pfn<= movablecore_map.map[map_pos].start_pfn) + break; + + if (start_pfn>= movablecore_map.map[map_pos].end_pfn) { + map_pos++; + continue; + } + + /* + * The start_pfn of ZONE_MOVABLE is either the minimum + * pfn specified by movablecore_map, or 0, which means + * the node has no ZONE_MOVABLE. + */ + zone_movable_limit[nid] = max(start_pfn, + movablecore_map.map[map_pos].start_pfn); + + break; + } + } +} + #else /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ static inline unsigned long __meminit zone_spanned_pages_in_node(int nid, unsigned long zone_type,@@ -4358,6 +4430,10 @@ static inline unsigned long __meminit zone_absent_pages_in_node(int nid, return zholes_size[zone_type]; } +static void __meminit sanitize_zone_movable_limit(void) +{ +} + #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ static void __meminit calculate_node_totalpages(struct pglist_data *pgdat,@@ -4923,6 +4999,7 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn) /* Find the PFNs that ZONE_MOVABLE begins at in each node */ memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn)); + sanitize_zone_movable_limit(); find_zone_movable_pfns_for_nodes(); /* Print out the zone ranges */-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>.
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>