Index: linux-2.6.13-sp/mm/swap_prefetch.c
===================================================================
--- linux-2.6.13-sp.orig/mm/swap_prefetch.c	2005-10-04 21:42:15.000000000 +1000
+++ linux-2.6.13-sp/mm/swap_prefetch.c	2005-10-04 21:43:04.000000000 +1000
@@ -13,6 +13,8 @@
 #include <linux/swap.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/syscalls.h>
+#include <linux/ioprio.h>
 
 /* Time to delay prefetching if vm is busy or prefetching unsuccessful */
 #define PREFETCH_DELAY	(HZ * 5)
@@ -20,13 +22,12 @@
 #define PREFETCH_INTERVAL (HZ)
 
 struct swapped_root_t {
-	unsigned long		busy;
-	spinlock_t		lock;
-	struct list_head	list;
-	struct radix_tree_root	swap_tree;	
-	rwlock_t		*rwlock;
-	unsigned int		count;
-	unsigned int		maxcount;
+	unsigned long		busy;		/* vm busy */
+	spinlock_t		lock;		/* protects all data */
+	struct list_head	list;		/* MRU list of swapped pages */
+	struct radix_tree_root	swap_tree;	/* Lookup tree of pages */
+	unsigned int		count;		/* Number of entries */
+	unsigned int		maxcount;	/* Maximum entries allowed */
 	kmem_cache_t		*cache;
 };
 
@@ -39,7 +40,6 @@ static struct swapped_root_t swapped = {
 	.busy 		= 0,
 	.list  		= LIST_HEAD_INIT(swapped.list),
 	.swap_tree	= RADIX_TREE_INIT(GFP_ATOMIC),
-	.rwlock		= &swapper_space.tree_lock,
 	.count 		= 0,
 };
 
@@ -47,7 +47,9 @@ static struct timer_list prefetch_timer;
 
 static DECLARE_WAIT_QUEUE_HEAD(kprefetchd_wait);
 
-static unsigned long mapped_limit;
+static unsigned long mapped_limit;	/* Max mapped we will prefetch to */
+static unsigned long last_free = 0;	/* Last total free pages */
+static unsigned long temp_free = 0;
 
 /*
  * Create kmem cache for swapped entries
@@ -55,15 +57,14 @@ static unsigned long mapped_limit;
 void __init prepare_prefetch(void)
 {
 	long total_memory = nr_free_pagecache_pages();
-	long se_size = sizeof(struct swapped_entry_t);
 
-	swapped.cache = kmem_cache_create("swapped_entry", se_size,
-		0, 0, NULL, NULL);
+	swapped.cache = kmem_cache_create("swapped_entry",
+		sizeof(struct swapped_entry_t), 0, 0, NULL, NULL);
 	if (unlikely(!swapped.cache))
 		panic("prepare_prefetch(): cannot create swapped_entry SLAB cache");
 
-	/* Set max count of swapped entries to 5% ram */
-	swapped.maxcount = (total_memory / 20) * (PAGE_SIZE / se_size);
+	/* Set max number of entries to size of physical ram */
+	swapped.maxcount = total_memory;
 	/* Set maximum amount of mapped pages to prefetch to 2/3 ram */
 	mapped_limit = total_memory / 3 * 2;
 
@@ -221,13 +222,13 @@ static int trickle_swap_cache_async(swp_
 	struct page *page = NULL;
 	int ret = 0;
 
-	/* Entry may already exist */
-	if (unlikely(!read_trylock(swapped.rwlock))) {
+	if (unlikely(!read_trylock(&swapper_space.tree_lock))) {
 		ret = -1;
 		goto out;
 	}
+	/* Entry may already exist */
 	page = radix_tree_lookup(&swapper_space.page_tree, entry.val);
-	read_unlock(swapped.rwlock);
+	read_unlock(&swapper_space.tree_lock);
 	if (page) {
 		remove_from_swapped_list(entry.val);
 		goto out;
@@ -246,7 +247,6 @@ static int trickle_swap_cache_async(swp_
 		goto out;
 	}
 
-	lru_cache_add(page);
 	if (unlikely(swap_readpage(NULL, page))) {
 		ret = -1;
 		goto out;
@@ -270,17 +270,35 @@ static int prefetch_suitable(void)
 	if (__test_and_clear_bit(0, &swapped.busy))
 		goto out;
 
+	temp_free = 0;
 	/*
 	 * Have some hysteresis between where page reclaiming and prefetching
 	 * will occur to prevent ping-ponging between them.
 	 */
 	for_each_zone(z) {
+		unsigned long free;
+
 		if (z->present_pages == 0)
 			continue;
-		if (z->pages_high * 3 > z->free_pages)
+		free = z->free_pages;
+		if (z->pages_high * 3 > free)
 			goto out;
+		temp_free += free;
 	}
 
+	/*
+	 * We check to see that pages are not being allocated elsewhere
+	 * at any significant rate implying any degree of memory pressure
+	 * (eg during file reads)
+	 */
+	if (last_free) {
+		if (temp_free + SWAP_CLUSTER_MAX * 2 < last_free) {
+			last_free = temp_free;
+			goto out;
+		}
+	} else
+		last_free = temp_free;
+
 	get_page_state(&ps);
 
 	/* We shouldn't prefetch when we are doing writeback */
@@ -348,6 +366,7 @@ static int trickle_swap(void)
 			goto out;
 		pages += got_page;
 	}
+	last_free = temp_free;
 	return 1;
 
 out_unlock:
@@ -362,6 +381,8 @@ static int kprefetchd(void *data)
 
 	daemonize("kprefetchd");
 	set_user_nice(current, 19);
+	/* Set ioprio to lowest if supported by i/o scheduler */
+	sys_ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_CLASS_IDLE);
 
 	for ( ; ; ) {
 		int prefetched;
@@ -372,9 +393,10 @@ static int kprefetchd(void *data)
 		finish_wait(&kprefetchd_wait, &wait);
 
 		/* If trickle_swap() returns -1 the timer is not reset */
-		if (!(prefetched = trickle_swap()))
+		if (!(prefetched = trickle_swap())) {
+			last_free = 0;
 			delay_prefetch_timer();
-		else if (prefetched == 1)
+		} else if (prefetched == 1)
 			reset_prefetch_timer();
 	}
 	return 0;
