summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/swap.h4
-rw-r--r--include/linux/vmstat.h1
-rw-r--r--mm/swap.c16
-rw-r--r--mm/swap_state.c2
-rw-r--r--mm/vmscan.c3
-rw-r--r--mm/workingset.c2
6 files changed, 19 insertions, 9 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 0b71bf75fb67..4c5974bb9ba9 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -334,7 +334,9 @@ extern unsigned long nr_free_pagecache_pages(void);
/* linux/mm/swap.c */
-extern void lru_note_cost(struct page *);
+extern void lru_note_cost(struct lruvec *lruvec, bool file,
+ unsigned int nr_pages);
+extern void lru_note_cost_page(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/include/linux/vmstat.h b/include/linux/vmstat.h
index 10cc932e209a..3d12c34cd42a 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -26,6 +26,7 @@ struct reclaim_stat {
unsigned nr_congested;
unsigned nr_writeback;
unsigned nr_immediate;
+ unsigned nr_pageout;
unsigned nr_activate[2];
unsigned nr_ref_keep;
unsigned nr_unmap_fail;
diff --git a/mm/swap.c b/mm/swap.c
index 4dff2123f695..343675d629ae 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -278,18 +278,16 @@ void rotate_reclaimable_page(struct page *page)
}
}
-void lru_note_cost(struct page *page)
+void lru_note_cost(struct lruvec *lruvec, bool file, unsigned int nr_pages)
{
- struct lruvec *lruvec = mem_cgroup_page_lruvec(page, page_pgdat(page));
-
do {
unsigned long lrusize;
/* Record cost event */
- if (page_is_file_lru(page))
- lruvec->file_cost++;
+ if (file)
+ lruvec->file_cost += nr_pages;
else
- lruvec->anon_cost++;
+ lruvec->anon_cost += nr_pages;
/*
* Decay previous events
@@ -311,6 +309,12 @@ void lru_note_cost(struct page *page)
} while ((lruvec = parent_lruvec(lruvec)));
}
+void lru_note_cost_page(struct page *page)
+{
+ lru_note_cost(mem_cgroup_page_lruvec(page, page_pgdat(page)),
+ page_is_file_lru(page), hpage_nr_pages(page));
+}
+
static void __activate_page(struct page *page, struct lruvec *lruvec,
void *arg)
{
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 1cd0b345ff7e..9d20b00627af 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -442,7 +442,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
/* XXX: Move to lru_cache_add() when it supports new vs putback */
spin_lock_irq(&page_pgdat(page)->lru_lock);
- lru_note_cost(page);
+ lru_note_cost_page(page);
spin_unlock_irq(&page_pgdat(page)->lru_lock);
/* Caller will initiate read into locked page */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d08640f0235c..14ffe9ccf7ef 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1359,6 +1359,8 @@ static unsigned int shrink_page_list(struct list_head *page_list,
case PAGE_ACTIVATE:
goto activate_locked;
case PAGE_SUCCESS:
+ stat->nr_pageout += hpage_nr_pages(page);
+
if (PageWriteback(page))
goto keep;
if (PageDirty(page))
@@ -1964,6 +1966,7 @@ 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);
+ lru_note_cost(lruvec, file, stat.nr_pageout);
item = current_is_kswapd() ? PGSTEAL_KSWAPD : PGSTEAL_DIRECT;
if (!cgroup_reclaim(sc))
__count_vm_events(item, nr_reclaimed);
diff --git a/mm/workingset.c b/mm/workingset.c
index a6a2a740ed0b..d481ea452eeb 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -367,7 +367,7 @@ void workingset_refault(struct page *page, void *shadow)
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);
+ lru_note_cost_page(page);
spin_unlock_irq(&page_pgdat(page)->lru_lock);
inc_lruvec_state(lruvec, WORKINGSET_RESTORE);
}