diff -urNp a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
--- a/arch/ia64/mm/discontig.c	Thu Aug  1 01:05:40 2002
+++ b/arch/ia64/mm/discontig.c	Thu Aug  1 00:55:31 2002
@@ -314,6 +314,70 @@ discontig_mem_init(void)
 
 
 /*
+ * Add zones of the other nodes to zonelists
+ */
+static void
+build_zonelists_others(int local_node)
+{
+	int 		i, j, k, cnodeid;
+	pg_data_t	*pgdat, *node;
+	zonelist_t	*zonelist;
+	zone_t		*zone;
+
+	pgdat = NODE_DATA(local_node);
+
+	for (i = 0; i <= GFP_ZONEMASK; i++) {
+
+		zonelist = pgdat->node_zonelists + i;
+
+		/* find bottom of the list */
+		for (j = 0; zonelist->zones[j] ;j++);
+
+		k = ZONE_NORMAL;
+		if (i & __GFP_HIGHMEM)
+			k = ZONE_HIGHMEM;
+		if (i & __GFP_DMA)
+			k = ZONE_DMA;
+
+		/*
+		 * Now we build the zonelist so that it contains the zones
+		 * of all the other nodes.
+		 */
+
+		for (cnodeid=local_node+1; local_node!=(cnodeid%numnodes); cnodeid++){
+			node = NODE_DATA(cnodeid % numnodes);
+			switch (k) {
+			default:
+				BUG();
+				/*
+				 * fallthrough:
+				 */
+			case ZONE_HIGHMEM:
+				zone = node->node_zones + ZONE_HIGHMEM;
+				if (zone->totalsize) {
+#ifndef CONFIG_HIGHMEM
+					BUG();
+#endif
+					zonelist->zones[j++] = zone;
+				}
+			case ZONE_NORMAL:
+				zone = node->node_zones + ZONE_NORMAL;
+				if (zone->totalsize)
+					zonelist->zones[j++] = zone;
+				
+			case ZONE_DMA:
+				zone = node->node_zones + ZONE_DMA;
+				if (zone->totalsize)
+					zonelist->zones[j++] = zone;
+			}
+		}
+		zonelist->zones[j++] = NULL;
+	} 
+}
+
+
+
+/*
  * Initialize the paging system.
  *	- determine sizes of each node
  *	- initialize the paging system for the node
@@ -382,6 +446,11 @@ discontig_paging_init(void)
 		max_mapnr = MAX(max_mapnr, page - mem_map);
 	}
 
+	/* build_all_zonelists */
+	for (cnodeid=0; cnodeid < numnodes; cnodeid++) {
+		build_zonelists_others(cnodeid);
+	}
+
 	/*
 	 * Finish setting up the node data for this node, then copy it to the other nodes.
 	 */
diff -urNp a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Thu Aug  1 00:58:35 2002
+++ b/include/linux/mm.h	Thu Aug  1 00:55:31 2002
@@ -367,7 +367,8 @@ static inline struct page * alloc_pages(
 	 */
 	if (order >= MAX_ORDER)
 		return NULL;
-	return _alloc_pages(gfp_mask, order);
+	return __alloc_pages(gfp_mask, order,
+			NODE_DATA(numa_node_id())->node_zonelists + (gfp_mask & GFP_ZONEMASK) );
 }
 
 #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
diff -urNp a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	Thu Aug  1 00:59:07 2002
+++ b/include/linux/mmzone.h	Thu Aug  1 00:55:31 2002
@@ -79,8 +79,21 @@ typedef struct zone_struct {
  * so despite the zonelist table being relatively big, the cache
  * footprint of this construct is very small.
  */
+#ifndef CONFIG_DISCONTIGMEM
+#define PLAT_MAX_COMPACT_NODES 1
+#elif defined(CONFIG_IA64_SGI_SN1)
+#include <asm/sn/sn1/mmzone_sn1.h>
+#elif defined(CONFIG_IA64_SGI_SN2)
+#include <asm/sn/sn2/mmzone_sn2.h>
+#elif defined(CONFIG_IA64_DIG)
+#include <asm/mmzone_dig_numa.h>
+#else
+#error "Unknown architecture"
+#endif /* !CONFIG_DISCONTIGMEM */
+
+
 typedef struct zonelist_struct {
-	zone_t * zones [MAX_NR_ZONES+1]; // NULL delimited
+	zone_t * zones [PLAT_MAX_COMPACT_NODES * MAX_NR_ZONES+1]; // NULL delimited
 } zonelist_t;
 
 #define GFP_ZONEMASK	0x0f
@@ -114,9 +127,8 @@ typedef struct pglist_data {
 extern int numnodes;
 extern pg_data_t *pgdat_list;
 
-#define memclass(pgzone, classzone)	(((pgzone)->zone_pgdat == (classzone)->zone_pgdat) \
-			&& ((pgzone) <= (classzone)))
-
+#define memclass(pgzone, classzone)	       (((pgzone) - (pgzone)->zone_pgdat->node_zones) <= \
+((classzone) - (classzone)->zone_pgdat->node_zones))
 /*
  * The following two are not meant for general usage. They are here as
  * prototypes for the discontig memory code.
diff -urNp a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Thu Aug  1 00:59:28 2002
+++ b/kernel/ksyms.c	Thu Aug  1 00:55:31 2002
@@ -90,7 +90,9 @@ EXPORT_SYMBOL(exit_fs);
 EXPORT_SYMBOL(exit_sighand);
 
 /* internal kernel memory management */
+#ifndef CONFIG_DISCONTIGMEM
 EXPORT_SYMBOL(_alloc_pages);
+#endif
 EXPORT_SYMBOL(__alloc_pages);
 EXPORT_SYMBOL(alloc_pages_node);
 EXPORT_SYMBOL(__get_free_pages);
diff -urNp a/mm/numa.c b/mm/numa.c
--- a/mm/numa.c	Thu Aug  1 00:58:15 2002
+++ b/mm/numa.c	Fri Aug  2 00:20:00 2002
@@ -82,49 +93,5 @@ void __init free_area_init_node(int nid,
 	memset(pgdat->valid_addr_bitmap, 0, size);
 }
 
-static struct page * alloc_pages_pgdat(pg_data_t *pgdat, unsigned int gfp_mask,
-	unsigned int order)
-{
-	return __alloc_pages(gfp_mask, order, pgdat->node_zonelists + (gfp_mask & GFP_ZONEMASK));
-}
-
-/*
- * This can be refined. Currently, tries to do round robin, instead
- * should do concentratic circle search, starting from current node.
- */
-struct page * _alloc_pages(unsigned int gfp_mask, unsigned int order)
-{
-	struct page *ret = 0;
-	pg_data_t *start, *temp;
-#ifndef CONFIG_NUMA
-	unsigned long flags;
-	static pg_data_t *next = 0;
-#endif
-
-	if (order >= MAX_ORDER)
-		return NULL;
-#ifdef CONFIG_NUMA
-	temp = NODE_DATA(numa_node_id());
-#else
-	spin_lock_irqsave(&node_lock, flags);
-	if (!next) next = pgdat_list;
-	temp = next;
-	next = next->node_next;
-	spin_unlock_irqrestore(&node_lock, flags);
-#endif
-	start = temp;
-	while (temp) {
-		if ((ret = alloc_pages_pgdat(temp, gfp_mask, order)))
-			return(ret);
-		temp = temp->node_next;
-	}
-	temp = pgdat_list;
-	while (temp != start) {
-		if ((ret = alloc_pages_pgdat(temp, gfp_mask, order)))
-			return(ret);
-		temp = temp->node_next;
-	}
-	return(0);
-}
 
 #endif /* CONFIG_DISCONTIGMEM */
