mm, x86: shrink_active_range() should check all
Now we are using register_e820_active_regions() instead of add_active_range() directly. So end_pfn could be different between the value in early_node_map to node_end_pfn. So we need to make shrink_active_range() smarter. shrink_active_range() is a generic MM function in mm/page_alloc.c but it is only used on 32-bit x86. Should we move it back to some file in arch/x86? Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
db3660c190
commit
cc1a9d86ce
3 changed files with 37 additions and 14 deletions
|
@ -282,7 +282,7 @@ static unsigned long calculate_numa_remap_pages(void)
|
||||||
|
|
||||||
node_end_pfn[nid] -= size;
|
node_end_pfn[nid] -= size;
|
||||||
node_remap_start_pfn[nid] = node_end_pfn[nid];
|
node_remap_start_pfn[nid] = node_end_pfn[nid];
|
||||||
shrink_active_range(nid, old_end_pfn, node_end_pfn[nid]);
|
shrink_active_range(nid, node_end_pfn[nid]);
|
||||||
}
|
}
|
||||||
printk("Reserving total of %ld pages for numa KVA remap\n",
|
printk("Reserving total of %ld pages for numa KVA remap\n",
|
||||||
reserve_pages);
|
reserve_pages);
|
||||||
|
|
|
@ -997,8 +997,7 @@ extern void free_area_init_node(int nid, pg_data_t *pgdat,
|
||||||
extern void free_area_init_nodes(unsigned long *max_zone_pfn);
|
extern void free_area_init_nodes(unsigned long *max_zone_pfn);
|
||||||
extern void add_active_range(unsigned int nid, unsigned long start_pfn,
|
extern void add_active_range(unsigned int nid, unsigned long start_pfn,
|
||||||
unsigned long end_pfn);
|
unsigned long end_pfn);
|
||||||
extern void shrink_active_range(unsigned int nid, unsigned long old_end_pfn,
|
extern void shrink_active_range(unsigned int nid, unsigned long new_end_pfn);
|
||||||
unsigned long new_end_pfn);
|
|
||||||
extern void push_node_boundaries(unsigned int nid, unsigned long start_pfn,
|
extern void push_node_boundaries(unsigned int nid, unsigned long start_pfn,
|
||||||
unsigned long end_pfn);
|
unsigned long end_pfn);
|
||||||
extern void remove_all_active_ranges(void);
|
extern void remove_all_active_ranges(void);
|
||||||
|
|
|
@ -3579,25 +3579,49 @@ void __init add_active_range(unsigned int nid, unsigned long start_pfn,
|
||||||
/**
|
/**
|
||||||
* shrink_active_range - Shrink an existing registered range of PFNs
|
* shrink_active_range - Shrink an existing registered range of PFNs
|
||||||
* @nid: The node id the range is on that should be shrunk
|
* @nid: The node id the range is on that should be shrunk
|
||||||
* @old_end_pfn: The old end PFN of the range
|
|
||||||
* @new_end_pfn: The new PFN of the range
|
* @new_end_pfn: The new PFN of the range
|
||||||
*
|
*
|
||||||
* i386 with NUMA use alloc_remap() to store a node_mem_map on a local node.
|
* i386 with NUMA use alloc_remap() to store a node_mem_map on a local node.
|
||||||
* The map is kept at the end physical page range that has already been
|
* The map is kept near the end physical page range that has already been
|
||||||
* registered with add_active_range(). This function allows an arch to shrink
|
* registered. This function allows an arch to shrink an existing registered
|
||||||
* an existing registered range.
|
* range.
|
||||||
*/
|
*/
|
||||||
void __init shrink_active_range(unsigned int nid, unsigned long old_end_pfn,
|
void __init shrink_active_range(unsigned int nid, unsigned long new_end_pfn)
|
||||||
unsigned long new_end_pfn)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i, j;
|
||||||
|
int removed = 0;
|
||||||
|
|
||||||
/* Find the old active region end and shrink */
|
/* Find the old active region end and shrink */
|
||||||
for_each_active_range_index_in_nid(i, nid)
|
for_each_active_range_index_in_nid(i, nid) {
|
||||||
if (early_node_map[i].end_pfn == old_end_pfn) {
|
if (early_node_map[i].start_pfn >= new_end_pfn) {
|
||||||
early_node_map[i].end_pfn = new_end_pfn;
|
/* clear it */
|
||||||
break;
|
early_node_map[i].end_pfn = 0;
|
||||||
|
removed = 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (early_node_map[i].end_pfn > new_end_pfn) {
|
||||||
|
early_node_map[i].end_pfn = new_end_pfn;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!removed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* remove the blank ones */
|
||||||
|
for (i = nr_nodemap_entries - 1; i > 0; i--) {
|
||||||
|
if (early_node_map[i].nid != nid)
|
||||||
|
continue;
|
||||||
|
if (early_node_map[i].end_pfn)
|
||||||
|
continue;
|
||||||
|
/* we found it, get rid of it */
|
||||||
|
for (j = i; j < nr_nodemap_entries - 1; j++)
|
||||||
|
memcpy(&early_node_map[j], &early_node_map[j+1],
|
||||||
|
sizeof(early_node_map[j]));
|
||||||
|
j = nr_nodemap_entries - 1;
|
||||||
|
memset(&early_node_map[j], 0, sizeof(early_node_map[j]));
|
||||||
|
nr_nodemap_entries--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue