aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorTang Chen <tangchen@cn.fujitsu.com>2013-02-22 19:33:39 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 20:50:14 -0500
commit6981ec31146cf19454c55c130625f6cee89aab95 (patch)
treec7f54f81d45c499103268ab95b88d0d617be9c59 /mm/page_alloc.c
parent34b71f1e04fcba578e719e675b4882eeeb2a1f6f (diff)
page_alloc: introduce zone_movable_limit[] to keep movable limit for nodes
Introduce a new array zone_movable_limit[] to store the ZONE_MOVABLE limit from movablemem_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. Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com> Signed-off-by: Liu Jiang <jiang.liu@huawei.com> Reviewed-by: Wen Congyang <wency@cn.fujitsu.com> Cc: Wu Jianguo <wujianguo@huawei.com> Reviewed-by: Lai Jiangshan <laijs@cn.fujitsu.com> Tested-by: Lin Feng <linfeng@cn.fujitsu.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Ingo Molnar <mingo@elte.hu> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c76
1 files changed, 74 insertions, 2 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index aa1cc5fe9904..0f267d9c73ff 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -210,6 +210,7 @@ static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
210static unsigned long __initdata required_kernelcore; 210static unsigned long __initdata required_kernelcore;
211static unsigned long __initdata required_movablecore; 211static unsigned long __initdata required_movablecore;
212static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES]; 212static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
213static unsigned long __meminitdata zone_movable_limit[MAX_NUMNODES];
213 214
214/* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */ 215/* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
215int movable_zone; 216int movable_zone;
@@ -4375,6 +4376,77 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid,
4375 return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn); 4376 return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
4376} 4377}
4377 4378
4379/**
4380 * sanitize_zone_movable_limit - Sanitize the zone_movable_limit array.
4381 *
4382 * zone_movable_limit is initialized as 0. This function will try to get
4383 * the first ZONE_MOVABLE pfn of each node from movablemem_map, and
4384 * assigne them to zone_movable_limit.
4385 * zone_movable_limit[nid] == 0 means no limit for the node.
4386 *
4387 * Note: Each range is represented as [start_pfn, end_pfn)
4388 */
4389static void __meminit sanitize_zone_movable_limit(void)
4390{
4391 int map_pos = 0, i, nid;
4392 unsigned long start_pfn, end_pfn;
4393
4394 if (!movablemem_map.nr_map)
4395 return;
4396
4397 /* Iterate all ranges from minimum to maximum */
4398 for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
4399 /*
4400 * If we have found lowest pfn of ZONE_MOVABLE of the node
4401 * specified by user, just go on to check next range.
4402 */
4403 if (zone_movable_limit[nid])
4404 continue;
4405
4406#ifdef CONFIG_ZONE_DMA
4407 /* Skip DMA memory. */
4408 if (start_pfn < arch_zone_highest_possible_pfn[ZONE_DMA])
4409 start_pfn = arch_zone_highest_possible_pfn[ZONE_DMA];
4410#endif
4411
4412#ifdef CONFIG_ZONE_DMA32
4413 /* Skip DMA32 memory. */
4414 if (start_pfn < arch_zone_highest_possible_pfn[ZONE_DMA32])
4415 start_pfn = arch_zone_highest_possible_pfn[ZONE_DMA32];
4416#endif
4417
4418#ifdef CONFIG_HIGHMEM
4419 /* Skip lowmem if ZONE_MOVABLE is highmem. */
4420 if (zone_movable_is_highmem() &&
4421 start_pfn < arch_zone_lowest_possible_pfn[ZONE_HIGHMEM])
4422 start_pfn = arch_zone_lowest_possible_pfn[ZONE_HIGHMEM];
4423#endif
4424
4425 if (start_pfn >= end_pfn)
4426 continue;
4427
4428 while (map_pos < movablemem_map.nr_map) {
4429 if (end_pfn <= movablemem_map.map[map_pos].start_pfn)
4430 break;
4431
4432 if (start_pfn >= movablemem_map.map[map_pos].end_pfn) {
4433 map_pos++;
4434 continue;
4435 }
4436
4437 /*
4438 * The start_pfn of ZONE_MOVABLE is either the minimum
4439 * pfn specified by movablemem_map, or 0, which means
4440 * the node has no ZONE_MOVABLE.
4441 */
4442 zone_movable_limit[nid] = max(start_pfn,
4443 movablemem_map.map[map_pos].start_pfn);
4444
4445 break;
4446 }
4447 }
4448}
4449
4378#else /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ 4450#else /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
4379static inline unsigned long __meminit zone_spanned_pages_in_node(int nid, 4451static inline unsigned long __meminit zone_spanned_pages_in_node(int nid,
4380 unsigned long zone_type, 4452 unsigned long zone_type,
@@ -4392,7 +4464,6 @@ static inline unsigned long __meminit zone_absent_pages_in_node(int nid,
4392 4464
4393 return zholes_size[zone_type]; 4465 return zholes_size[zone_type];
4394} 4466}
4395
4396#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ 4467#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
4397 4468
4398static void __meminit calculate_node_totalpages(struct pglist_data *pgdat, 4469static void __meminit calculate_node_totalpages(struct pglist_data *pgdat,
@@ -4839,7 +4910,6 @@ static void __init find_zone_movable_pfns_for_nodes(void)
4839 goto out; 4910 goto out;
4840 4911
4841 /* usable_startpfn is the lowest possible pfn ZONE_MOVABLE can be at */ 4912 /* usable_startpfn is the lowest possible pfn ZONE_MOVABLE can be at */
4842 find_usable_zone_for_movable();
4843 usable_startpfn = arch_zone_lowest_possible_pfn[movable_zone]; 4913 usable_startpfn = arch_zone_lowest_possible_pfn[movable_zone];
4844 4914
4845restart: 4915restart:
@@ -4998,6 +5068,8 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
4998 5068
4999 /* Find the PFNs that ZONE_MOVABLE begins at in each node */ 5069 /* Find the PFNs that ZONE_MOVABLE begins at in each node */
5000 memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn)); 5070 memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn));
5071 find_usable_zone_for_movable();
5072 sanitize_zone_movable_limit();
5001 find_zone_movable_pfns_for_nodes(); 5073 find_zone_movable_pfns_for_nodes();
5002 5074
5003 /* Print out the zone ranges */ 5075 /* Print out the zone ranges */