diff options
Diffstat (limited to 'mm/swap_state.c')
-rw-r--r-- | mm/swap_state.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/mm/swap_state.c b/mm/swap_state.c index d8aadaf2a0ba..797c3831cbec 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c | |||
@@ -39,7 +39,7 @@ static struct backing_dev_info swap_backing_dev_info = { | |||
39 | 39 | ||
40 | struct address_space swapper_space = { | 40 | struct address_space swapper_space = { |
41 | .page_tree = RADIX_TREE_INIT(GFP_ATOMIC|__GFP_NOWARN), | 41 | .page_tree = RADIX_TREE_INIT(GFP_ATOMIC|__GFP_NOWARN), |
42 | .tree_lock = __RW_LOCK_UNLOCKED(swapper_space.tree_lock), | 42 | .tree_lock = __SPIN_LOCK_UNLOCKED(swapper_space.tree_lock), |
43 | .a_ops = &swap_aops, | 43 | .a_ops = &swap_aops, |
44 | .i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear), | 44 | .i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear), |
45 | .backing_dev_info = &swap_backing_dev_info, | 45 | .backing_dev_info = &swap_backing_dev_info, |
@@ -56,15 +56,16 @@ static struct { | |||
56 | 56 | ||
57 | void show_swap_cache_info(void) | 57 | void show_swap_cache_info(void) |
58 | { | 58 | { |
59 | printk("Swap cache: add %lu, delete %lu, find %lu/%lu\n", | 59 | printk("%lu pages in swap cache\n", total_swapcache_pages); |
60 | printk("Swap cache stats: add %lu, delete %lu, find %lu/%lu\n", | ||
60 | swap_cache_info.add_total, swap_cache_info.del_total, | 61 | swap_cache_info.add_total, swap_cache_info.del_total, |
61 | swap_cache_info.find_success, swap_cache_info.find_total); | 62 | swap_cache_info.find_success, swap_cache_info.find_total); |
62 | printk("Free swap = %lukB\n", nr_swap_pages << (PAGE_SHIFT - 10)); | 63 | printk("Free swap = %ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10)); |
63 | printk("Total swap = %lukB\n", total_swap_pages << (PAGE_SHIFT - 10)); | 64 | printk("Total swap = %lukB\n", total_swap_pages << (PAGE_SHIFT - 10)); |
64 | } | 65 | } |
65 | 66 | ||
66 | /* | 67 | /* |
67 | * add_to_swap_cache resembles add_to_page_cache on swapper_space, | 68 | * add_to_swap_cache resembles add_to_page_cache_locked on swapper_space, |
68 | * but sets SwapCache flag and private instead of mapping and index. | 69 | * but sets SwapCache flag and private instead of mapping and index. |
69 | */ | 70 | */ |
70 | int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp_mask) | 71 | int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp_mask) |
@@ -76,19 +77,26 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp_mask) | |||
76 | BUG_ON(PagePrivate(page)); | 77 | BUG_ON(PagePrivate(page)); |
77 | error = radix_tree_preload(gfp_mask); | 78 | error = radix_tree_preload(gfp_mask); |
78 | if (!error) { | 79 | if (!error) { |
79 | write_lock_irq(&swapper_space.tree_lock); | 80 | page_cache_get(page); |
81 | SetPageSwapCache(page); | ||
82 | set_page_private(page, entry.val); | ||
83 | |||
84 | spin_lock_irq(&swapper_space.tree_lock); | ||
80 | error = radix_tree_insert(&swapper_space.page_tree, | 85 | error = radix_tree_insert(&swapper_space.page_tree, |
81 | entry.val, page); | 86 | entry.val, page); |
82 | if (!error) { | 87 | if (likely(!error)) { |
83 | page_cache_get(page); | ||
84 | SetPageSwapCache(page); | ||
85 | set_page_private(page, entry.val); | ||
86 | total_swapcache_pages++; | 88 | total_swapcache_pages++; |
87 | __inc_zone_page_state(page, NR_FILE_PAGES); | 89 | __inc_zone_page_state(page, NR_FILE_PAGES); |
88 | INC_CACHE_INFO(add_total); | 90 | INC_CACHE_INFO(add_total); |
89 | } | 91 | } |
90 | write_unlock_irq(&swapper_space.tree_lock); | 92 | spin_unlock_irq(&swapper_space.tree_lock); |
91 | radix_tree_preload_end(); | 93 | radix_tree_preload_end(); |
94 | |||
95 | if (unlikely(error)) { | ||
96 | set_page_private(page, 0UL); | ||
97 | ClearPageSwapCache(page); | ||
98 | page_cache_release(page); | ||
99 | } | ||
92 | } | 100 | } |
93 | return error; | 101 | return error; |
94 | } | 102 | } |
@@ -175,9 +183,9 @@ void delete_from_swap_cache(struct page *page) | |||
175 | 183 | ||
176 | entry.val = page_private(page); | 184 | entry.val = page_private(page); |
177 | 185 | ||
178 | write_lock_irq(&swapper_space.tree_lock); | 186 | spin_lock_irq(&swapper_space.tree_lock); |
179 | __delete_from_swap_cache(page); | 187 | __delete_from_swap_cache(page); |
180 | write_unlock_irq(&swapper_space.tree_lock); | 188 | spin_unlock_irq(&swapper_space.tree_lock); |
181 | 189 | ||
182 | swap_free(entry); | 190 | swap_free(entry); |
183 | page_cache_release(page); | 191 | page_cache_release(page); |
@@ -193,7 +201,7 @@ void delete_from_swap_cache(struct page *page) | |||
193 | */ | 201 | */ |
194 | static inline void free_swap_cache(struct page *page) | 202 | static inline void free_swap_cache(struct page *page) |
195 | { | 203 | { |
196 | if (PageSwapCache(page) && !TestSetPageLocked(page)) { | 204 | if (PageSwapCache(page) && trylock_page(page)) { |
197 | remove_exclusive_swap_page(page); | 205 | remove_exclusive_swap_page(page); |
198 | unlock_page(page); | 206 | unlock_page(page); |
199 | } | 207 | } |
@@ -294,9 +302,9 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, | |||
294 | * re-using the just freed swap entry for an existing page. | 302 | * re-using the just freed swap entry for an existing page. |
295 | * May fail (-ENOMEM) if radix-tree node allocation failed. | 303 | * May fail (-ENOMEM) if radix-tree node allocation failed. |
296 | */ | 304 | */ |
297 | SetPageLocked(new_page); | 305 | set_page_locked(new_page); |
298 | err = add_to_swap_cache(new_page, entry, gfp_mask & GFP_KERNEL); | 306 | err = add_to_swap_cache(new_page, entry, gfp_mask & GFP_KERNEL); |
299 | if (!err) { | 307 | if (likely(!err)) { |
300 | /* | 308 | /* |
301 | * Initiate read into locked page and return. | 309 | * Initiate read into locked page and return. |
302 | */ | 310 | */ |
@@ -304,7 +312,7 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, | |||
304 | swap_readpage(NULL, new_page); | 312 | swap_readpage(NULL, new_page); |
305 | return new_page; | 313 | return new_page; |
306 | } | 314 | } |
307 | ClearPageLocked(new_page); | 315 | clear_page_locked(new_page); |
308 | swap_free(entry); | 316 | swap_free(entry); |
309 | } while (err != -ENOMEM); | 317 | } while (err != -ENOMEM); |
310 | 318 | ||