[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] fix discontig with 0-sized nodes
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.
--
Dave Hansen
haveblue@us.ibm.com
diff -ru linux-2.5.70-clean/arch/i386/mm/discontig.c linux-2.5.70-numa-mem=1/arch/i386/mm/discontig.c
--- linux-2.5.70-clean/arch/i386/mm/discontig.c Mon May 26 18:00:40 2003
+++ linux-2.5.70-numa-mem=1/arch/i386/mm/discontig.c Fri Jun 6 16:52:18 2003
@@ -114,10 +114,16 @@
*/
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 -ru linux-2.5.70-clean/mm/page_alloc.c linux-2.5.70-numa-mem=1/mm/page_alloc.c
--- linux-2.5.70-clean/mm/page_alloc.c Mon May 26 18:00:22 2003
+++ linux-2.5.70-numa-mem=1/mm/page_alloc.c Fri Jun 6 16:57:30 2003
@@ -1153,8 +1153,11 @@
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);
+ }
}
/*