diff -urN oldtree/Documentation/sysctl/vm.txt newtree/Documentation/sysctl/vm.txt
--- oldtree/Documentation/sysctl/vm.txt	2006-06-24 21:49:32.000000000 +0000
+++ newtree/Documentation/sysctl/vm.txt	2006-06-25 11:35:19.114703000 +0000
@@ -22,6 +22,8 @@
 - dirty_background_ratio
 - dirty_expire_centisecs
 - dirty_writeback_centisecs
+- hardmaplimit
+- mapped
 - max_map_count
 - min_free_kbytes
 - laptop_mode
@@ -87,6 +89,27 @@
 
 ==============================================================
 
+hardmaplimit:
+
+This flag makes the vm adhere to the mapped value as closely as possible
+except in the most extreme vm stress where doing so would provoke an out
+of memory condition (see mapped below).
+
+Enabled by default.
+
+==============================================================
+
+mapped:
+
+This is the percentage ram that is filled with mapped pages (applications)
+before the vm will start reclaiming mapped pages by moving them to swap.
+It is altered by the relative stress of the vm at the time so is not
+strictly adhered to to prevent provoking out of memory kills.
+
+Set to 66 by default.
+
+==============================================================
+
 max_map_count:
 
 This file contains the maximum number of memory map areas a process
diff -urN oldtree/include/linux/swap.h newtree/include/linux/swap.h
--- oldtree/include/linux/swap.h	2006-06-24 21:49:32.000000000 +0000
+++ newtree/include/linux/swap.h	2006-06-25 11:35:19.122703500 +0000
@@ -184,7 +184,8 @@
 /* linux/mm/vmscan.c */
 extern unsigned long try_to_free_pages(struct zone **, gfp_t);
 extern unsigned long shrink_all_memory(unsigned long nr_pages);
-extern int vm_swappiness;
+extern int vm_mapped;
+extern int vm_hardmaplimit;
 extern int remove_mapping(struct address_space *mapping, struct page *page);
 extern long vm_total_pages;
 
diff -urN oldtree/include/linux/sysctl.h newtree/include/linux/sysctl.h
--- oldtree/include/linux/sysctl.h	2006-06-24 21:49:32.000000000 +0000
+++ newtree/include/linux/sysctl.h	2006-06-25 11:35:19.142704750 +0000
@@ -177,7 +177,7 @@
 	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_LOWMEM_RESERVE_RATIO=20,/* reservation ratio for lower memory zones */
 	VM_MIN_FREE_KBYTES=21,	/* Minimum free kilobytes to maintain */
 	VM_MAX_MAP_COUNT=22,	/* int: Maximum number of mmaps/address-space */
@@ -196,6 +196,7 @@
 	VM_SWAP_PREFETCH=35,	/* swap prefetch */
 	VM_READAHEAD_RATIO=36,	/* percent of read-ahead size to thrashing-threshold */
 	VM_READAHEAD_HIT_RATE=37, /* one accessed page legitimizes so many read-ahead pages */
+        VM_HARDMAPLIMIT=38,     /* Make mapped a hard limit */
 };
 
 /* CTL_NET names: */
diff -urN oldtree/kernel/sysctl.c newtree/kernel/sysctl.c
--- oldtree/kernel/sysctl.c	2006-06-24 21:49:32.000000000 +0000
+++ newtree/kernel/sysctl.c	2006-06-25 11:35:19.158705750 +0000
@@ -865,16 +865,24 @@
 		.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,
 		.extra1		= &zero,
 		.extra2		= &one_hundred,
 	},
+	{
+		.ctl_name	= VM_HARDMAPLIMIT,
+		.procname	= "hardmaplimit",
+		.data		= &vm_hardmaplimit,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 #ifdef CONFIG_HUGETLB_PAGE
 	 {
 		.ctl_name	= VM_HUGETLB_PAGES,
diff -urN oldtree/mm/vmscan.c newtree/mm/vmscan.c
--- oldtree/mm/vmscan.c	2006-06-24 21:49:32.000000000 +0000
+++ newtree/mm/vmscan.c	2006-06-25 11:35:19.214709250 +0000
@@ -62,7 +62,7 @@
 	 * whole list at once. */
 	int swap_cluster_max;
 
-	int swappiness;
+	int mapped;
 };
 
 /*
@@ -107,10 +107,11 @@
 #endif
 
 /*
- * From 0 .. 100.  Higher means more swappy.
+ * From 0 .. 100.  Lower means more swappy.
  */
-int vm_swappiness = 60;
-long vm_total_pages;	/* The total number of pages which the VM controls */
+int vm_mapped __read_mostly = 66;
+int vm_hardmaplimit __read_mostly = 1;
+static long total_memory __read_mostly;
 
 static LIST_HEAD(shrinker_list);
 static DECLARE_RWSEM(shrinker_rwsem);
@@ -761,10 +762,14 @@
 		 * The distress ratio is important - we don't want to start
 		 * going oom.
 		 *
-		 * A 100% value of vm_swappiness overrides this algorithm
-		 * altogether.
+		 * This distress value is ignored if we apply a hardmaplimit except
+		 * in extreme distress.
+		 *
+		 * A 0% value of vm_mapped overrides this algorithm altogether.
 		 */
-		swap_tendency = mapped_ratio / 2 + distress + sc->swappiness;
+		swap_tendency = mapped_ratio * 100 / (sc->mapped + 1);
+		if (!vm_hardmaplimit || distress == 100)
+			swap_tendency += distress;
 
 		/*
 		 * Now use this metric to decide whether to start moving mapped
@@ -980,7 +985,7 @@
 		.may_writepage = !laptop_mode,
 		.swap_cluster_max = SWAP_CLUSTER_MAX,
 		.may_swap = 1,
-		.swappiness = vm_swappiness,
+		.mapped = vm_mapped,
 	};
 
 	delay_swap_prefetch();
@@ -1074,7 +1079,7 @@
 		.gfp_mask = GFP_KERNEL,
 		.may_swap = 1,
 		.swap_cluster_max = SWAP_CLUSTER_MAX,
-		.swappiness = vm_swappiness,
+		.mapped = vm_mapped,
 	};
 
 loop_again:
@@ -1360,7 +1365,7 @@
 		.may_swap = 0,
 		.swap_cluster_max = nr_pages,
 		.may_writepage = 1,
-		.swappiness = vm_swappiness,
+		.mapped = vm_mapped,
 	};
 
 	delay_swap_prefetch();
@@ -1407,7 +1412,7 @@
 		/* Force reclaiming mapped pages in the passes #3 and #4 */
 		if (pass > 2) {
 			sc.may_swap = 1;
-			sc.swappiness = 100;
+			sc.mapped = 0;
 		}
 
 		for (prio = DEF_PRIORITY; prio >= 0; prio--) {
@@ -1550,7 +1555,7 @@
 		.swap_cluster_max = max_t(unsigned long, nr_pages,
 					SWAP_CLUSTER_MAX),
 		.gfp_mask = gfp_mask,
-		.swappiness = vm_swappiness,
+		.mapped = vm_mapped,
 	};
 
 	disable_swap_token();
