diff options
Diffstat (limited to 'mm/swap_state.c')
-rw-r--r-- | mm/swap_state.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/mm/swap_state.c b/mm/swap_state.c index d8aadaf2a0ba..b8035b055129 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,7 +56,8 @@ 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 = %lukB\n", nr_swap_pages << (PAGE_SHIFT - 10)); |
@@ -64,7 +65,7 @@ void show_swap_cache_info(void) | |||
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); |