Index: linux-2.6.9-rc2-mm2/include/linux/mmzone.h
===================================================================
--- linux-2.6.9-rc2-mm2.orig/include/linux/mmzone.h	2004-09-24 09:12:56.839196048 +1000
+++ linux-2.6.9-rc2-mm2/include/linux/mmzone.h	2004-09-24 09:13:21.867276139 +1000
@@ -113,7 +113,7 @@ struct zone {
 	 */
 	spinlock_t		lock;
 	unsigned long		free_pages;
-	unsigned long		pages_min, pages_low, pages_high;
+	unsigned long		pages_min, pages_low, pages_high, pages_unmapped;
 	/*
 	 * protection[] is a pre-calculated number of extra pages that must be
 	 * available in a zone in order for __alloc_pages() to allocate memory
@@ -264,6 +264,7 @@ typedef struct pglist_data {
 	struct pglist_data *pgdat_next;
 	wait_queue_head_t       kswapd_wait;
 	struct task_struct *kswapd;
+	unsigned long mapped_nrpages;
 } pg_data_t;
 
 #define node_present_pages(nid)	(NODE_DATA(nid)->node_present_pages)
Index: linux-2.6.9-rc2-mm2/include/linux/swap.h
===================================================================
--- linux-2.6.9-rc2-mm2.orig/include/linux/swap.h	2004-09-24 09:12:56.840195892 +1000
+++ linux-2.6.9-rc2-mm2/include/linux/swap.h	2004-09-24 09:13:21.868275982 +1000
@@ -174,7 +174,7 @@ extern void swap_setup(void);
 /* linux/mm/vmscan.c */
 extern int try_to_free_pages(struct zone **, unsigned int, unsigned int);
 extern int shrink_all_memory(int);
-extern int vm_swappiness;
+extern int vm_mapped;
 
 #ifdef CONFIG_MMU
 /* linux/mm/shmem.c */
Index: linux-2.6.9-rc2-mm2/include/linux/sysctl.h
===================================================================
--- linux-2.6.9-rc2-mm2.orig/include/linux/sysctl.h	2004-09-24 09:13:20.841436806 +1000
+++ linux-2.6.9-rc2-mm2/include/linux/sysctl.h	2004-09-24 09:13:21.868275982 +1000
@@ -160,7 +160,7 @@ enum
 	VM_OVERCOMMIT_RATIO=16, /* percent of RAM to allow overcommit in */
 	VM_PAGEBUF=17,		/* struct: Control pagebuf parameters */
 	VM_HUGETLB_PAGES=18,	/* int: Number of available Huge Pages */
-	VM_SWAPPINESS=19,	/* Tendency to steal mapped memory */
+	VM_MAPPED=19,		/* percent mapped min while evicting cache */
 	VM_LOWER_ZONE_PROTECTION=20,/* Amount of protection of lower zones */
 	VM_MIN_FREE_KBYTES=21,	/* Minimum free kilobytes to maintain */
 	VM_MAX_MAP_COUNT=22,	/* int: Maximum number of mmaps/address-space */
Index: linux-2.6.9-rc2-mm2/kernel/sysctl.c
===================================================================
--- linux-2.6.9-rc2-mm2.orig/kernel/sysctl.c	2004-09-24 09:13:20.850435397 +1000
+++ linux-2.6.9-rc2-mm2/kernel/sysctl.c	2004-09-24 09:13:21.869275825 +1000
@@ -721,10 +721,10 @@ static ctl_table vm_table[] = {
 		.proc_handler	= &proc_dointvec,
 	},
 	{
-		.ctl_name	= VM_SWAPPINESS,
-		.procname	= "swappiness",
-		.data		= &vm_swappiness,
-		.maxlen		= sizeof(vm_swappiness),
+		.ctl_name	= VM_MAPPED,
+		.procname	= "mapped",
+		.data		= &vm_mapped,
+		.maxlen		= sizeof(vm_mapped),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec_minmax,
 		.strategy	= &sysctl_intvec,
Index: linux-2.6.9-rc2-mm2/mm/page_alloc.c
===================================================================
--- linux-2.6.9-rc2-mm2.orig/mm/page_alloc.c	2004-09-24 09:12:56.836196518 +1000
+++ linux-2.6.9-rc2-mm2/mm/page_alloc.c	2004-09-24 09:13:21.871275512 +1000
@@ -737,6 +737,14 @@ __alloc_pages(unsigned int gfp_mask, uns
 		if (!cpuset_zone_allowed(z))
 			continue;
 
+		if (vm_mapped && wait && 
+			z->free_pages < z->pages_unmapped &&
+			z->free_pages > z->pages_low) {
+				z->zone_pgdat->mapped_nrpages =
+					z->pages_unmapped - z->free_pages;
+				wakeup_kswapd(z);
+		}
+
 		page = buffered_rmqueue(z, order, gfp_mask);
 		if (page)
 			goto got_pg;
@@ -2046,6 +2054,7 @@ static void setup_per_zone_pages_min(voi
 
 		zone->pages_low = zone->pages_min * 2;
 		zone->pages_high = zone->pages_min * 3;
+		zone->pages_unmapped = zone->pages_min * 4;
 		spin_unlock_irqrestore(&zone->lru_lock, flags);
 	}
 }
Index: linux-2.6.9-rc2-mm2/mm/vmscan.c
===================================================================
--- linux-2.6.9-rc2-mm2.orig/mm/vmscan.c	2004-09-24 09:12:56.837196362 +1000
+++ linux-2.6.9-rc2-mm2/mm/vmscan.c	2004-09-24 09:13:21.872275356 +1000
@@ -117,10 +117,7 @@ struct shrinker {
 #define prefetchw_prev_lru_page(_page, _base, _field) do { } while (0)
 #endif
 
-/*
- * From 0 .. 100.  Higher means more swappy.
- */
-int vm_swappiness = 60;
+int vm_mapped = 66;
 static long total_memory;
 
 static LIST_HEAD(shrinker_list);
@@ -346,7 +343,8 @@ static pageout_t pageout(struct page *pa
 /*
  * shrink_list adds the number of reclaimed pages to sc->nr_reclaimed
  */
-static int shrink_list(struct list_head *page_list, struct scan_control *sc)
+static int shrink_list(struct list_head *page_list, struct scan_control *sc,
+			int maplimit)
 {
 	LIST_HEAD(ret_pages);
 	struct pagevec freed_pvec;
@@ -376,6 +374,8 @@ static int shrink_list(struct list_head 
 			goto keep_locked;
 
 		sc->nr_scanned++;
+		if (maplimit && page_mapped(page))
+			goto keep_locked;
 		/* Double the slab pressure for mapped and swapcache pages */
 		if (page_mapped(page) || PageSwapCache(page))
 			sc->nr_scanned++;
@@ -548,6 +548,7 @@ static void shrink_cache(struct zone *zo
 	LIST_HEAD(page_list);
 	struct pagevec pvec;
 	int max_scan = sc->nr_to_scan;
+	int maplimit = 0;
 
 	pagevec_init(&pvec, 1);
 
@@ -589,11 +590,12 @@ static void shrink_cache(struct zone *zo
 			goto done;
 
 		max_scan -= nr_scan;
-		if (current_is_kswapd())
+		if (current_is_kswapd()) {
 			mod_page_state_zone(zone, pgscan_kswapd, nr_scan);
-		else
+			maplimit = !!zone->zone_pgdat->mapped_nrpages;
+		} else
 			mod_page_state_zone(zone, pgscan_direct, nr_scan);
-		nr_freed = shrink_list(&page_list, sc);
+		nr_freed = shrink_list(&page_list, sc, maplimit);
 		if (current_is_kswapd())
 			mod_page_state(kswapd_steal, nr_freed);
 		mod_page_state_zone(zone, pgsteal, nr_freed);
@@ -653,10 +655,6 @@ refill_inactive_zone(struct zone *zone, 
 	LIST_HEAD(l_active);	/* Pages to go onto the active_list */
 	struct page *page;
 	struct pagevec pvec;
-	int reclaim_mapped = 0;
-	long mapped_ratio;
-	long distress;
-	long swap_tendency;
 
 	lru_add_drain();
 	pgmoved = 0;
@@ -686,43 +684,13 @@ refill_inactive_zone(struct zone *zone, 
 	zone->nr_active -= pgmoved;
 	spin_unlock_irq(&zone->lru_lock);
 
-	/*
-	 * `distress' is a measure of how much trouble we're having reclaiming
-	 * pages.  0 -> no problems.  100 -> great trouble.
-	 */
-	distress = 100 >> zone->prev_priority;
-
-	/*
-	 * The point of this algorithm is to decide when to start reclaiming
-	 * mapped memory instead of just pagecache.  Work out how much memory
-	 * is mapped.
-	 */
-	mapped_ratio = (sc->nr_mapped * 100) / total_memory;
-
-	/*
-	 * Now decide how much we really want to unmap some pages.  The mapped
-	 * ratio is downgraded - just because there's a lot of mapped memory
-	 * doesn't necessarily mean that page reclaim isn't succeeding.
-	 *
-	 * The distress ratio is important - we don't want to start going oom.
-	 *
-	 * A 100% value of vm_swappiness overrides this algorithm altogether.
-	 */
-	swap_tendency = mapped_ratio / 2 + distress + vm_swappiness;
-
-	/*
-	 * Now use this metric to decide whether to start moving mapped memory
-	 * onto the inactive list.
-	 */
-	if (swap_tendency >= 100)
-		reclaim_mapped = 1;
 
 	while (!list_empty(&l_hold)) {
 		cond_resched();
 		page = lru_to_page(&l_hold);
 		list_del(&page->lru);
 		if (page_mapped(page)) {
-			if (!reclaim_mapped ||
+			if (zone->zone_pgdat->mapped_nrpages ||
 			    (total_swap_pages == 0 && PageAnon(page)) ||
 			    page_referenced(page, 0)) {
 				list_add(&page->lru, &l_active);
@@ -988,11 +956,12 @@ out:
  * the page allocator fallback scheme to ensure that aging of pages is balanced
  * across the zones.
  */
-static int balance_pgdat(pg_data_t *pgdat, int nr_pages)
+static int 
+balance_pgdat(pg_data_t *pgdat, int nr_pages, unsigned long mapped_nrpages)
 {
 	int to_free = nr_pages;
 	int priority;
-	int i;
+	int i, maplimit = 0;
 	int total_scanned = 0, total_reclaimed = 0;
 	struct reclaim_state *reclaim_state = current->reclaim_state;
 	struct scan_control sc;
@@ -1001,6 +970,23 @@ static int balance_pgdat(pg_data_t *pgda
 	sc.may_writepage = 0;
 	sc.nr_mapped = read_page_state(nr_mapped);
 
+	/*
+	 * Sanity check to ensure we don't have a stale maplimit set
+	 * and are calling balance_pgdat for a different reason.
+	 */
+	if (!nr_pages && mapped_nrpages) {
+		maplimit = 1;
+		nr_pages = mapped_nrpages;
+	}
+	
+	/*
+	 * kswapd does a light balance_pgdat() when there is less than 
+	 * ->pages_unmapped free provided there is less than vm_mapped %
+	 * of that ram mapped.
+	 */
+	if (maplimit && sc.nr_mapped * 100 / total_memory > vm_mapped)
+		return 0;
+
 	inc_page_state(pageoutrun);
 
 	for (i = 0; i < pgdat->nr_zones; i++) {
@@ -1014,6 +1000,12 @@ static int balance_pgdat(pg_data_t *pgda
 		int end_zone = 0;	/* Inclusive.  0 = ZONE_DMA */
 		unsigned long lru_pages = 0;
 
+		/*
+		 * Only do low priority scanning if we're here due to
+		 * mapped watermark.
+		 */
+		if (maplimit && priority < DEF_PRIORITY)
+			goto out;
 		if (nr_pages == 0) {
 			/*
 			 * Scan in the highmem->dma direction for the highest
@@ -1026,10 +1018,13 @@ static int balance_pgdat(pg_data_t *pgda
 						priority != DEF_PRIORITY)
 					continue;
 
-				if (zone->free_pages <= zone->pages_high) {
-					end_zone = i;
-					goto scan;
+				if (zone->free_pages <= zone->pages_high ||
+					(maplimit && zone->free_pages <= 
+					zone->pages_unmapped)) {
+						end_zone = i;
+						goto scan;
 				}
+
 			}
 			goto out;
 		} else {
@@ -1155,7 +1150,7 @@ int kswapd(void *p)
 		schedule();
 		finish_wait(&pgdat->kswapd_wait, &wait);
 
-		balance_pgdat(pgdat, 0);
+		balance_pgdat(pgdat, 0, pgdat->mapped_nrpages);
 	}
 	return 0;
 }
@@ -1165,8 +1160,10 @@ int kswapd(void *p)
  */
 void wakeup_kswapd(struct zone *zone)
 {
-	if (zone->free_pages > zone->pages_low)
+	if (zone->free_pages > zone->pages_unmapped)
 		return;
+	if (zone->free_pages <= zone->pages_low)
+		zone->zone_pgdat->mapped_nrpages = 0;
 	if (!cpuset_zone_allowed(zone))
 		return;
 	if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
@@ -1191,7 +1188,7 @@ int shrink_all_memory(int nr_pages)
 	current->reclaim_state = &reclaim_state;
 	for_each_pgdat(pgdat) {
 		int freed;
-		freed = balance_pgdat(pgdat, nr_to_free);
+		freed = balance_pgdat(pgdat, nr_to_free, 0);
 		ret += freed;
 		nr_to_free -= freed;
 		if (nr_to_free <= 0)
