diff options
Diffstat (limited to 'mm/swap.c')
-rw-r--r-- | mm/swap.c | 52 |
1 files changed, 47 insertions, 5 deletions
@@ -272,14 +272,10 @@ static void update_page_reclaim_stat(struct zone *zone, struct page *page, | |||
272 | memcg_reclaim_stat->recent_rotated[file]++; | 272 | memcg_reclaim_stat->recent_rotated[file]++; |
273 | } | 273 | } |
274 | 274 | ||
275 | /* | 275 | static void __activate_page(struct page *page, void *arg) |
276 | * FIXME: speed this up? | ||
277 | */ | ||
278 | void activate_page(struct page *page) | ||
279 | { | 276 | { |
280 | struct zone *zone = page_zone(page); | 277 | struct zone *zone = page_zone(page); |
281 | 278 | ||
282 | spin_lock_irq(&zone->lru_lock); | ||
283 | if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) { | 279 | if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) { |
284 | int file = page_is_file_cache(page); | 280 | int file = page_is_file_cache(page); |
285 | int lru = page_lru_base_type(page); | 281 | int lru = page_lru_base_type(page); |
@@ -292,8 +288,45 @@ void activate_page(struct page *page) | |||
292 | 288 | ||
293 | update_page_reclaim_stat(zone, page, file, 1); | 289 | update_page_reclaim_stat(zone, page, file, 1); |
294 | } | 290 | } |
291 | } | ||
292 | |||
293 | #ifdef CONFIG_SMP | ||
294 | static DEFINE_PER_CPU(struct pagevec, activate_page_pvecs); | ||
295 | |||
296 | static void activate_page_drain(int cpu) | ||
297 | { | ||
298 | struct pagevec *pvec = &per_cpu(activate_page_pvecs, cpu); | ||
299 | |||
300 | if (pagevec_count(pvec)) | ||
301 | pagevec_lru_move_fn(pvec, __activate_page, NULL); | ||
302 | } | ||
303 | |||
304 | void activate_page(struct page *page) | ||
305 | { | ||
306 | if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) { | ||
307 | struct pagevec *pvec = &get_cpu_var(activate_page_pvecs); | ||
308 | |||
309 | page_cache_get(page); | ||
310 | if (!pagevec_add(pvec, page)) | ||
311 | pagevec_lru_move_fn(pvec, __activate_page, NULL); | ||
312 | put_cpu_var(activate_page_pvecs); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | #else | ||
317 | static inline void activate_page_drain(int cpu) | ||
318 | { | ||
319 | } | ||
320 | |||
321 | void activate_page(struct page *page) | ||
322 | { | ||
323 | struct zone *zone = page_zone(page); | ||
324 | |||
325 | spin_lock_irq(&zone->lru_lock); | ||
326 | __activate_page(page, NULL); | ||
295 | spin_unlock_irq(&zone->lru_lock); | 327 | spin_unlock_irq(&zone->lru_lock); |
296 | } | 328 | } |
329 | #endif | ||
297 | 330 | ||
298 | /* | 331 | /* |
299 | * Mark a page as having seen activity. | 332 | * Mark a page as having seen activity. |
@@ -464,6 +497,8 @@ static void drain_cpu_pagevecs(int cpu) | |||
464 | pvec = &per_cpu(lru_deactivate_pvecs, cpu); | 497 | pvec = &per_cpu(lru_deactivate_pvecs, cpu); |
465 | if (pagevec_count(pvec)) | 498 | if (pagevec_count(pvec)) |
466 | pagevec_lru_move_fn(pvec, lru_deactivate_fn, NULL); | 499 | pagevec_lru_move_fn(pvec, lru_deactivate_fn, NULL); |
500 | |||
501 | activate_page_drain(cpu); | ||
467 | } | 502 | } |
468 | 503 | ||
469 | /** | 504 | /** |
@@ -476,6 +511,13 @@ static void drain_cpu_pagevecs(int cpu) | |||
476 | */ | 511 | */ |
477 | void deactivate_page(struct page *page) | 512 | void deactivate_page(struct page *page) |
478 | { | 513 | { |
514 | /* | ||
515 | * In a workload with many unevictable page such as mprotect, unevictable | ||
516 | * page deactivation for accelerating reclaim is pointless. | ||
517 | */ | ||
518 | if (PageUnevictable(page)) | ||
519 | return; | ||
520 | |||
479 | if (likely(get_page_unless_zero(page))) { | 521 | if (likely(get_page_unless_zero(page))) { |
480 | struct pagevec *pvec = &get_cpu_var(lru_deactivate_pvecs); | 522 | struct pagevec *pvec = &get_cpu_var(lru_deactivate_pvecs); |
481 | 523 | ||