mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: Joonsoo Kim <iamjoonsoo.kim@lge.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Vlastimil 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: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									b518154e59
								
							
						
					
					
						commit
						170b04b7ae
					
				
					 5 changed files with 43 additions and 21 deletions
				
			
		| 
						 | 
					@ -173,9 +173,15 @@ enum node_stat_item {
 | 
				
			||||||
	NR_ISOLATED_ANON,	/* Temporary isolated pages from anon lru */
 | 
						NR_ISOLATED_ANON,	/* Temporary isolated pages from anon lru */
 | 
				
			||||||
	NR_ISOLATED_FILE,	/* Temporary isolated pages from file lru */
 | 
						NR_ISOLATED_FILE,	/* Temporary isolated pages from file lru */
 | 
				
			||||||
	WORKINGSET_NODES,
 | 
						WORKINGSET_NODES,
 | 
				
			||||||
	WORKINGSET_REFAULT,
 | 
						WORKINGSET_REFAULT_BASE,
 | 
				
			||||||
	WORKINGSET_ACTIVATE,
 | 
						WORKINGSET_REFAULT_ANON = WORKINGSET_REFAULT_BASE,
 | 
				
			||||||
	WORKINGSET_RESTORE,
 | 
						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,
 | 
						WORKINGSET_NODERECLAIM,
 | 
				
			||||||
	NR_ANON_MAPPED,	/* Mapped anonymous pages */
 | 
						NR_ANON_MAPPED,	/* Mapped anonymous pages */
 | 
				
			||||||
	NR_FILE_MAPPED,	/* pagecache pages mapped into pagetables.
 | 
						NR_FILE_MAPPED,	/* pagecache pages mapped into pagetables.
 | 
				
			||||||
| 
						 | 
					@ -277,8 +283,8 @@ struct lruvec {
 | 
				
			||||||
	unsigned long			file_cost;
 | 
						unsigned long			file_cost;
 | 
				
			||||||
	/* Non-resident age, driven by LRU movement */
 | 
						/* Non-resident age, driven by LRU movement */
 | 
				
			||||||
	atomic_long_t			nonresident_age;
 | 
						atomic_long_t			nonresident_age;
 | 
				
			||||||
	/* Refaults at the time of last reclaim cycle */
 | 
						/* Refaults at the time of last reclaim cycle, anon=0, file=1 */
 | 
				
			||||||
	unsigned long			refaults;
 | 
						unsigned long			refaults[2];
 | 
				
			||||||
	/* Various lruvec state flags (enum lruvec_flags) */
 | 
						/* Various lruvec state flags (enum lruvec_flags) */
 | 
				
			||||||
	unsigned long			flags;
 | 
						unsigned long			flags;
 | 
				
			||||||
#ifdef CONFIG_MEMCG
 | 
					#ifdef CONFIG_MEMCG
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1530,12 +1530,18 @@ static char *memory_stat_format(struct mem_cgroup *memcg)
 | 
				
			||||||
	seq_buf_printf(&s, "%s %lu\n", vm_event_name(PGMAJFAULT),
 | 
						seq_buf_printf(&s, "%s %lu\n", vm_event_name(PGMAJFAULT),
 | 
				
			||||||
		       memcg_events(memcg, PGMAJFAULT));
 | 
							       memcg_events(memcg, PGMAJFAULT));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	seq_buf_printf(&s, "workingset_refault %lu\n",
 | 
						seq_buf_printf(&s, "workingset_refault_anon %lu\n",
 | 
				
			||||||
		       memcg_page_state(memcg, WORKINGSET_REFAULT));
 | 
							       memcg_page_state(memcg, WORKINGSET_REFAULT_ANON));
 | 
				
			||||||
	seq_buf_printf(&s, "workingset_activate %lu\n",
 | 
						seq_buf_printf(&s, "workingset_refault_file %lu\n",
 | 
				
			||||||
		       memcg_page_state(memcg, WORKINGSET_ACTIVATE));
 | 
							       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",
 | 
						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",
 | 
						seq_buf_printf(&s, "workingset_nodereclaim %lu\n",
 | 
				
			||||||
		       memcg_page_state(memcg, WORKINGSET_NODERECLAIM));
 | 
							       memcg_page_state(memcg, WORKINGSET_NODERECLAIM));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								mm/vmscan.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								mm/vmscan.c
									
									
									
									
									
								
							| 
						 | 
					@ -2683,7 +2683,10 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
 | 
				
			||||||
	if (!sc->force_deactivate) {
 | 
						if (!sc->force_deactivate) {
 | 
				
			||||||
		unsigned long refaults;
 | 
							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;
 | 
								sc->may_deactivate |= DEACTIVATE_ANON;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			sc->may_deactivate &= ~DEACTIVATE_ANON;
 | 
								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.
 | 
							 * rid of any stale active pages quickly.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		refaults = lruvec_page_state(target_lruvec,
 | 
							refaults = lruvec_page_state(target_lruvec,
 | 
				
			||||||
					     WORKINGSET_ACTIVATE);
 | 
									WORKINGSET_ACTIVATE_FILE);
 | 
				
			||||||
		if (refaults != target_lruvec->refaults ||
 | 
							if (refaults != target_lruvec->refaults[1] ||
 | 
				
			||||||
		    inactive_is_low(target_lruvec, LRU_INACTIVE_FILE))
 | 
							    inactive_is_low(target_lruvec, LRU_INACTIVE_FILE))
 | 
				
			||||||
			sc->may_deactivate |= DEACTIVATE_FILE;
 | 
								sc->may_deactivate |= DEACTIVATE_FILE;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
| 
						 | 
					@ -2972,8 +2975,10 @@ static void snapshot_refaults(struct mem_cgroup *target_memcg, pg_data_t *pgdat)
 | 
				
			||||||
	unsigned long refaults;
 | 
						unsigned long refaults;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	target_lruvec = mem_cgroup_lruvec(target_memcg, pgdat);
 | 
						target_lruvec = mem_cgroup_lruvec(target_memcg, pgdat);
 | 
				
			||||||
	refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE);
 | 
						refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_ANON);
 | 
				
			||||||
	target_lruvec->refaults = refaults;
 | 
						target_lruvec->refaults[0] = refaults;
 | 
				
			||||||
 | 
						refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_FILE);
 | 
				
			||||||
 | 
						target_lruvec->refaults[1] = refaults;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1167,9 +1167,12 @@ const char * const vmstat_text[] = {
 | 
				
			||||||
	"nr_isolated_anon",
 | 
						"nr_isolated_anon",
 | 
				
			||||||
	"nr_isolated_file",
 | 
						"nr_isolated_file",
 | 
				
			||||||
	"workingset_nodes",
 | 
						"workingset_nodes",
 | 
				
			||||||
	"workingset_refault",
 | 
						"workingset_refault_anon",
 | 
				
			||||||
	"workingset_activate",
 | 
						"workingset_refault_file",
 | 
				
			||||||
	"workingset_restore",
 | 
						"workingset_activate_anon",
 | 
				
			||||||
 | 
						"workingset_activate_file",
 | 
				
			||||||
 | 
						"workingset_restore_anon",
 | 
				
			||||||
 | 
						"workingset_restore_file",
 | 
				
			||||||
	"workingset_nodereclaim",
 | 
						"workingset_nodereclaim",
 | 
				
			||||||
	"nr_anon_pages",
 | 
						"nr_anon_pages",
 | 
				
			||||||
	"nr_mapped",
 | 
						"nr_mapped",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/memcontrol.h>
 | 
					#include <linux/memcontrol.h>
 | 
				
			||||||
 | 
					#include <linux/mm_inline.h>
 | 
				
			||||||
#include <linux/writeback.h>
 | 
					#include <linux/writeback.h>
 | 
				
			||||||
#include <linux/shmem_fs.h>
 | 
					#include <linux/shmem_fs.h>
 | 
				
			||||||
#include <linux/pagemap.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)
 | 
					void workingset_refault(struct page *page, void *shadow)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						bool file = page_is_file_lru(page);
 | 
				
			||||||
	struct mem_cgroup *eviction_memcg;
 | 
						struct mem_cgroup *eviction_memcg;
 | 
				
			||||||
	struct lruvec *eviction_lruvec;
 | 
						struct lruvec *eviction_lruvec;
 | 
				
			||||||
	unsigned long refault_distance;
 | 
						unsigned long refault_distance;
 | 
				
			||||||
| 
						 | 
					@ -346,7 +348,7 @@ void workingset_refault(struct page *page, void *shadow)
 | 
				
			||||||
	memcg = page_memcg(page);
 | 
						memcg = page_memcg(page);
 | 
				
			||||||
	lruvec = mem_cgroup_lruvec(memcg, pgdat);
 | 
						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
 | 
						 * Compare the distance to the existing workingset size. We
 | 
				
			||||||
| 
						 | 
					@ -366,7 +368,7 @@ void workingset_refault(struct page *page, void *shadow)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SetPageActive(page);
 | 
						SetPageActive(page);
 | 
				
			||||||
	workingset_age_nonresident(lruvec, hpage_nr_pages(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 */
 | 
						/* Page was active prior to eviction */
 | 
				
			||||||
	if (workingset) {
 | 
						if (workingset) {
 | 
				
			||||||
| 
						 | 
					@ -375,7 +377,7 @@ void workingset_refault(struct page *page, void *shadow)
 | 
				
			||||||
		spin_lock_irq(&page_pgdat(page)->lru_lock);
 | 
							spin_lock_irq(&page_pgdat(page)->lru_lock);
 | 
				
			||||||
		lru_note_cost_page(page);
 | 
							lru_note_cost_page(page);
 | 
				
			||||||
		spin_unlock_irq(&page_pgdat(page)->lru_lock);
 | 
							spin_unlock_irq(&page_pgdat(page)->lru_lock);
 | 
				
			||||||
		inc_lruvec_state(lruvec, WORKINGSET_RESTORE);
 | 
							inc_lruvec_state(lruvec, WORKINGSET_RESTORE_BASE + file);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue