diff options
-rw-r--r-- | mm/swap.c | 41 |
1 files changed, 39 insertions, 2 deletions
@@ -432,6 +432,33 @@ void activate_page(struct page *page) | |||
432 | } | 432 | } |
433 | #endif | 433 | #endif |
434 | 434 | ||
435 | static 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) | |||
442 | void mark_page_accessed(struct page *page) | 469 | void 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); |