Index: linux-2.6.13-sp/include/linux/swap.h
===================================================================
--- linux-2.6.13-sp.orig/include/linux/swap.h	2005-10-05 22:48:41.000000000 +1000
+++ linux-2.6.13-sp/include/linux/swap.h	2005-10-05 22:49:34.000000000 +1000
@@ -196,6 +196,7 @@ extern void delay_prefetch(void);
 extern struct page *
 buffered_rmqueue(struct zone *zone, int order, unsigned int __nocast gfp_flags);
 extern void zone_statistics(struct zonelist *zonelist, struct zone *z);
+extern int swap_prefetch;
 
 #else	/* CONFIG_SWAP_PREFETCH */
 static inline void add_to_swapped_list(unsigned long index)
Index: linux-2.6.13-sp/include/linux/sysctl.h
===================================================================
--- linux-2.6.13-sp.orig/include/linux/sysctl.h	2005-10-05 22:48:23.000000000 +1000
+++ linux-2.6.13-sp/include/linux/sysctl.h	2005-10-05 22:49:34.000000000 +1000
@@ -180,6 +180,7 @@ enum
 	VM_VFS_CACHE_PRESSURE=26, /* dcache/icache reclaim pressure */
 	VM_LEGACY_VA_LAYOUT=27, /* legacy/compatibility virtual address space layout */
 	VM_SWAP_TOKEN_TIMEOUT=28, /* default time for token time out */
+	VM_SWAP_PREFETCH=29,	/* int: amount to swap prefetch */
 };
 
 
Index: linux-2.6.13-sp/init/Kconfig
===================================================================
--- linux-2.6.13-sp.orig/init/Kconfig	2005-10-05 22:48:41.000000000 +1000
+++ linux-2.6.13-sp/init/Kconfig	2005-10-05 22:49:34.000000000 +1000
@@ -89,7 +89,7 @@ config SWAP
 
 config SWAP_PREFETCH
 	bool "Support for prefetching swapped memory"
-	depends on SWAP && EXPERIMENTAL
+	depends on SWAP
 	default n
 	---help---
 	  This option will allow the kernel to prefetch swapped memory pages
Index: linux-2.6.13-sp/kernel/sysctl.c
===================================================================
--- linux-2.6.13-sp.orig/kernel/sysctl.c	2005-10-05 22:48:23.000000000 +1000
+++ linux-2.6.13-sp/kernel/sysctl.c	2005-10-05 22:49:34.000000000 +1000
@@ -850,6 +850,18 @@ static ctl_table vm_table[] = {
 		.proc_handler	= &proc_dointvec_jiffies,
 		.strategy	= &sysctl_jiffies,
 	},
+#ifdef CONFIG_SWAP_PREFETCH
+	{
+		.ctl_name	= VM_SWAP_PREFETCH,
+		.procname	= "swap_prefetch",
+		.data		= &swap_prefetch,
+		.maxlen		= sizeof(swap_prefetch),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
+#endif
 #endif
 	{ .ctl_name = 0 }
 };
Index: linux-2.6.13-sp/mm/swap_prefetch.c
===================================================================
--- linux-2.6.13-sp.orig/mm/swap_prefetch.c	2005-10-05 22:48:41.000000000 +1000
+++ linux-2.6.13-sp/mm/swap_prefetch.c	2005-10-05 22:49:34.000000000 +1000
@@ -21,6 +21,8 @@
 /* Time between attempting prefetching when vm is idle */
 #define PREFETCH_INTERVAL (HZ)
 
+int swap_prefetch = 2;	/* sysctl - if/how much to prefetch at a time */
+
 struct swapped_root_t {
 	unsigned long		busy;		/* vm busy */
 	spinlock_t		lock;		/* protects all data */
@@ -181,10 +183,6 @@ static struct page *prefetch_get_page(vo
 
 		free = z->free_pages;
 
-		/* Check yet again we are above watermarks, by now likely */
-		if (unlikely(free < z->pages_high * 3))
-			goto out;
-
 		/* We don't prefetch into DMA */
 		if (zone_idx(z) == ZONE_DMA)
 			continue;
@@ -241,17 +239,19 @@ static int trickle_swap_cache_async(swp_
 		goto out;
 	}
 
-	if (add_to_swap_cache(page, entry)) {
+	if (add_to_swap_cache(page, entry))
 		/* Failed to add to swap cache */
-		page_cache_release(page);
-		goto out;
-	}
+		goto out_release;
 
 	if (unlikely(swap_readpage(NULL, page))) {
 		ret = -1;
-		goto out;
+		goto out_release;
 	}
+
 	ret = 1;
+
+out_release:
+	page_cache_release(page);
 out:
 	return ret;
 }
@@ -292,9 +292,10 @@ static int prefetch_suitable(void)
 	 * (eg during file reads)
 	 */
 	if (last_free) {
-		if (temp_free + SWAP_CLUSTER_MAX * 2 < last_free) {
-			last_free = temp_free;
-			goto out;
+		if (temp_free + SWAP_CLUSTER_MAX * (swap_prefetch + 1) <
+			last_free) {
+				last_free = temp_free;
+				goto out;
 		}
 	} else
 		last_free = temp_free;
@@ -336,16 +337,16 @@ out:
  * trickle_swap is the main function that initiates the swap prefetching. It
  * first checks to see if the busy flag is set, and does not prefetch if it
  * is, as the flag implied we are low on memory or swapping in currently.
- * Otherwise it runs till SWAP_CLUSTER_MAX is prefetched. This function
- * returns 1 if it succeeds in a cycle of prefetching, 0 if it is interrupted
- * or -1 if there is nothing left to prefetch.
+ * Otherwise it runs till SWAP_CLUSTER_MAX * swap_prefetch is prefetched.
+ * This function returns 1 if it succeeds in a cycle of prefetching, 0 if it
+ * is interrupted or -1 if there is nothing left to prefetch.
  */
 static int trickle_swap(void)
 {
 	int ret = 0, pages = 0;
 	struct swapped_entry_t *entry;
 
-	while (pages < SWAP_CLUSTER_MAX) {
+	while (pages < SWAP_CLUSTER_MAX * swap_prefetch) {
 		int got_page;
 
 		if (!prefetch_suitable())
@@ -366,7 +367,6 @@ static int trickle_swap(void)
 			goto out;
 		pages += got_page;
 	}
-	last_free = temp_free;
 	return 1;
 
 out_unlock:
@@ -393,11 +393,15 @@ static int kprefetchd(void *data)
 		finish_wait(&kprefetchd_wait, &wait);
 
 		/* If trickle_swap() returns -1 the timer is not reset */
-		if (!(prefetched = trickle_swap())) {
-			last_free = 0;
-			delay_prefetch_timer();
-		} else if (prefetched == 1)
+		prefetched = trickle_swap();
+		if (prefetched == 1) {
+			last_free = temp_free;
 			reset_prefetch_timer();
+		} else {
+			last_free = 0;
+			if (!prefetched)
+				delay_prefetch_timer();
+		}
 	}
 	return 0;
 }
