|
@@ -4512,10 +4512,13 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp
|
|
|
int scanned;
|
|
|
int reclaimed;
|
|
|
LIST_HEAD(list);
|
|
|
+ LIST_HEAD(clean);
|
|
|
struct page *page;
|
|
|
+ struct page *next;
|
|
|
enum vm_event_item item;
|
|
|
struct reclaim_stat stat;
|
|
|
struct lru_gen_mm_walk *walk;
|
|
|
+ bool skip_retry = false;
|
|
|
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
|
|
|
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
|
|
|
|
|
@@ -4532,20 +4535,37 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp
|
|
|
|
|
|
if (list_empty(&list))
|
|
|
return scanned;
|
|
|
-
|
|
|
+retry:
|
|
|
reclaimed = shrink_page_list(&list, pgdat, sc, &stat, false);
|
|
|
+ sc->nr_reclaimed += reclaimed;
|
|
|
|
|
|
- list_for_each_entry(page, &list, lru) {
|
|
|
- /* restore LRU_REFS_FLAGS cleared by isolate_page() */
|
|
|
- if (PageWorkingset(page))
|
|
|
- SetPageReferenced(page);
|
|
|
+ list_for_each_entry_safe_reverse(page, next, &list, lru) {
|
|
|
+ if (!page_evictable(page)) {
|
|
|
+ list_del(&page->lru);
|
|
|
+ putback_lru_page(page);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- /* don't add rejected pages to the oldest generation */
|
|
|
if (PageReclaim(page) &&
|
|
|
- (PageDirty(page) || PageWriteback(page)))
|
|
|
- ClearPageActive(page);
|
|
|
- else
|
|
|
- SetPageActive(page);
|
|
|
+ (PageDirty(page) || PageWriteback(page))) {
|
|
|
+ /* restore LRU_REFS_FLAGS cleared by isolate_page() */
|
|
|
+ if (PageWorkingset(page))
|
|
|
+ SetPageReferenced(page);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (skip_retry || PageActive(page) || PageReferenced(page) ||
|
|
|
+ page_mapped(page) || PageLocked(page) ||
|
|
|
+ PageDirty(page) || PageWriteback(page)) {
|
|
|
+ /* don't add rejected pages to the oldest generation */
|
|
|
+ set_mask_bits(&page->flags, LRU_REFS_MASK | LRU_REFS_FLAGS,
|
|
|
+ BIT(PG_active));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* retry pages that may have missed page_rotate_reclaimable() */
|
|
|
+ list_move(&page->lru, &clean);
|
|
|
+ sc->nr_scanned -= compound_nr(page);
|
|
|
}
|
|
|
|
|
|
spin_lock_irq(&pgdat->lru_lock);
|
|
@@ -4567,7 +4587,13 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp
|
|
|
mem_cgroup_uncharge_list(&list);
|
|
|
free_unref_page_list(&list);
|
|
|
|
|
|
- sc->nr_reclaimed += reclaimed;
|
|
|
+ INIT_LIST_HEAD(&list);
|
|
|
+ list_splice_init(&clean, &list);
|
|
|
+
|
|
|
+ if (!list_empty(&list)) {
|
|
|
+ skip_retry = true;
|
|
|
+ goto retry;
|
|
|
+ }
|
|
|
|
|
|
if (need_swapping && type == LRU_GEN_ANON)
|
|
|
*need_swapping = true;
|