diff options
-rw-r--r-- | include/linux/pagevec.h | 13 | ||||
-rw-r--r-- | include/linux/swap.h | 18 | ||||
-rw-r--r-- | mm/migrate.c | 11 | ||||
-rw-r--r-- | mm/swap.c | 79 |
4 files changed, 55 insertions, 66 deletions
diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h index 8eb7fa76c1d0..6b8f11bcc948 100644 --- a/include/linux/pagevec.h +++ b/include/linux/pagevec.h | |||
@@ -23,8 +23,7 @@ struct pagevec { | |||
23 | void __pagevec_release(struct pagevec *pvec); | 23 | void __pagevec_release(struct pagevec *pvec); |
24 | void __pagevec_release_nonlru(struct pagevec *pvec); | 24 | void __pagevec_release_nonlru(struct pagevec *pvec); |
25 | void __pagevec_free(struct pagevec *pvec); | 25 | void __pagevec_free(struct pagevec *pvec); |
26 | void __pagevec_lru_add(struct pagevec *pvec); | 26 | void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru); |
27 | void __pagevec_lru_add_active(struct pagevec *pvec); | ||
28 | void pagevec_strip(struct pagevec *pvec); | 27 | void pagevec_strip(struct pagevec *pvec); |
29 | unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, | 28 | unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, |
30 | pgoff_t start, unsigned nr_pages); | 29 | pgoff_t start, unsigned nr_pages); |
@@ -81,6 +80,16 @@ static inline void pagevec_free(struct pagevec *pvec) | |||
81 | __pagevec_free(pvec); | 80 | __pagevec_free(pvec); |
82 | } | 81 | } |
83 | 82 | ||
83 | static inline void __pagevec_lru_add(struct pagevec *pvec) | ||
84 | { | ||
85 | ____pagevec_lru_add(pvec, LRU_INACTIVE); | ||
86 | } | ||
87 | |||
88 | static inline void __pagevec_lru_add_active(struct pagevec *pvec) | ||
89 | { | ||
90 | ____pagevec_lru_add(pvec, LRU_ACTIVE); | ||
91 | } | ||
92 | |||
84 | static inline void pagevec_lru_add(struct pagevec *pvec) | 93 | static inline void pagevec_lru_add(struct pagevec *pvec) |
85 | { | 94 | { |
86 | if (pagevec_count(pvec)) | 95 | if (pagevec_count(pvec)) |
diff --git a/include/linux/swap.h b/include/linux/swap.h index de40f169a4e4..fcc169610d09 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -171,8 +171,8 @@ extern unsigned int nr_free_pagecache_pages(void); | |||
171 | 171 | ||
172 | 172 | ||
173 | /* linux/mm/swap.c */ | 173 | /* linux/mm/swap.c */ |
174 | extern void lru_cache_add(struct page *); | 174 | extern void __lru_cache_add(struct page *, enum lru_list lru); |
175 | extern void lru_cache_add_active(struct page *); | 175 | extern void lru_cache_add_lru(struct page *, enum lru_list lru); |
176 | extern void activate_page(struct page *); | 176 | extern void activate_page(struct page *); |
177 | extern void mark_page_accessed(struct page *); | 177 | extern void mark_page_accessed(struct page *); |
178 | extern void lru_add_drain(void); | 178 | extern void lru_add_drain(void); |
@@ -180,6 +180,20 @@ extern int lru_add_drain_all(void); | |||
180 | extern void rotate_reclaimable_page(struct page *page); | 180 | extern void rotate_reclaimable_page(struct page *page); |
181 | extern void swap_setup(void); | 181 | extern void swap_setup(void); |
182 | 182 | ||
183 | /** | ||
184 | * lru_cache_add: add a page to the page lists | ||
185 | * @page: the page to add | ||
186 | */ | ||
187 | static inline void lru_cache_add(struct page *page) | ||
188 | { | ||
189 | __lru_cache_add(page, LRU_INACTIVE); | ||
190 | } | ||
191 | |||
192 | static inline void lru_cache_add_active(struct page *page) | ||
193 | { | ||
194 | __lru_cache_add(page, LRU_ACTIVE); | ||
195 | } | ||
196 | |||
183 | /* linux/mm/vmscan.c */ | 197 | /* linux/mm/vmscan.c */ |
184 | extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, | 198 | extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, |
185 | gfp_t gfp_mask); | 199 | gfp_t gfp_mask); |
diff --git a/mm/migrate.c b/mm/migrate.c index da73742e52a5..ad15b5ef2599 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -55,16 +55,7 @@ int migrate_prep(void) | |||
55 | 55 | ||
56 | static inline void move_to_lru(struct page *page) | 56 | static inline void move_to_lru(struct page *page) |
57 | { | 57 | { |
58 | if (PageActive(page)) { | 58 | lru_cache_add_lru(page, page_lru(page)); |
59 | /* | ||
60 | * lru_cache_add_active checks that | ||
61 | * the PG_active bit is off. | ||
62 | */ | ||
63 | ClearPageActive(page); | ||
64 | lru_cache_add_active(page); | ||
65 | } else { | ||
66 | lru_cache_add(page); | ||
67 | } | ||
68 | put_page(page); | 59 | put_page(page); |
69 | } | 60 | } |
70 | 61 | ||
@@ -34,8 +34,7 @@ | |||
34 | /* How many pages do we try to swap or page in/out together? */ | 34 | /* How many pages do we try to swap or page in/out together? */ |
35 | int page_cluster; | 35 | int page_cluster; |
36 | 36 | ||
37 | static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs); | 37 | static DEFINE_PER_CPU(struct pagevec[NR_LRU_LISTS], lru_add_pvecs); |
38 | static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs); | ||
39 | static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs); | 38 | static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs); |
40 | 39 | ||
41 | /* | 40 | /* |
@@ -186,28 +185,29 @@ void mark_page_accessed(struct page *page) | |||
186 | 185 | ||
187 | EXPORT_SYMBOL(mark_page_accessed); | 186 | EXPORT_SYMBOL(mark_page_accessed); |
188 | 187 | ||
189 | /** | 188 | void __lru_cache_add(struct page *page, enum lru_list lru) |
190 | * lru_cache_add: add a page to the page lists | ||
191 | * @page: the page to add | ||
192 | */ | ||
193 | void lru_cache_add(struct page *page) | ||
194 | { | 189 | { |
195 | struct pagevec *pvec = &get_cpu_var(lru_add_pvecs); | 190 | struct pagevec *pvec = &get_cpu_var(lru_add_pvecs)[lru]; |
196 | 191 | ||
197 | page_cache_get(page); | 192 | page_cache_get(page); |
198 | if (!pagevec_add(pvec, page)) | 193 | if (!pagevec_add(pvec, page)) |
199 | __pagevec_lru_add(pvec); | 194 | ____pagevec_lru_add(pvec, lru); |
200 | put_cpu_var(lru_add_pvecs); | 195 | put_cpu_var(lru_add_pvecs); |
201 | } | 196 | } |
202 | 197 | ||
203 | void lru_cache_add_active(struct page *page) | 198 | /** |
199 | * lru_cache_add_lru - add a page to a page list | ||
200 | * @page: the page to be added to the LRU. | ||
201 | * @lru: the LRU list to which the page is added. | ||
202 | */ | ||
203 | void lru_cache_add_lru(struct page *page, enum lru_list lru) | ||
204 | { | 204 | { |
205 | struct pagevec *pvec = &get_cpu_var(lru_add_active_pvecs); | 205 | if (PageActive(page)) { |
206 | ClearPageActive(page); | ||
207 | } | ||
206 | 208 | ||
207 | page_cache_get(page); | 209 | VM_BUG_ON(PageLRU(page) || PageActive(page)); |
208 | if (!pagevec_add(pvec, page)) | 210 | __lru_cache_add(page, lru); |
209 | __pagevec_lru_add_active(pvec); | ||
210 | put_cpu_var(lru_add_active_pvecs); | ||
211 | } | 211 | } |
212 | 212 | ||
213 | /* | 213 | /* |
@@ -217,15 +217,15 @@ void lru_cache_add_active(struct page *page) | |||
217 | */ | 217 | */ |
218 | static void drain_cpu_pagevecs(int cpu) | 218 | static void drain_cpu_pagevecs(int cpu) |
219 | { | 219 | { |
220 | struct pagevec *pvecs = per_cpu(lru_add_pvecs, cpu); | ||
220 | struct pagevec *pvec; | 221 | struct pagevec *pvec; |
222 | int lru; | ||
221 | 223 | ||
222 | pvec = &per_cpu(lru_add_pvecs, cpu); | 224 | for_each_lru(lru) { |
223 | if (pagevec_count(pvec)) | 225 | pvec = &pvecs[lru - LRU_BASE]; |
224 | __pagevec_lru_add(pvec); | 226 | if (pagevec_count(pvec)) |
225 | 227 | ____pagevec_lru_add(pvec, lru); | |
226 | pvec = &per_cpu(lru_add_active_pvecs, cpu); | 228 | } |
227 | if (pagevec_count(pvec)) | ||
228 | __pagevec_lru_add_active(pvec); | ||
229 | 229 | ||
230 | pvec = &per_cpu(lru_rotate_pvecs, cpu); | 230 | pvec = &per_cpu(lru_rotate_pvecs, cpu); |
231 | if (pagevec_count(pvec)) { | 231 | if (pagevec_count(pvec)) { |
@@ -380,7 +380,7 @@ void __pagevec_release_nonlru(struct pagevec *pvec) | |||
380 | * Add the passed pages to the LRU, then drop the caller's refcount | 380 | * Add the passed pages to the LRU, then drop the caller's refcount |
381 | * on them. Reinitialises the caller's pagevec. | 381 | * on them. Reinitialises the caller's pagevec. |
382 | */ | 382 | */ |
383 | void __pagevec_lru_add(struct pagevec *pvec) | 383 | void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru) |
384 | { | 384 | { |
385 | int i; | 385 | int i; |
386 | struct zone *zone = NULL; | 386 | struct zone *zone = NULL; |
@@ -397,7 +397,9 @@ void __pagevec_lru_add(struct pagevec *pvec) | |||
397 | } | 397 | } |
398 | VM_BUG_ON(PageLRU(page)); | 398 | VM_BUG_ON(PageLRU(page)); |
399 | SetPageLRU(page); | 399 | SetPageLRU(page); |
400 | add_page_to_inactive_list(zone, page); | 400 | if (is_active_lru(lru)) |
401 | SetPageActive(page); | ||
402 | add_page_to_lru_list(zone, page, lru); | ||
401 | } | 403 | } |
402 | if (zone) | 404 | if (zone) |
403 | spin_unlock_irq(&zone->lru_lock); | 405 | spin_unlock_irq(&zone->lru_lock); |
@@ -405,34 +407,7 @@ void __pagevec_lru_add(struct pagevec *pvec) | |||
405 | pagevec_reinit(pvec); | 407 | pagevec_reinit(pvec); |
406 | } | 408 | } |
407 | 409 | ||
408 | EXPORT_SYMBOL(__pagevec_lru_add); | 410 | EXPORT_SYMBOL(____pagevec_lru_add); |
409 | |||
410 | void __pagevec_lru_add_active(struct pagevec *pvec) | ||
411 | { | ||
412 | int i; | ||
413 | struct zone *zone = NULL; | ||
414 | |||
415 | for (i = 0; i < pagevec_count(pvec); i++) { | ||
416 | struct page *page = pvec->pages[i]; | ||
417 | struct zone *pagezone = page_zone(page); | ||
418 | |||
419 | if (pagezone != zone) { | ||
420 | if (zone) | ||
421 | spin_unlock_irq(&zone->lru_lock); | ||
422 | zone = pagezone; | ||
423 | spin_lock_irq(&zone->lru_lock); | ||
424 | } | ||
425 | VM_BUG_ON(PageLRU(page)); | ||
426 | SetPageLRU(page); | ||
427 | VM_BUG_ON(PageActive(page)); | ||
428 | SetPageActive(page); | ||
429 | add_page_to_active_list(zone, page); | ||
430 | } | ||
431 | if (zone) | ||
432 | spin_unlock_irq(&zone->lru_lock); | ||
433 | release_pages(pvec->pages, pvec->nr, pvec->cold); | ||
434 | pagevec_reinit(pvec); | ||
435 | } | ||
436 | 411 | ||
437 | /* | 412 | /* |
438 | * Try to drop buffers from the pages in a pagevec | 413 | * Try to drop buffers from the pages in a pagevec |