aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/swap.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/mm/swap.c b/mm/swap.c
index 868b493431c2..c53d161fc76d 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -432,6 +432,33 @@ void activate_page(struct page *page)
432} 432}
433#endif 433#endif
434 434
435static void __lru_cache_activate_page(struct page *page)
436{
437 struct pagevec *pvec = &get_cpu_var(lru_add_pvec);
438 int i;
439
440 /*
441 * Search backwards on the optimistic assumption that the page being
442 * activated has just been added to this pagevec. Note that only
443 * the local pagevec is examined as a !PageLRU page could be in the
444 * process of being released, reclaimed, migrated or on a remote
445 * pagevec that is currently being drained. Furthermore, marking
446 * a remote pagevec's page PageActive potentially hits a race where
447 * a page is marked PageActive just after it is added to the inactive
448 * list causing accounting errors and BUG_ON checks to trigger.
449 */
450 for (i = pagevec_count(pvec) - 1; i >= 0; i--) {
451 struct page *pagevec_page = pvec->pages[i];
452
453 if (pagevec_page == page) {
454 SetPageActive(page);
455 break;
456 }
457 }
458
459 put_cpu_var(lru_add_pvec);
460}
461
435/* 462/*
436 * Mark a page as having seen activity. 463 * Mark a page as having seen activity.
437 * 464 *
@@ -442,8 +469,18 @@ void activate_page(struct page *page)
442void mark_page_accessed(struct page *page) 469void mark_page_accessed(struct page *page)
443{ 470{
444 if (!PageActive(page) && !PageUnevictable(page) && 471 if (!PageActive(page) && !PageUnevictable(page) &&
445 PageReferenced(page) && PageLRU(page)) { 472 PageReferenced(page)) {
446 activate_page(page); 473
474 /*
475 * If the page is on the LRU, queue it for activation via
476 * activate_page_pvecs. Otherwise, assume the page is on a
477 * pagevec, mark it active and it'll be moved to the active
478 * LRU on the next drain.
479 */
480 if (PageLRU(page))
481 activate_page(page);
482 else
483 __lru_cache_activate_page(page);
447 ClearPageReferenced(page); 484 ClearPageReferenced(page);
448 } else if (!PageReferenced(page)) { 485 } else if (!PageReferenced(page)) {
449 SetPageReferenced(page); 486 SetPageReferenced(page);