diff options
author | Rik van Riel <riel@redhat.com> | 2012-03-21 19:33:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 20:54:56 -0400 |
commit | 67f96aa252e606cdf6c3cf1032952ec207ec0cf0 (patch) | |
tree | a5a4299dd32789831eda558b51c0120272846664 /mm/swapfile.c | |
parent | c38446cc65e1f2b3eb8630c53943b94c4f65f670 (diff) |
mm: make swapin readahead skip over holes
Ever since abandoning the virtual scan of processes, for scalability
reasons, swap space has been a little more fragmented than before. This
can lead to the situation where a large memory user is killed, swap space
ends up full of "holes" and swapin readahead is totally ineffective.
On my home system, after killing a leaky firefox it took over an hour to
page just under 2GB of memory back in, slowing the virtual machines down
to a crawl.
This patch makes swapin readahead simply skip over holes, instead of
stopping at them. This allows the system to swap things back in at rates
of several MB/second, instead of a few hundred kB/second.
The checks done in valid_swaphandles are already done in
read_swap_cache_async as well, allowing us to remove a fair amount of
code.
[akpm@linux-foundation.org: fix it for page_cluster >= 32]
Signed-off-by: Rik van Riel <riel@redhat.com>
Cc: Minchan Kim <minchan.kim@gmail.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Mel Gorman <mgorman@suse.de>
Cc: Adrian Drzewiecki <z@drze.net>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 52 |
1 files changed, 0 insertions, 52 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index 44595a373e42..b82c028cfcc6 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -2288,58 +2288,6 @@ int swapcache_prepare(swp_entry_t entry) | |||
2288 | } | 2288 | } |
2289 | 2289 | ||
2290 | /* | 2290 | /* |
2291 | * swap_lock prevents swap_map being freed. Don't grab an extra | ||
2292 | * reference on the swaphandle, it doesn't matter if it becomes unused. | ||
2293 | */ | ||
2294 | int valid_swaphandles(swp_entry_t entry, unsigned long *offset) | ||
2295 | { | ||
2296 | struct swap_info_struct *si; | ||
2297 | int our_page_cluster = page_cluster; | ||
2298 | pgoff_t target, toff; | ||
2299 | pgoff_t base, end; | ||
2300 | int nr_pages = 0; | ||
2301 | |||
2302 | if (!our_page_cluster) /* no readahead */ | ||
2303 | return 0; | ||
2304 | |||
2305 | si = swap_info[swp_type(entry)]; | ||
2306 | target = swp_offset(entry); | ||
2307 | base = (target >> our_page_cluster) << our_page_cluster; | ||
2308 | end = base + (1 << our_page_cluster); | ||
2309 | if (!base) /* first page is swap header */ | ||
2310 | base++; | ||
2311 | |||
2312 | spin_lock(&swap_lock); | ||
2313 | if (end > si->max) /* don't go beyond end of map */ | ||
2314 | end = si->max; | ||
2315 | |||
2316 | /* Count contiguous allocated slots above our target */ | ||
2317 | for (toff = target; ++toff < end; nr_pages++) { | ||
2318 | /* Don't read in free or bad pages */ | ||
2319 | if (!si->swap_map[toff]) | ||
2320 | break; | ||
2321 | if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD) | ||
2322 | break; | ||
2323 | } | ||
2324 | /* Count contiguous allocated slots below our target */ | ||
2325 | for (toff = target; --toff >= base; nr_pages++) { | ||
2326 | /* Don't read in free or bad pages */ | ||
2327 | if (!si->swap_map[toff]) | ||
2328 | break; | ||
2329 | if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD) | ||
2330 | break; | ||
2331 | } | ||
2332 | spin_unlock(&swap_lock); | ||
2333 | |||
2334 | /* | ||
2335 | * Indicate starting offset, and return number of pages to get: | ||
2336 | * if only 1, say 0, since there's then no readahead to be done. | ||
2337 | */ | ||
2338 | *offset = ++toff; | ||
2339 | return nr_pages? ++nr_pages: 0; | ||
2340 | } | ||
2341 | |||
2342 | /* | ||
2343 | * add_swap_count_continuation - called when a swap count is duplicated | 2291 | * add_swap_count_continuation - called when a swap count is duplicated |
2344 | * beyond SWAP_MAP_MAX, it allocates a new page and links that to the entry's | 2292 | * beyond SWAP_MAP_MAX, it allocates a new page and links that to the entry's |
2345 | * page of the original vmalloc'ed swap_map, to hold the continuation count | 2293 | * page of the original vmalloc'ed swap_map, to hold the continuation count |