diff -urNp ref/include/linux/sched.h 2.4.20pre7aa1/include/linux/sched.h
--- ref/include/linux/sched.h	Wed Sep 18 00:33:53 2002
+++ 2.4.20pre7aa1/include/linux/sched.h	Wed Sep 18 00:34:32 2002
@@ -332,6 +332,18 @@ extern struct user_struct root_user;
 
 typedef struct prio_array prio_array_t;
 
+struct zone_struct;
+
+/*
+ * Used when a task if trying to free some pages for its own
+ * use - to prevent other tasks/CPUs from stealing the just-freed
+ * pages.
+ */
+struct local_page {
+	struct page *page;
+	struct zone_struct * classzone;
+};
+
 struct task_struct {
 	/*
 	 * offsets of these are hardcoded elsewhere - touch with care
@@ -367,9 +379,7 @@ struct task_struct {
 	task_t *next_task, *prev_task;
 
 	struct mm_struct *mm, *active_mm;
-	struct list_head local_pages;
-
-	unsigned int allocation_order, nr_local_pages;
+	struct local_page local_page;
 
 /* task state */
 	struct linux_binfmt *binfmt;
diff -urNp ref/kernel/fork.c 2.4.20pre7aa1/kernel/fork.c
--- ref/kernel/fork.c	Wed Sep 18 00:33:53 2002
+++ 2.4.20pre7aa1/kernel/fork.c	Wed Sep 18 00:34:32 2002
@@ -679,7 +679,8 @@ int do_fork(unsigned long clone_flags, u
 	p->lock_depth = -1;		/* -1 = no lock */
 	p->start_time = jiffies;
 
-	INIT_LIST_HEAD(&p->local_pages);
+	if (p->local_page.page)
+		BUG();
 
 	retval = -ENOMEM;
 	/* copy all the process information */
diff -urNp ref/mm/page_alloc.c 2.4.20pre7aa1/mm/page_alloc.c
--- ref/mm/page_alloc.c	Wed Sep 18 00:33:54 2002
+++ 2.4.20pre7aa1/mm/page_alloc.c	Wed Sep 18 00:35:03 2002
@@ -111,7 +111,7 @@ static void __free_pages_ok (struct page
 		BUG();
 	page->flags &= ~((1<<PG_referenced) | (1<<PG_dirty));
 
-	if (current->flags & PF_FREE_PAGES)
+	if (unlikely(order == 0 && current->flags & PF_FREE_PAGES))
 		goto local_freelist;
  back_local_freelist:
 
@@ -164,14 +164,12 @@ static void __free_pages_ok (struct page
 	return;
 
  local_freelist:
-	if (current->nr_local_pages)
+	if (current->local_page.page ||
+	    !memclass(page_zone(page), current->local_page.classzone) ||
+	    in_interrupt())
 		goto back_local_freelist;
-	if (in_interrupt())
-		goto back_local_freelist;		
 
-	list_add(&page->list, &current->local_pages);
-	page->index = order;
-	current->nr_local_pages++;
+	current->local_page.page = page;
 }
 
 #define MARK_USED(index, order, area) \
@@ -258,66 +256,41 @@ static struct page * balance_classzone(z
 	struct page * page = NULL;
 	int __freed = 0;
 
-	if (!(gfp_mask & __GFP_WAIT))
-		goto out;
 	if (in_interrupt())
 		BUG();
 
-	current->allocation_order = order;
-	current->flags |= PF_MEMALLOC | PF_FREE_PAGES;
+	if (current->local_page.page)
+		BUG();
+	current->local_page.classzone = classzone;
+	current->flags |= PF_MEMALLOC | (!order ? PF_FREE_PAGES : 0);
 
 	__freed = try_to_free_pages_zone(classzone, gfp_mask);
 
 	current->flags &= ~(PF_MEMALLOC | PF_FREE_PAGES);
 
-	if (current->nr_local_pages) {
-		struct list_head * entry, * local_pages;
-		struct page * tmp;
-		int nr_pages;
-
-		local_pages = &current->local_pages;
-
-		if (likely(__freed)) {
-			/* pick from the last inserted so we're lifo */
-			entry = local_pages->next;
-			do {
-				tmp = list_entry(entry, struct page, list);
-				if (tmp->index == order && memclass(page_zone(tmp), classzone)) {
-					list_del(entry);
-					current->nr_local_pages--;
-					set_page_count(tmp, 1);
-					page = tmp;
-
-					if (page->buffers)
-						BUG();
-					if (page->mapping)
-						BUG();
-					if (!VALID_PAGE(page))
-						BUG();
-					if (PageLocked(page))
-						BUG();
-					if (PageLRU(page))
-						BUG();
-					if (PageActive(page))
-						BUG();
-					if (PageDirty(page))
-						BUG();
-
-					break;
-				}
-			} while ((entry = entry->next) != local_pages);
-		}
+	if (current->local_page.page) {
+		page = current->local_page.page;
+		current->local_page.page = NULL;
 
-		nr_pages = current->nr_local_pages;
-		/* free in reverse order so that the global order will be lifo */
-		while ((entry = local_pages->prev) != local_pages) {
-			list_del(entry);
-			tmp = list_entry(entry, struct page, list);
-			__free_pages_ok(tmp, tmp->index);
-			if (!nr_pages--)
-				BUG();
-		}
-		current->nr_local_pages = 0;
+		if (order != 0)
+			BUG();
+		set_page_count(page, 1);
+		if (!memclass(page_zone(page), classzone))
+			BUG();
+		if (page->buffers)
+			BUG();
+		if (page->mapping)
+			BUG();
+		if (!VALID_PAGE(page))
+			BUG();
+		if (PageLocked(page))
+			BUG();
+		if (PageLRU(page))
+			BUG();
+		if (PageActive(page))
+			BUG();
+		if (PageDirty(page))
+			BUG();
 	}
  out:
 	*freed = __freed;