From: Andi Kleen This patch three issues in NUMA API - When 1 was passed to set_mempolicy or mbind as maxnodes argument get_nodes could corrupt the stack and cause a crash. Fix that. - Remove the restriction to do interleaving only for order 0. Together with the patch that went in previously to use interleaving policy at boot time this should give back the original behaviour of distributing the big hash tables. - Fix some bad white space in comments Signed-off-by: Andrew Morton --- /dev/null | 0 25-akpm/mm/mempolicy.c | 23 +++++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff -puN mm/mempolicy.c~numa-api-updates mm/mempolicy.c --- 25/mm/mempolicy.c~numa-api-updates 2004-06-19 14:08:46.564525128 -0700 +++ 25-akpm/mm/mempolicy.c 2004-06-19 14:08:46.568524520 -0700 @@ -26,7 +26,7 @@ * process policy. * default Allocate on the local node first, or when on a VMA * use the process policy. This is what Linux always did - * in a NUMA aware kernel and still does by, ahem, default. + * in a NUMA aware kernel and still does by, ahem, default. * * The process policy is applied for most non interrupt memory allocations * in that process' context. Interrupts ignore the policies and always @@ -133,6 +133,10 @@ static int get_nodes(unsigned long *node unsigned long endmask; --maxnode; + bitmap_zero(nodes, MAX_NUMNODES); + if (maxnode == 0 || !nmask) + return 0; + nlongs = BITS_TO_LONGS(maxnode); if ((maxnode % BITS_PER_LONG) == 0) endmask = ~0UL; @@ -141,7 +145,7 @@ static int get_nodes(unsigned long *node /* When the user specified more nodes than supported just check if the non supported part is all zero. */ - if (nmask && nlongs > BITS_TO_LONGS(MAX_NUMNODES)) { + if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) { for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) { unsigned long t; if (get_user(t, nmask + k)) @@ -156,8 +160,7 @@ static int get_nodes(unsigned long *node endmask = ~0UL; } - bitmap_zero(nodes, MAX_NUMNODES); - if (nmask && copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long))) + if (copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long))) return -EFAULT; nodes[nlongs-1] &= endmask; return mpol_check_policy(mode, nodes); @@ -620,14 +623,14 @@ static unsigned offset_il_node(struct me /* Allocate a page in interleaved policy. Own path because it needs to do special accounting. */ -static struct page *alloc_page_interleave(unsigned gfp, unsigned nid) +static struct page *alloc_page_interleave(unsigned gfp, unsigned order, unsigned nid) { struct zonelist *zl; struct page *page; BUG_ON(!test_bit(nid, node_online_map)); zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK); - page = __alloc_pages(gfp, 0, zl); + page = __alloc_pages(gfp, order, zl); if (page && page_zone(page) == zl->zones[0]) { zl->zones[0]->pageset[get_cpu()].interleave_hit++; put_cpu(); @@ -675,7 +678,7 @@ alloc_page_vma(unsigned gfp, struct vm_a /* fall back to process interleaving */ nid = interleave_nodes(pol); } - return alloc_page_interleave(gfp, nid); + return alloc_page_interleave(gfp, 0, nid); } return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); } @@ -684,7 +687,7 @@ alloc_page_vma(unsigned gfp, struct vm_a * alloc_pages_current - Allocate pages. * * @gfp: - * %GFP_USER user allocation, + * %GFP_USER user allocation, * %GFP_KERNEL kernel allocation, * %GFP_HIGHMEM highmem allocation, * %GFP_FS don't call back into a file system. @@ -701,8 +704,8 @@ struct page *alloc_pages_current(unsigne if (!pol || in_interrupt()) pol = &default_policy; - if (pol->policy == MPOL_INTERLEAVE && order == 0) - return alloc_page_interleave(gfp, interleave_nodes(pol)); + if (pol->policy == MPOL_INTERLEAVE) + return alloc_page_interleave(gfp, order, interleave_nodes(pol)); return __alloc_pages(gfp, order, zonelist_policy(gfp, pol)); } EXPORT_SYMBOL(alloc_pages_current); diff -L mm/mempolicy.c-o -puN /dev/null /dev/null _