Index: linux-2.6.9-rc1-mm3/include/linux/mmzone.h
===================================================================
--- linux-2.6.9-rc1-mm3.orig/include/linux/mmzone.h	2004-09-04 09:52:25.892045941 +1000
+++ linux-2.6.9-rc1-mm3/include/linux/mmzone.h	2004-09-04 10:06:04.291512800 +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-rc1-mm3/include/linux/swap.h
===================================================================
--- linux-2.6.9-rc1-mm3.orig/include/linux/swap.h	2004-09-04 09:51:41.536957901 +1000
+++ linux-2.6.9-rc1-mm3/include/linux/swap.h	2004-09-04 10:06:04.292512644 +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-rc1-mm3/include/linux/sysctl.h
===================================================================
--- linux-2.6.9-rc1-mm3.orig/include/linux/sysctl.h	2004-09-04 10:03:25.426269150 +1000
+++ linux-2.6.9-rc1-mm3/include/linux/sysctl.h	2004-09-04 10:06:04.293512489 +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-rc1-mm3/kernel/sysctl.c
===================================================================
--- linux-2.6.9-rc1-mm3.orig/kernel/sysctl.c	2004-09-04 10:03:25.435267748 +1000
+++ linux-2.6.9-rc1-mm3/kernel/sysctl.c	2004-09-04 10:06:04.294512333 +1000
@@ -716,10 +716,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-rc1-mm3/mm/page_alloc.c
===================================================================
--- linux-2.6.9-rc1-mm3.orig/mm/page_alloc.c	2004-09-04 09:52:28.184688673 +1000
+++ linux-2.6.9-rc1-mm3/mm/page_alloc.c	2004-09-04 10:08:38.070549046 +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-rc1-mm3/mm/vmscan.c
===================================================================
--- linux-2.6.9-rc1-mm3.orig/mm/vmscan.c	2004-09-04 09:52:28.318667795 +1000
+++ linux-2.6.9-rc1-mm3/mm/vmscan.c	2004-09-04 10:20:17.912491007 +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;
@@ -374,6 +372,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++;
@@ -546,6 +546,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);
 
@@ -587,11 +588,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);
@@ -651,10 +653,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;
@@ -684,42 +682,11 @@ 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)) {
 		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);
@@ -985,11 +952,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;
@@ -998,6 +966,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 1/3
+	 * ram 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++) {
@@ -1011,6 +996,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
@@ -1023,10 +1014,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 {
@@ -1152,7 +1146,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;
 }
@@ -1162,10 +1156,12 @@ 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 (!cpuset_zone_allowed(zone))
 		return;
+	if (zone->free_pages <= zone->pages_low)
+		zone->zone_pgdat->mapped_nrpages = 0;
 	if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
 		return;
 	wake_up_interruptible(&zone->zone_pgdat->kswapd_wait);
@@ -1188,7 +1184,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)
