summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/swap.h3
-rw-r--r--mm/swap.c11
-rw-r--r--mm/swap_state.c5
-rw-r--r--mm/vmscan.c39
-rw-r--r--mm/workingset.c4
5 files changed, 27 insertions, 35 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h
index ce3c55747006..0b71bf75fb67 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -334,8 +334,7 @@ extern unsigned long nr_free_pagecache_pages(void);
/* linux/mm/swap.c */
-extern void lru_note_cost(struct lruvec *lruvec, bool file,
- unsigned int nr_pages);
+extern void lru_note_cost(struct page *);
extern void lru_cache_add(struct page *);
extern void lru_add_page_tail(struct page *page, struct page *page_tail,
struct lruvec *lruvec, struct list_head *head);
diff --git a/mm/swap.c b/mm/swap.c
index 7d552af25797..2dc7d392642f 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -278,12 +278,15 @@ void rotate_reclaimable_page(struct page *page)
}
}
-void lru_note_cost(struct lruvec *lruvec, bool file, unsigned int nr_pages)
+void lru_note_cost(struct page *page)
{
- if (file)
- lruvec->file_cost += nr_pages;
+ struct lruvec *lruvec = mem_cgroup_page_lruvec(page, page_pgdat(page));
+
+ /* Record new data point */
+ if (page_is_file_lru(page))
+ lruvec->file_cost++;
else
- lruvec->anon_cost += nr_pages;
+ lruvec->anon_cost++;
}
static void __activate_page(struct page *page, struct lruvec *lruvec,
diff --git a/mm/swap_state.c b/mm/swap_state.c
index fa089002125f..1cd0b345ff7e 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -440,6 +440,11 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
goto fail_unlock;
}
+ /* XXX: Move to lru_cache_add() when it supports new vs putback */
+ spin_lock_irq(&page_pgdat(page)->lru_lock);
+ lru_note_cost(page);
+ spin_unlock_irq(&page_pgdat(page)->lru_lock);
+
/* Caller will initiate read into locked page */
SetPageWorkingset(page);
lru_cache_add(page);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 3c89eac629f3..76e823db21a7 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1958,12 +1958,6 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
move_pages_to_lru(lruvec, &page_list);
__mod_node_page_state(pgdat, NR_ISOLATED_ANON + file, -nr_taken);
- /*
- * Rotating pages costs CPU without actually
- * progressing toward the reclaim goal.
- */
- lru_note_cost(lruvec, 0, stat.nr_activate[0]);
- lru_note_cost(lruvec, 1, stat.nr_activate[1]);
item = current_is_kswapd() ? PGSTEAL_KSWAPD : PGSTEAL_DIRECT;
if (!cgroup_reclaim(sc))
__count_vm_events(item, nr_reclaimed);
@@ -2079,11 +2073,6 @@ static void shrink_active_list(unsigned long nr_to_scan,
* Move pages back to the lru list.
*/
spin_lock_irq(&pgdat->lru_lock);
- /*
- * Rotating pages costs CPU without actually
- * progressing toward the reclaim goal.
- */
- lru_note_cost(lruvec, file, nr_rotated);
nr_activate = move_pages_to_lru(lruvec, &l_active);
nr_deactivate = move_pages_to_lru(lruvec, &l_inactive);
@@ -2298,22 +2287,23 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
scan_balance = SCAN_FRACT;
/*
- * With swappiness at 100, anonymous and file have the same priority.
- * This scanning priority is essentially the inverse of IO cost.
+ * Calculate the pressure balance between anon and file pages.
+ *
+ * The amount of pressure we put on each LRU is inversely
+ * proportional to the cost of reclaiming each list, as
+ * determined by the share of pages that are refaulting, times
+ * the relative IO cost of bringing back a swapped out
+ * anonymous page vs reloading a filesystem page (swappiness).
+ *
+ * With swappiness at 100, anon and file have equal IO cost.
*/
anon_prio = swappiness;
file_prio = 200 - anon_prio;
/*
- * OK, so we have swap space and a fair amount of page cache
- * pages. We use the recently rotated / recently scanned
- * ratios to determine how valuable each cache is.
- *
* Because workloads change over time (and to avoid overflow)
* we keep these statistics as a floating average, which ends
- * up weighing recent references more than old ones.
- *
- * anon in [0], file in [1]
+ * up weighing recent refaults more than old ones.
*/
anon = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON, MAX_NR_ZONES) +
@@ -2328,15 +2318,6 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
lruvec->file_cost /= 2;
totalcost /= 2;
}
-
- /*
- * The amount of pressure on anon vs file pages is inversely
- * proportional to the assumed cost of reclaiming each list,
- * as determined by the share of pages that are likely going
- * to refault or rotate on each list (recently referenced),
- * times the relative IO cost of bringing back a swapped out
- * anonymous page vs reloading a filesystem page (swappiness).
- */
ap = anon_prio * (totalcost + 1);
ap /= lruvec->anon_cost + 1;
diff --git a/mm/workingset.c b/mm/workingset.c
index e69865739539..a6a2a740ed0b 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -365,6 +365,10 @@ void workingset_refault(struct page *page, void *shadow)
/* Page was active prior to eviction */
if (workingset) {
SetPageWorkingset(page);
+ /* XXX: Move to lru_cache_add() when it supports new vs putback */
+ spin_lock_irq(&page_pgdat(page)->lru_lock);
+ lru_note_cost(page);
+ spin_unlock_irq(&page_pgdat(page)->lru_lock);
inc_lruvec_state(lruvec, WORKINGSET_RESTORE);
}
out: