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; }