
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.  



 arch/i386/mm/discontig.c |   10 ++++++++--
 mm/page_alloc.c          |    7 +++++--
 2 files changed, 13 insertions(+), 4 deletions(-)

diff -puN arch/i386/mm/discontig.c~discontig-empty-node-fix arch/i386/mm/discontig.c
--- 25/arch/i386/mm/discontig.c~discontig-empty-node-fix	2003-06-10 23:33:16.000000000 -0700
+++ 25-akpm/arch/i386/mm/discontig.c	2003-06-10 23:33:16.000000000 -0700
@@ -114,10 +114,16 @@ void __init get_memcfg_numa_flat(void)
  */
 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)
 		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();
 }
 
 /* 
diff -puN mm/page_alloc.c~discontig-empty-node-fix mm/page_alloc.c
--- 25/mm/page_alloc.c~discontig-empty-node-fix	2003-06-10 23:33:16.000000000 -0700
+++ 25-akpm/mm/page_alloc.c	2003-06-10 23:33:16.000000000 -0700
@@ -1152,8 +1152,11 @@ static void __init calculate_zone_bitmap
 	for (i = 0; i < MAX_NR_ZONES; i++)
 		size += zones_size[i];
 	size = LONG_ALIGN((size + 7) >> 3);
-	pgdat->valid_addr_bitmap = (unsigned long *)alloc_bootmem_node(pgdat, size);
-	memset(pgdat->valid_addr_bitmap, 0, size);
+	if (size) {
+		pgdat->valid_addr_bitmap = 
+			(unsigned long *)alloc_bootmem_node(pgdat, size);
+		memset(pgdat->valid_addr_bitmap, 0, size);
+	}
 }
 
 /*

_
