mm/workingset: prepare the workingset detection infrastructure for anon LRU
authorJoonsoo Kim <iamjoonsoo.kim@lge.com>
Wed, 12 Aug 2020 01:30:43 +0000 (18:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 12 Aug 2020 17:57:55 +0000 (10:57 -0700)
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>
include/linux/mmzone.h
mm/memcontrol.c
mm/vmscan.c
mm/vmstat.c
mm/workingset.c

index 635a96c..efbd95d 100644 (file)
@@ -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
index f1fd265..c6c5792 100644 (file)
@@ -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));
 
index 783cd7f..017f323 100644 (file)
@@ -2683,7 +2683,10 @@ again:
        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 @@ again:
                 * 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;
 }
 
 /*
index 2b866cb..fef0346 100644 (file)
@@ -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",
index b199726..941bbaa 100644 (file)
@@ -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();