Index: linux-2.6/mm/mempolicy.c =================================================================== --- linux-2.6.orig/mm/mempolicy.c 2007-06-11 11:13:09.000000000 -0700 +++ linux-2.6/mm/mempolicy.c 2007-06-11 11:19:03.000000000 -0700 @@ -1125,9 +1125,11 @@ static unsigned interleave_nodes(struct struct task_struct *me = current; nid = me->il_next; - next = next_node(nid, policy->v.nodes); - if (next >= MAX_NUMNODES) - next = first_node(policy->v.nodes); + do { + next = next_node(nid, policy->v.nodes); + if (next >= MAX_NUMNODES) + next = first_node(policy->v.nodes); + } while (!NODE_DATA(node)->present_pages); me->il_next = next; return nid; } @@ -1191,6 +1193,11 @@ static inline unsigned interleave_nid(st * for huge pages, since vm_pgoff is in units of small * pages, we need to shift off the always 0 bits to get * a useful offset. + * + * For configurations with memoryless nodes this is broken + * since the allocation attempts on that node will fall + * back to other nodes and thus one neighboring node + * will be overallocated from. */ BUG_ON(shift < PAGE_SHIFT); off = vma->vm_pgoff >> (shift - PAGE_SHIFT); Index: linux-2.6/include/linux/gfp.h =================================================================== --- linux-2.6.orig/include/linux/gfp.h 2007-06-11 11:19:32.000000000 -0700 +++ linux-2.6/include/linux/gfp.h 2007-06-11 11:21:33.000000000 -0700 @@ -134,6 +134,9 @@ static inline struct page *alloc_pages_n if (nid < 0) nid = numa_node_id(); + if ((gfp_mask & __GFP_THISNODE) && !NODE_DATA(nid)->present_pages) + return NULL; + return __alloc_pages(gfp_mask, order, NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_mask)); }