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 #include #include +#include /* 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; }