diff options
author | Tejun Heo <tj@kernel.org> | 2011-12-08 13:22:09 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2011-12-08 13:22:09 -0500 |
commit | 0ee332c1451869963626bf9cac88f165a90990e1 (patch) | |
tree | a40e6c9c6cfe39ecbca37a08019be3c9e56a4a9b /mm/page_alloc.c | |
parent | a2bf79e7dcc97b4e9654f273453f9264f49e41ff (diff) |
memblock: Kill early_node_map[]
Now all ARCH_POPULATES_NODE_MAP archs select HAVE_MEBLOCK_NODE_MAP -
there's no user of early_node_map[] left. Kill early_node_map[] and
replace ARCH_POPULATES_NODE_MAP with HAVE_MEMBLOCK_NODE_MAP. Also,
relocate for_each_mem_pfn_range() and helper from mm.h to memblock.h
as page_alloc.c would no longer host an alternative implementation.
This change is ultimately one to one mapping and shouldn't cause any
observable difference; however, after the recent changes, there are
some functions which now would fit memblock.c better than page_alloc.c
and dependency on HAVE_MEMBLOCK_NODE_MAP instead of HAVE_MEMBLOCK
doesn't make much sense on some of them. Further cleanups for
functions inside HAVE_MEMBLOCK_NODE_MAP in mm.h would be nice.
-v2: Fix compile bug introduced by mis-spelling
CONFIG_HAVE_MEMBLOCK_NODE_MAP to CONFIG_MEMBLOCK_HAVE_NODE_MAP in
mmzone.h. Reported by Stephen Rothwell.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Chen Liqin <liqin.chen@sunplusct.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 259 |
1 files changed, 18 insertions, 241 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6ce27331834c..63ff8dab433a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -181,42 +181,17 @@ static unsigned long __meminitdata nr_kernel_pages; | |||
181 | static unsigned long __meminitdata nr_all_pages; | 181 | static unsigned long __meminitdata nr_all_pages; |
182 | static unsigned long __meminitdata dma_reserve; | 182 | static unsigned long __meminitdata dma_reserve; |
183 | 183 | ||
184 | #ifdef CONFIG_ARCH_POPULATES_NODE_MAP | 184 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
185 | #ifndef CONFIG_HAVE_MEMBLOCK_NODE_MAP | 185 | static unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES]; |
186 | /* | 186 | static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES]; |
187 | * MAX_ACTIVE_REGIONS determines the maximum number of distinct ranges | 187 | static unsigned long __initdata required_kernelcore; |
188 | * of memory (RAM) that may be registered with add_active_range(). | 188 | static unsigned long __initdata required_movablecore; |
189 | * Ranges passed to add_active_range() will be merged if possible so | 189 | static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES]; |
190 | * the number of times add_active_range() can be called is related to | 190 | |
191 | * the number of nodes and the number of holes | 191 | /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */ |
192 | */ | 192 | int movable_zone; |
193 | #ifdef CONFIG_MAX_ACTIVE_REGIONS | 193 | EXPORT_SYMBOL(movable_zone); |
194 | /* Allow an architecture to set MAX_ACTIVE_REGIONS to save memory */ | 194 | #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ |
195 | #define MAX_ACTIVE_REGIONS CONFIG_MAX_ACTIVE_REGIONS | ||
196 | #else | ||
197 | #if MAX_NUMNODES >= 32 | ||
198 | /* If there can be many nodes, allow up to 50 holes per node */ | ||
199 | #define MAX_ACTIVE_REGIONS (MAX_NUMNODES*50) | ||
200 | #else | ||
201 | /* By default, allow up to 256 distinct regions */ | ||
202 | #define MAX_ACTIVE_REGIONS 256 | ||
203 | #endif | ||
204 | #endif | ||
205 | |||
206 | static struct node_active_region __meminitdata early_node_map[MAX_ACTIVE_REGIONS]; | ||
207 | static int __meminitdata nr_nodemap_entries; | ||
208 | #endif /* !CONFIG_HAVE_MEMBLOCK_NODE_MAP */ | ||
209 | |||
210 | static unsigned long __meminitdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES]; | ||
211 | static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES]; | ||
212 | static unsigned long __initdata required_kernelcore; | ||
213 | static unsigned long __initdata required_movablecore; | ||
214 | static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES]; | ||
215 | |||
216 | /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */ | ||
217 | int movable_zone; | ||
218 | EXPORT_SYMBOL(movable_zone); | ||
219 | #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ | ||
220 | 195 | ||
221 | #if MAX_NUMNODES > 1 | 196 | #if MAX_NUMNODES > 1 |
222 | int nr_node_ids __read_mostly = MAX_NUMNODES; | 197 | int nr_node_ids __read_mostly = MAX_NUMNODES; |
@@ -3734,7 +3709,7 @@ __meminit int init_currently_empty_zone(struct zone *zone, | |||
3734 | return 0; | 3709 | return 0; |
3735 | } | 3710 | } |
3736 | 3711 | ||
3737 | #ifdef CONFIG_ARCH_POPULATES_NODE_MAP | 3712 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
3738 | #ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID | 3713 | #ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID |
3739 | /* | 3714 | /* |
3740 | * Required by SPARSEMEM. Given a PFN, return what node the PFN is on. | 3715 | * Required by SPARSEMEM. Given a PFN, return what node the PFN is on. |
@@ -4002,7 +3977,7 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid, | |||
4002 | return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn); | 3977 | return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn); |
4003 | } | 3978 | } |
4004 | 3979 | ||
4005 | #else | 3980 | #else /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ |
4006 | static inline unsigned long __meminit zone_spanned_pages_in_node(int nid, | 3981 | static inline unsigned long __meminit zone_spanned_pages_in_node(int nid, |
4007 | unsigned long zone_type, | 3982 | unsigned long zone_type, |
4008 | unsigned long *zones_size) | 3983 | unsigned long *zones_size) |
@@ -4020,7 +3995,7 @@ static inline unsigned long __meminit zone_absent_pages_in_node(int nid, | |||
4020 | return zholes_size[zone_type]; | 3995 | return zholes_size[zone_type]; |
4021 | } | 3996 | } |
4022 | 3997 | ||
4023 | #endif | 3998 | #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ |
4024 | 3999 | ||
4025 | static void __meminit calculate_node_totalpages(struct pglist_data *pgdat, | 4000 | static void __meminit calculate_node_totalpages(struct pglist_data *pgdat, |
4026 | unsigned long *zones_size, unsigned long *zholes_size) | 4001 | unsigned long *zones_size, unsigned long *zholes_size) |
@@ -4243,10 +4218,10 @@ static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat) | |||
4243 | */ | 4218 | */ |
4244 | if (pgdat == NODE_DATA(0)) { | 4219 | if (pgdat == NODE_DATA(0)) { |
4245 | mem_map = NODE_DATA(0)->node_mem_map; | 4220 | mem_map = NODE_DATA(0)->node_mem_map; |
4246 | #ifdef CONFIG_ARCH_POPULATES_NODE_MAP | 4221 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
4247 | if (page_to_pfn(mem_map) != pgdat->node_start_pfn) | 4222 | if (page_to_pfn(mem_map) != pgdat->node_start_pfn) |
4248 | mem_map -= (pgdat->node_start_pfn - ARCH_PFN_OFFSET); | 4223 | mem_map -= (pgdat->node_start_pfn - ARCH_PFN_OFFSET); |
4249 | #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ | 4224 | #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ |
4250 | } | 4225 | } |
4251 | #endif | 4226 | #endif |
4252 | #endif /* CONFIG_FLAT_NODE_MEM_MAP */ | 4227 | #endif /* CONFIG_FLAT_NODE_MEM_MAP */ |
@@ -4271,7 +4246,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size, | |||
4271 | free_area_init_core(pgdat, zones_size, zholes_size); | 4246 | free_area_init_core(pgdat, zones_size, zholes_size); |
4272 | } | 4247 | } |
4273 | 4248 | ||
4274 | #ifdef CONFIG_ARCH_POPULATES_NODE_MAP | 4249 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
4275 | 4250 | ||
4276 | #if MAX_NUMNODES > 1 | 4251 | #if MAX_NUMNODES > 1 |
4277 | /* | 4252 | /* |
@@ -4292,201 +4267,6 @@ static inline void setup_nr_node_ids(void) | |||
4292 | } | 4267 | } |
4293 | #endif | 4268 | #endif |
4294 | 4269 | ||
4295 | #ifndef CONFIG_HAVE_MEMBLOCK_NODE_MAP | ||
4296 | /* | ||
4297 | * Common iterator interface used to define for_each_mem_pfn_range(). | ||
4298 | */ | ||
4299 | void __meminit __next_mem_pfn_range(int *idx, int nid, | ||
4300 | unsigned long *out_start_pfn, | ||
4301 | unsigned long *out_end_pfn, int *out_nid) | ||
4302 | { | ||
4303 | struct node_active_region *r = NULL; | ||
4304 | |||
4305 | while (++*idx < nr_nodemap_entries) { | ||
4306 | if (nid == MAX_NUMNODES || nid == early_node_map[*idx].nid) { | ||
4307 | r = &early_node_map[*idx]; | ||
4308 | break; | ||
4309 | } | ||
4310 | } | ||
4311 | if (!r) { | ||
4312 | *idx = -1; | ||
4313 | return; | ||
4314 | } | ||
4315 | |||
4316 | if (out_start_pfn) | ||
4317 | *out_start_pfn = r->start_pfn; | ||
4318 | if (out_end_pfn) | ||
4319 | *out_end_pfn = r->end_pfn; | ||
4320 | if (out_nid) | ||
4321 | *out_nid = r->nid; | ||
4322 | } | ||
4323 | |||
4324 | /** | ||
4325 | * add_active_range - Register a range of PFNs backed by physical memory | ||
4326 | * @nid: The node ID the range resides on | ||
4327 | * @start_pfn: The start PFN of the available physical memory | ||
4328 | * @end_pfn: The end PFN of the available physical memory | ||
4329 | * | ||
4330 | * These ranges are stored in an early_node_map[] and later used by | ||
4331 | * free_area_init_nodes() to calculate zone sizes and holes. If the | ||
4332 | * range spans a memory hole, it is up to the architecture to ensure | ||
4333 | * the memory is not freed by the bootmem allocator. If possible | ||
4334 | * the range being registered will be merged with existing ranges. | ||
4335 | */ | ||
4336 | void __init add_active_range(unsigned int nid, unsigned long start_pfn, | ||
4337 | unsigned long end_pfn) | ||
4338 | { | ||
4339 | int i; | ||
4340 | |||
4341 | mminit_dprintk(MMINIT_TRACE, "memory_register", | ||
4342 | "Entering add_active_range(%d, %#lx, %#lx) " | ||
4343 | "%d entries of %d used\n", | ||
4344 | nid, start_pfn, end_pfn, | ||
4345 | nr_nodemap_entries, MAX_ACTIVE_REGIONS); | ||
4346 | |||
4347 | mminit_validate_memmodel_limits(&start_pfn, &end_pfn); | ||
4348 | |||
4349 | /* Merge with existing active regions if possible */ | ||
4350 | for (i = 0; i < nr_nodemap_entries; i++) { | ||
4351 | if (early_node_map[i].nid != nid) | ||
4352 | continue; | ||
4353 | |||
4354 | /* Skip if an existing region covers this new one */ | ||
4355 | if (start_pfn >= early_node_map[i].start_pfn && | ||
4356 | end_pfn <= early_node_map[i].end_pfn) | ||
4357 | return; | ||
4358 | |||
4359 | /* Merge forward if suitable */ | ||
4360 | if (start_pfn <= early_node_map[i].end_pfn && | ||
4361 | end_pfn > early_node_map[i].end_pfn) { | ||
4362 | early_node_map[i].end_pfn = end_pfn; | ||
4363 | return; | ||
4364 | } | ||
4365 | |||
4366 | /* Merge backward if suitable */ | ||
4367 | if (start_pfn < early_node_map[i].start_pfn && | ||
4368 | end_pfn >= early_node_map[i].start_pfn) { | ||
4369 | early_node_map[i].start_pfn = start_pfn; | ||
4370 | return; | ||
4371 | } | ||
4372 | } | ||
4373 | |||
4374 | /* Check that early_node_map is large enough */ | ||
4375 | if (i >= MAX_ACTIVE_REGIONS) { | ||
4376 | printk(KERN_CRIT "More than %d memory regions, truncating\n", | ||
4377 | MAX_ACTIVE_REGIONS); | ||
4378 | return; | ||
4379 | } | ||
4380 | |||
4381 | early_node_map[i].nid = nid; | ||
4382 | early_node_map[i].start_pfn = start_pfn; | ||
4383 | early_node_map[i].end_pfn = end_pfn; | ||
4384 | nr_nodemap_entries = i + 1; | ||
4385 | } | ||
4386 | |||
4387 | /** | ||
4388 | * remove_active_range - Shrink an existing registered range of PFNs | ||
4389 | * @nid: The node id the range is on that should be shrunk | ||
4390 | * @start_pfn: The new PFN of the range | ||
4391 | * @end_pfn: The new PFN of the range | ||
4392 | * | ||
4393 | * i386 with NUMA use alloc_remap() to store a node_mem_map on a local node. | ||
4394 | * The map is kept near the end physical page range that has already been | ||
4395 | * registered. This function allows an arch to shrink an existing registered | ||
4396 | * range. | ||
4397 | */ | ||
4398 | void __init remove_active_range(unsigned int nid, unsigned long start_pfn, | ||
4399 | unsigned long end_pfn) | ||
4400 | { | ||
4401 | unsigned long this_start_pfn, this_end_pfn; | ||
4402 | int i, j; | ||
4403 | int removed = 0; | ||
4404 | |||
4405 | printk(KERN_DEBUG "remove_active_range (%d, %lu, %lu)\n", | ||
4406 | nid, start_pfn, end_pfn); | ||
4407 | |||
4408 | /* Find the old active region end and shrink */ | ||
4409 | for_each_mem_pfn_range(i, nid, &this_start_pfn, &this_end_pfn, NULL) { | ||
4410 | if (this_start_pfn >= start_pfn && this_end_pfn <= end_pfn) { | ||
4411 | /* clear it */ | ||
4412 | early_node_map[i].start_pfn = 0; | ||
4413 | early_node_map[i].end_pfn = 0; | ||
4414 | removed = 1; | ||
4415 | continue; | ||
4416 | } | ||
4417 | if (this_start_pfn < start_pfn && this_end_pfn > start_pfn) { | ||
4418 | early_node_map[i].end_pfn = start_pfn; | ||
4419 | if (this_end_pfn > end_pfn) | ||
4420 | add_active_range(nid, end_pfn, this_end_pfn); | ||
4421 | continue; | ||
4422 | } | ||
4423 | if (this_start_pfn >= start_pfn && this_end_pfn > end_pfn && | ||
4424 | this_start_pfn < end_pfn) { | ||
4425 | early_node_map[i].start_pfn = end_pfn; | ||
4426 | continue; | ||
4427 | } | ||
4428 | } | ||
4429 | |||
4430 | if (!removed) | ||
4431 | return; | ||
4432 | |||
4433 | /* remove the blank ones */ | ||
4434 | for (i = nr_nodemap_entries - 1; i > 0; i--) { | ||
4435 | if (early_node_map[i].nid != nid) | ||
4436 | continue; | ||
4437 | if (early_node_map[i].end_pfn) | ||
4438 | continue; | ||
4439 | /* we found it, get rid of it */ | ||
4440 | for (j = i; j < nr_nodemap_entries - 1; j++) | ||
4441 | memcpy(&early_node_map[j], &early_node_map[j+1], | ||
4442 | sizeof(early_node_map[j])); | ||
4443 | j = nr_nodemap_entries - 1; | ||
4444 | memset(&early_node_map[j], 0, sizeof(early_node_map[j])); | ||
4445 | nr_nodemap_entries--; | ||
4446 | } | ||
4447 | } | ||
4448 | |||
4449 | /** | ||
4450 | * remove_all_active_ranges - Remove all currently registered regions | ||
4451 | * | ||
4452 | * During discovery, it may be found that a table like SRAT is invalid | ||
4453 | * and an alternative discovery method must be used. This function removes | ||
4454 | * all currently registered regions. | ||
4455 | */ | ||
4456 | void __init remove_all_active_ranges(void) | ||
4457 | { | ||
4458 | memset(early_node_map, 0, sizeof(early_node_map)); | ||
4459 | nr_nodemap_entries = 0; | ||
4460 | } | ||
4461 | |||
4462 | /* Compare two active node_active_regions */ | ||
4463 | static int __init cmp_node_active_region(const void *a, const void *b) | ||
4464 | { | ||
4465 | struct node_active_region *arange = (struct node_active_region *)a; | ||
4466 | struct node_active_region *brange = (struct node_active_region *)b; | ||
4467 | |||
4468 | /* Done this way to avoid overflows */ | ||
4469 | if (arange->start_pfn > brange->start_pfn) | ||
4470 | return 1; | ||
4471 | if (arange->start_pfn < brange->start_pfn) | ||
4472 | return -1; | ||
4473 | |||
4474 | return 0; | ||
4475 | } | ||
4476 | |||
4477 | /* sort the node_map by start_pfn */ | ||
4478 | void __init sort_node_map(void) | ||
4479 | { | ||
4480 | sort(early_node_map, (size_t)nr_nodemap_entries, | ||
4481 | sizeof(struct node_active_region), | ||
4482 | cmp_node_active_region, NULL); | ||
4483 | } | ||
4484 | #else /* !CONFIG_HAVE_MEMBLOCK_NODE_MAP */ | ||
4485 | static inline void sort_node_map(void) | ||
4486 | { | ||
4487 | } | ||
4488 | #endif | ||
4489 | |||
4490 | /** | 4270 | /** |
4491 | * node_map_pfn_alignment - determine the maximum internode alignment | 4271 | * node_map_pfn_alignment - determine the maximum internode alignment |
4492 | * | 4272 | * |
@@ -4764,9 +4544,6 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn) | |||
4764 | unsigned long start_pfn, end_pfn; | 4544 | unsigned long start_pfn, end_pfn; |
4765 | int i, nid; | 4545 | int i, nid; |
4766 | 4546 | ||
4767 | /* Sort early_node_map as initialisation assumes it is sorted */ | ||
4768 | sort_node_map(); | ||
4769 | |||
4770 | /* Record where the zone boundaries are */ | 4547 | /* Record where the zone boundaries are */ |
4771 | memset(arch_zone_lowest_possible_pfn, 0, | 4548 | memset(arch_zone_lowest_possible_pfn, 0, |
4772 | sizeof(arch_zone_lowest_possible_pfn)); | 4549 | sizeof(arch_zone_lowest_possible_pfn)); |
@@ -4867,7 +4644,7 @@ static int __init cmdline_parse_movablecore(char *p) | |||
4867 | early_param("kernelcore", cmdline_parse_kernelcore); | 4644 | early_param("kernelcore", cmdline_parse_kernelcore); |
4868 | early_param("movablecore", cmdline_parse_movablecore); | 4645 | early_param("movablecore", cmdline_parse_movablecore); |
4869 | 4646 | ||
4870 | #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ | 4647 | #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ |
4871 | 4648 | ||
4872 | /** | 4649 | /** |
4873 | * set_dma_reserve - set the specified number of pages reserved in the first zone | 4650 | * set_dma_reserve - set the specified number of pages reserved in the first zone |