Commit 9d7a7faf authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] fix discontig with 0-sized nodes

From: Dave Hansen <haveblue@us.ibm.com>

In order to turn an 8-way x440 into a 4-way for testing, we often use
mem=(1/2 of total) and maxcpus=4.  maxcpus has always worked, but mem=
hasn't.  The mem= parameter actually changes the kernel's e820 structure,
which manifests itself as max_pfn.  node_end_pfn[] obeys this because of
find_max_pfn_node(), but node_start_pfn[] wasn't modified.

If you have a mem= line that causes memory to stop before the beginning of
a node, you get a condition where start > end (because start was never
modified).  There is a bug check for this, but it was placed just _before_
the error was made :)

Also, the bootmem alloc functions die if you request something of zero size
from them.  This patch avoids that too.  This shouldn't have much of an
effect on non-NUMA systems.
parent 1e955536
...@@ -114,10 +114,16 @@ void __init get_memcfg_numa_flat(void) ...@@ -114,10 +114,16 @@ void __init get_memcfg_numa_flat(void)
*/ */
static void __init find_max_pfn_node(int nid) static void __init find_max_pfn_node(int nid)
{ {
if (node_start_pfn[nid] >= node_end_pfn[nid])
BUG();
if (node_end_pfn[nid] > max_pfn) if (node_end_pfn[nid] > max_pfn)
node_end_pfn[nid] = max_pfn; node_end_pfn[nid] = max_pfn;
/*
* if a user has given mem=XXXX, then we need to make sure
* that the node _starts_ before that, too, not just ends
*/
if (node_start_pfn[nid] > max_pfn)
node_start_pfn[nid] = max_pfn;
if (node_start_pfn[nid] > node_end_pfn[nid])
BUG();
} }
/* /*
......
...@@ -1152,8 +1152,11 @@ static void __init calculate_zone_bitmap(struct pglist_data *pgdat, ...@@ -1152,8 +1152,11 @@ static void __init calculate_zone_bitmap(struct pglist_data *pgdat,
for (i = 0; i < MAX_NR_ZONES; i++) for (i = 0; i < MAX_NR_ZONES; i++)
size += zones_size[i]; size += zones_size[i];
size = LONG_ALIGN((size + 7) >> 3); size = LONG_ALIGN((size + 7) >> 3);
pgdat->valid_addr_bitmap = (unsigned long *)alloc_bootmem_node(pgdat, size); if (size) {
memset(pgdat->valid_addr_bitmap, 0, size); pgdat->valid_addr_bitmap =
(unsigned long *)alloc_bootmem_node(pgdat, size);
memset(pgdat->valid_addr_bitmap, 0, size);
}
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment