Index: linux-2.6.13-ck7/Documentation/sysctl/vm.txt
===================================================================
--- linux-2.6.13-ck7.orig/Documentation/sysctl/vm.txt	2005-03-02 18:38:17.000000000 +1100
+++ linux-2.6.13-ck7/Documentation/sysctl/vm.txt	2005-10-06 23:10:54.000000000 +1000
@@ -26,6 +26,7 @@ Currently, these files are in /proc/sys/
 - min_free_kbytes
 - laptop_mode
 - block_dump
+- swap_prefetch
 
 ==============================================================
 
@@ -102,3 +103,14 @@ This is used to force the Linux VM to ke
 of kilobytes free.  The VM uses this number to compute a pages_min
 value for each lowmem zone in the system.  Each lowmem zone gets 
 a number of reserved free pages based proportionally on its size.
+
+==============================================================
+
+swap_prefetch
+
+This is the amount of data prefetched per prefetching interval when
+swap prefetching is compiled in. The value means multiples of 128K,
+except when laptop_mode is enabled and then it is ten times larger.
+Setting it to 0 disables prefetching entirely.
+
+The default value is 2.
Index: linux-2.6.13-ck7/mm/swap_prefetch.c
===================================================================
--- linux-2.6.13-ck7.orig/mm/swap_prefetch.c	2005-10-06 13:00:52.000000000 +1000
+++ linux-2.6.13-ck7/mm/swap_prefetch.c	2005-10-06 23:11:39.000000000 +1000
@@ -15,13 +15,23 @@
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
 #include <linux/ioprio.h>
+#include <linux/writeback.h>
 
 /* Time to delay prefetching if vm is busy or prefetching unsuccessful */
 #define PREFETCH_DELAY	(HZ * 5)
 /* 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 */
+/* sysctl - if/how much to prefetch at a time */
+int swap_prefetch = 2;
+
+/*
+ * How many pages to prefetch at a time. We prefetch SWAP_CLUSTER_MAX *
+ * swap_prefetch per PREFETCH_INTERVAL, but prefetch ten times as much at a
+ * time in laptop_mode to minimise the time we keep the disk spinning.
+ */
+#define PREFETCH_PAGES()	(SWAP_CLUSTER_MAX * swap_prefetch * \
+					(1 + 9 * laptop_mode))
 
 struct swapped_root_t {
 	unsigned long		busy;		/* vm busy */
@@ -243,13 +253,13 @@ static int trickle_swap_cache_async(swp_
 		/* Failed to add to swap cache */
 		goto out_release;
 
+	lru_cache_add(page);
 	if (unlikely(swap_readpage(NULL, page))) {
 		ret = -1;
 		goto out_release;
 	}
 
 	ret = 1;
-
 out_release:
 	page_cache_release(page);
 out:
@@ -292,7 +302,7 @@ static int prefetch_suitable(void)
 	 * (eg during file reads)
 	 */
 	if (last_free) {
-		if (temp_free + SWAP_CLUSTER_MAX * (swap_prefetch + 1) <
+		if (temp_free + SWAP_CLUSTER_MAX + PREFETCH_PAGES() <
 			last_free) {
 				last_free = temp_free;
 				goto out;
@@ -337,7 +347,7 @@ 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 * swap_prefetch is prefetched.
+ * Otherwise it runs till PREFETCH_PAGES() are 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.
  */
@@ -346,7 +356,7 @@ static int trickle_swap(void)
 	int ret = 0, pages = 0;
 	struct swapped_entry_t *entry;
 
-	while (pages < SWAP_CLUSTER_MAX * swap_prefetch) {
+	while (pages < PREFETCH_PAGES()) {
 		int got_page;
 
 		if (!prefetch_suitable())
@@ -355,8 +365,9 @@ static int trickle_swap(void)
 		if (unlikely(!spin_trylock(&swapped.lock)))
 			goto out;
 		if (list_empty(&swapped.list)) {
+			spin_unlock(&swapped.lock);
 			ret = -1;
-			goto out_unlock;
+			goto out;
 		}
 		entry = list_entry(swapped.list.next,
 			struct swapped_entry_t, swapped_list);
@@ -367,11 +378,11 @@ static int trickle_swap(void)
 			goto out;
 		pages += got_page;
 	}
-	return 1;
+	ret = 1;
 
-out_unlock:
-	spin_unlock(&swapped.lock);
 out:
+	if (pages)
+		lru_add_drain();
 	return ret;
 }
 
