diff -urN 2.4.10/include/linux/fs.h vm/include/linux/fs.h
--- 2.4.10/include/linux/fs.h	Sun Sep 23 21:11:42 2001
+++ vm/include/linux/fs.h	Wed Sep 26 15:34:35 2001
@@ -282,7 +282,7 @@
 
 extern void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long offset);
 
-#define touch_buffer(bh)	SetPageReferenced(bh->b_page)
+#define touch_buffer(bh)	mark_page_accessed(bh->b_page)
 
 
 #include <linux/pipe_fs_i.h>
diff -urN 2.4.10/mm/filemap.c vm/mm/filemap.c
--- 2.4.10/mm/filemap.c	Sun Sep 23 21:11:43 2001
+++ vm/mm/filemap.c	Wed Sep 26 15:34:35 2001
@@ -1704,7 +1704,7 @@
 	 * and possibly copy it over to another page..
 	 */
 	old_page = page;
-	mark_page_accessed(page);
+	activate_page(page);
 	if (no_share) {
 		struct page *new_page = alloc_page(GFP_HIGHUSER);
 
diff -urN 2.4.10/mm/swap.c vm/mm/swap.c
--- 2.4.10/mm/swap.c	Sun Sep 23 21:11:43 2001
+++ vm/mm/swap.c	Wed Sep 26 15:34:35 2001
@@ -54,6 +54,7 @@
 		del_page_from_active_list(page);
 		add_page_to_inactive_list(page);
 	}
+	SetPageReferenced(page);
 }	
 
 void deactivate_page(struct page * page)
@@ -72,6 +73,7 @@
 		del_page_from_inactive_list(page);
 		add_page_to_active_list(page);
 	}
+	ClearPageReferenced(page);
 }
 
 void activate_page(struct page * page)
diff -urN 2.4.10/mm/vmscan.c vm/mm/vmscan.c
--- 2.4.10/mm/vmscan.c	Sun Sep 23 21:11:43 2001
+++ vm/mm/vmscan.c	Wed Sep 26 15:35:03 2001
@@ -55,6 +55,9 @@
 		return 0;
 	}
 
+	if (PageActive(page) || (PageInactive(page) && PageReferenced(page)))
+		return 0;
+
 	if (TryLockPage(page))
 		return 0;
 
@@ -329,7 +332,6 @@
 {
 	struct list_head * entry;
 
-	spin_lock(&pagemap_lru_lock);
 	while (max_scan && (entry = inactive_list.prev) != &inactive_list) {
 		struct page * page;
 		swp_entry_t swap;
@@ -358,8 +360,10 @@
 			continue;
 
 		/* Racy check to avoid trylocking when not worthwhile */
-		if (!page->buffers && page_count(page) != 1)
+		if (!page->buffers && page_count(page) != 1) {
+			activate_page_nolock(page);
 			continue;
+		}
 
 		/*
 		 * The page is locked. IO in progress?
@@ -514,7 +518,6 @@
 {
 	struct list_head * entry;
 
-	spin_lock(&pagemap_lru_lock);
 	entry = active_list.prev;
 	while (nr_pages-- && entry != &active_list) {
 		struct page * page;
@@ -529,23 +532,28 @@
 
 		del_page_from_active_list(page);
 		add_page_to_inactive_list(page);
+		SetPageReferenced(page);
 	}
-	spin_unlock(&pagemap_lru_lock);
 }
 
 static int FASTCALL(shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages));
 static int shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages)
 {
-	int max_scan = nr_inactive_pages / priority;
+	int max_scan;
+	int chunk_size = nr_pages;
+	unsigned long ratio;
 
 	nr_pages -= kmem_cache_reap(gfp_mask);
 	if (nr_pages <= 0)
 		return 0;
 
-	/* Do we want to age the active list? */
-	if (nr_inactive_pages < nr_active_pages*2)
-		refill_inactive(nr_pages);
+	spin_lock(&pagemap_lru_lock);
+	nr_pages = chunk_size;
+	/* try to keep the active list 2/3 of the size of the cache */
+	ratio = (unsigned long) nr_pages * nr_active_pages / ((nr_inactive_pages + 1) * 2);
+	refill_inactive(ratio);
 
+	max_scan = nr_inactive_pages / priority;
 	nr_pages = shrink_cache(nr_pages, max_scan, classzone, gfp_mask);
 	if (nr_pages <= 0)
 		return 0;
@@ -558,17 +566,28 @@
 
 int try_to_free_pages(zone_t * classzone, unsigned int gfp_mask, unsigned int order)
 {
-	int priority = DEF_PRIORITY;
-	int ret = 0;
+	int priority, nr_pages, ret = 0;
 
-	do {
-		int nr_pages = SWAP_CLUSTER_MAX;
-		nr_pages = shrink_caches(priority, classzone, gfp_mask, nr_pages);
-		if (nr_pages <= 0)
-			return 1;
+	for (;;) {
+		priority = DEF_PRIORITY;
+		nr_pages = SWAP_CLUSTER_MAX;
+
+		do {
+			nr_pages = shrink_caches(priority, classzone, gfp_mask, nr_pages);
+			if (nr_pages <= 0)
+				return 1;
+
+			ret |= swap_out(priority, classzone, gfp_mask, SWAP_CLUSTER_MAX << 2);
+		} while (--priority);
 
-		ret |= swap_out(priority, classzone, gfp_mask, SWAP_CLUSTER_MAX << 2);
-	} while (--priority);
+		if (likely(ret))
+			break;
+		if (likely(current->pid != 1))
+			break;
+		current->policy |= SCHED_YIELD;
+		__set_current_state(TASK_RUNNING);
+		schedule();
+	}
 
 	return ret;
 }