Commit 170b04b7 authored by Joonsoo Kim's avatar Joonsoo Kim Committed by Linus Torvalds
Browse files

mm/workingset: prepare the workingset detection infrastructure for anon LRU



To prepare the workingset detection for anon LRU, this patch splits
workingset event counters for refault, activate and restore into anon and
file variants, as well as the refaults counter in struct lruvec.

Signed-off-by: default avatarJoonsoo Kim <iamjoonsoo.kim@lge.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
Cc: Hugh Dickins <hughd@google.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Minchan Kim <minchan@kernel.org>
Link: http://lkml.kernel.org/r/1595490560-15117-4-git-send-email-iamjoonsoo.kim@lge.com


Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b518154e
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -173,9 +173,15 @@ enum node_stat_item {
	NR_ISOLATED_ANON,	/* Temporary isolated pages from anon lru */
	NR_ISOLATED_FILE,	/* Temporary isolated pages from file lru */
	WORKINGSET_NODES,
	WORKINGSET_REFAULT,
	WORKINGSET_ACTIVATE,
	WORKINGSET_RESTORE,
	WORKINGSET_REFAULT_BASE,
	WORKINGSET_REFAULT_ANON = WORKINGSET_REFAULT_BASE,
	WORKINGSET_REFAULT_FILE,
	WORKINGSET_ACTIVATE_BASE,
	WORKINGSET_ACTIVATE_ANON = WORKINGSET_ACTIVATE_BASE,
	WORKINGSET_ACTIVATE_FILE,
	WORKINGSET_RESTORE_BASE,
	WORKINGSET_RESTORE_ANON = WORKINGSET_RESTORE_BASE,
	WORKINGSET_RESTORE_FILE,
	WORKINGSET_NODERECLAIM,
	NR_ANON_MAPPED,	/* Mapped anonymous pages */
	NR_FILE_MAPPED,	/* pagecache pages mapped into pagetables.
@@ -277,8 +283,8 @@ struct lruvec {
	unsigned long			file_cost;
	/* Non-resident age, driven by LRU movement */
	atomic_long_t			nonresident_age;
	/* Refaults at the time of last reclaim cycle */
	unsigned long			refaults;
	/* Refaults at the time of last reclaim cycle, anon=0, file=1 */
	unsigned long			refaults[2];
	/* Various lruvec state flags (enum lruvec_flags) */
	unsigned long			flags;
#ifdef CONFIG_MEMCG
+11 −5
Original line number Diff line number Diff line
@@ -1530,12 +1530,18 @@ static char *memory_stat_format(struct mem_cgroup *memcg)
	seq_buf_printf(&s, "%s %lu\n", vm_event_name(PGMAJFAULT),
		       memcg_events(memcg, PGMAJFAULT));

	seq_buf_printf(&s, "workingset_refault %lu\n",
		       memcg_page_state(memcg, WORKINGSET_REFAULT));
	seq_buf_printf(&s, "workingset_activate %lu\n",
		       memcg_page_state(memcg, WORKINGSET_ACTIVATE));
	seq_buf_printf(&s, "workingset_refault_anon %lu\n",
		       memcg_page_state(memcg, WORKINGSET_REFAULT_ANON));
	seq_buf_printf(&s, "workingset_refault_file %lu\n",
		       memcg_page_state(memcg, WORKINGSET_REFAULT_FILE));
	seq_buf_printf(&s, "workingset_activate_anon %lu\n",
		       memcg_page_state(memcg, WORKINGSET_ACTIVATE_ANON));
	seq_buf_printf(&s, "workingset_activate_file %lu\n",
		       memcg_page_state(memcg, WORKINGSET_ACTIVATE_FILE));
	seq_buf_printf(&s, "workingset_restore %lu\n",
		       memcg_page_state(memcg, WORKINGSET_RESTORE));
		       memcg_page_state(memcg, WORKINGSET_RESTORE_ANON));
	seq_buf_printf(&s, "workingset_restore %lu\n",
		       memcg_page_state(memcg, WORKINGSET_RESTORE_FILE));
	seq_buf_printf(&s, "workingset_nodereclaim %lu\n",
		       memcg_page_state(memcg, WORKINGSET_NODERECLAIM));

+10 −5
Original line number Diff line number Diff line
@@ -2683,7 +2683,10 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
	if (!sc->force_deactivate) {
		unsigned long refaults;

		if (inactive_is_low(target_lruvec, LRU_INACTIVE_ANON))
		refaults = lruvec_page_state(target_lruvec,
				WORKINGSET_ACTIVATE_ANON);
		if (refaults != target_lruvec->refaults[0] ||
			inactive_is_low(target_lruvec, LRU_INACTIVE_ANON))
			sc->may_deactivate |= DEACTIVATE_ANON;
		else
			sc->may_deactivate &= ~DEACTIVATE_ANON;
@@ -2694,8 +2697,8 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
		 * rid of any stale active pages quickly.
		 */
		refaults = lruvec_page_state(target_lruvec,
					     WORKINGSET_ACTIVATE);
		if (refaults != target_lruvec->refaults ||
				WORKINGSET_ACTIVATE_FILE);
		if (refaults != target_lruvec->refaults[1] ||
		    inactive_is_low(target_lruvec, LRU_INACTIVE_FILE))
			sc->may_deactivate |= DEACTIVATE_FILE;
		else
@@ -2972,8 +2975,10 @@ static void snapshot_refaults(struct mem_cgroup *target_memcg, pg_data_t *pgdat)
	unsigned long refaults;

	target_lruvec = mem_cgroup_lruvec(target_memcg, pgdat);
	refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE);
	target_lruvec->refaults = refaults;
	refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_ANON);
	target_lruvec->refaults[0] = refaults;
	refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_FILE);
	target_lruvec->refaults[1] = refaults;
}

/*
+6 −3
Original line number Diff line number Diff line
@@ -1167,9 +1167,12 @@ const char * const vmstat_text[] = {
	"nr_isolated_anon",
	"nr_isolated_file",
	"workingset_nodes",
	"workingset_refault",
	"workingset_activate",
	"workingset_restore",
	"workingset_refault_anon",
	"workingset_refault_file",
	"workingset_activate_anon",
	"workingset_activate_file",
	"workingset_restore_anon",
	"workingset_restore_file",
	"workingset_nodereclaim",
	"nr_anon_pages",
	"nr_mapped",
+5 −3
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 */

#include <linux/memcontrol.h>
#include <linux/mm_inline.h>
#include <linux/writeback.h>
#include <linux/shmem_fs.h>
#include <linux/pagemap.h>
@@ -280,6 +281,7 @@ void *workingset_eviction(struct page *page, struct mem_cgroup *target_memcg)
 */
void workingset_refault(struct page *page, void *shadow)
{
	bool file = page_is_file_lru(page);
	struct mem_cgroup *eviction_memcg;
	struct lruvec *eviction_lruvec;
	unsigned long refault_distance;
@@ -346,7 +348,7 @@ void workingset_refault(struct page *page, void *shadow)
	memcg = page_memcg(page);
	lruvec = mem_cgroup_lruvec(memcg, pgdat);

	inc_lruvec_state(lruvec, WORKINGSET_REFAULT);
	inc_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file);

	/*
	 * Compare the distance to the existing workingset size. We
@@ -366,7 +368,7 @@ void workingset_refault(struct page *page, void *shadow)

	SetPageActive(page);
	workingset_age_nonresident(lruvec, hpage_nr_pages(page));
	inc_lruvec_state(lruvec, WORKINGSET_ACTIVATE);
	inc_lruvec_state(lruvec, WORKINGSET_ACTIVATE_BASE + file);

	/* Page was active prior to eviction */
	if (workingset) {
@@ -375,7 +377,7 @@ void workingset_refault(struct page *page, void *shadow)
		spin_lock_irq(&page_pgdat(page)->lru_lock);
		lru_note_cost_page(page);
		spin_unlock_irq(&page_pgdat(page)->lru_lock);
		inc_lruvec_state(lruvec, WORKINGSET_RESTORE);
		inc_lruvec_state(lruvec, WORKINGSET_RESTORE_BASE + file);
	}
out:
	rcu_read_unlock();