diff options
Diffstat (limited to 'mm/page_alloc.c')
| -rw-r--r-- | mm/page_alloc.c | 80 |
1 files changed, 67 insertions, 13 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f32fae3121f0..41c6e3aa059f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -2929,6 +2929,14 @@ void __init free_bootmem_with_active_regions(int nid, | |||
| 2929 | } | 2929 | } |
| 2930 | } | 2930 | } |
| 2931 | 2931 | ||
| 2932 | void __init work_with_active_regions(int nid, work_fn_t work_fn, void *data) | ||
| 2933 | { | ||
| 2934 | int i; | ||
| 2935 | |||
| 2936 | for_each_active_range_index_in_nid(i, nid) | ||
| 2937 | work_fn(early_node_map[i].start_pfn, early_node_map[i].end_pfn, | ||
| 2938 | data); | ||
| 2939 | } | ||
| 2932 | /** | 2940 | /** |
| 2933 | * sparse_memory_present_with_active_regions - Call memory_present for each active range | 2941 | * sparse_memory_present_with_active_regions - Call memory_present for each active range |
| 2934 | * @nid: The node to call memory_present for. If MAX_NUMNODES, all nodes will be used. | 2942 | * @nid: The node to call memory_present for. If MAX_NUMNODES, all nodes will be used. |
| @@ -3461,6 +3469,11 @@ void __paginginit free_area_init_node(int nid, struct pglist_data *pgdat, | |||
| 3461 | calculate_node_totalpages(pgdat, zones_size, zholes_size); | 3469 | calculate_node_totalpages(pgdat, zones_size, zholes_size); |
| 3462 | 3470 | ||
| 3463 | alloc_node_mem_map(pgdat); | 3471 | alloc_node_mem_map(pgdat); |
| 3472 | #ifdef CONFIG_FLAT_NODE_MEM_MAP | ||
| 3473 | printk(KERN_DEBUG "free_area_init_node: node %d, pgdat %08lx, node_mem_map %08lx\n", | ||
| 3474 | nid, (unsigned long)pgdat, | ||
| 3475 | (unsigned long)pgdat->node_mem_map); | ||
| 3476 | #endif | ||
| 3464 | 3477 | ||
| 3465 | free_area_init_core(pgdat, zones_size, zholes_size); | 3478 | free_area_init_core(pgdat, zones_size, zholes_size); |
| 3466 | } | 3479 | } |
| @@ -3547,27 +3560,68 @@ void __init add_active_range(unsigned int nid, unsigned long start_pfn, | |||
| 3547 | } | 3560 | } |
| 3548 | 3561 | ||
| 3549 | /** | 3562 | /** |
| 3550 | * shrink_active_range - Shrink an existing registered range of PFNs | 3563 | * remove_active_range - Shrink an existing registered range of PFNs |
| 3551 | * @nid: The node id the range is on that should be shrunk | 3564 | * @nid: The node id the range is on that should be shrunk |
| 3552 | * @old_end_pfn: The old end PFN of the range | 3565 | * @start_pfn: The new PFN of the range |
| 3553 | * @new_end_pfn: The new PFN of the range | 3566 | * @end_pfn: The new PFN of the range |
| 3554 | * | 3567 | * |
| 3555 | * i386 with NUMA use alloc_remap() to store a node_mem_map on a local node. | 3568 | * i386 with NUMA use alloc_remap() to store a node_mem_map on a local node. |
| 3556 | * The map is kept at the end physical page range that has already been | 3569 | * The map is kept near the end physical page range that has already been |
| 3557 | * registered with add_active_range(). This function allows an arch to shrink | 3570 | * registered. This function allows an arch to shrink an existing registered |
| 3558 | * an existing registered range. | 3571 | * range. |
| 3559 | */ | 3572 | */ |
| 3560 | void __init shrink_active_range(unsigned int nid, unsigned long old_end_pfn, | 3573 | void __init remove_active_range(unsigned int nid, unsigned long start_pfn, |
| 3561 | unsigned long new_end_pfn) | 3574 | unsigned long end_pfn) |
| 3562 | { | 3575 | { |
| 3563 | int i; | 3576 | int i, j; |
| 3577 | int removed = 0; | ||
| 3578 | |||
| 3579 | printk(KERN_DEBUG "remove_active_range (%d, %lu, %lu)\n", | ||
| 3580 | nid, start_pfn, end_pfn); | ||
| 3564 | 3581 | ||
| 3565 | /* Find the old active region end and shrink */ | 3582 | /* Find the old active region end and shrink */ |
| 3566 | for_each_active_range_index_in_nid(i, nid) | 3583 | for_each_active_range_index_in_nid(i, nid) { |
| 3567 | if (early_node_map[i].end_pfn == old_end_pfn) { | 3584 | if (early_node_map[i].start_pfn >= start_pfn && |
| 3568 | early_node_map[i].end_pfn = new_end_pfn; | 3585 | early_node_map[i].end_pfn <= end_pfn) { |
| 3569 | break; | 3586 | /* clear it */ |
| 3587 | early_node_map[i].start_pfn = 0; | ||
| 3588 | early_node_map[i].end_pfn = 0; | ||
| 3589 | removed = 1; | ||
| 3590 | continue; | ||
| 3570 | } | 3591 | } |
| 3592 | if (early_node_map[i].start_pfn < start_pfn && | ||
| 3593 | early_node_map[i].end_pfn > start_pfn) { | ||
| 3594 | unsigned long temp_end_pfn = early_node_map[i].end_pfn; | ||
| 3595 | early_node_map[i].end_pfn = start_pfn; | ||
| 3596 | if (temp_end_pfn > end_pfn) | ||
| 3597 | add_active_range(nid, end_pfn, temp_end_pfn); | ||
| 3598 | continue; | ||
| 3599 | } | ||
| 3600 | if (early_node_map[i].start_pfn >= start_pfn && | ||
| 3601 | early_node_map[i].end_pfn > end_pfn && | ||
| 3602 | early_node_map[i].start_pfn < end_pfn) { | ||
| 3603 | early_node_map[i].start_pfn = end_pfn; | ||
| 3604 | continue; | ||
| 3605 | } | ||
| 3606 | } | ||
| 3607 | |||
| 3608 | if (!removed) | ||
| 3609 | return; | ||
| 3610 | |||
| 3611 | /* remove the blank ones */ | ||
| 3612 | for (i = nr_nodemap_entries - 1; i > 0; i--) { | ||
| 3613 | if (early_node_map[i].nid != nid) | ||
| 3614 | continue; | ||
| 3615 | if (early_node_map[i].end_pfn) | ||
| 3616 | continue; | ||
| 3617 | /* we found it, get rid of it */ | ||
| 3618 | for (j = i; j < nr_nodemap_entries - 1; j++) | ||
| 3619 | memcpy(&early_node_map[j], &early_node_map[j+1], | ||
| 3620 | sizeof(early_node_map[j])); | ||
| 3621 | j = nr_nodemap_entries - 1; | ||
| 3622 | memset(&early_node_map[j], 0, sizeof(early_node_map[j])); | ||
| 3623 | nr_nodemap_entries--; | ||
| 3624 | } | ||
| 3571 | } | 3625 | } |
| 3572 | 3626 | ||
| 3573 | /** | 3627 | /** |
