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 635a96cd9b1f7e70c948b825a87337ae89c509e4..efbd95dd3bbffa3f15a69a4aa24446ccabbe9c46 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 f1fd265b9f9ea60d1ac803c89f02e143e1b7894e..c6c5792178555ec197083878c12de28c02f3f905 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 783cd7fdc61a34aef3f468b5701192aa1c7e2e8b..017f323318a370c4f5e770f9584e7d30bc4e57ce 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 2b866cbab11db75f982dee0c37b278becd24ac24..fef03463a0cfe60bc3289f894d9ab320670a3e9b 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 b199726924ddd094f56c8421d1a85cba7f2069c4..941bbaa6c262718b3f054691e8241a3b8e706e79 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();