The memory.{min, low} protection can prevent the reclaimers to reclaim the pages from a memcg when there're memory pressure outside of a memcg. We'd better introduce some counters to show this behavior. This patch introduce two counters, pgscan_passive and pgsteal_passive. pgscan_passive: pages scanned due to memory pressure outside this memcg pgsteal_passive: pages reclaimed due to memory pressure outside this memcg memcg set with higher memory.{min, low} setting, will get a lower pgscan_passive and pgsteal_passive. For example, if memory.min is equal to memory.max, then these passive reclaim counters should always be zero. These counters are only for non-root memory cgroup. It's not easy to introduce some container-only vmstat counters, because it will make lots of changes. So I introduce some global vmstat counters, but they are always zero for root memory cgroup. Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx> --- Documentation/admin-guide/cgroup-v2.rst | 10 ++++++++++ include/linux/vm_event_item.h | 2 ++ mm/memcontrol.c | 4 ++++ mm/vmscan.c | 11 +++++++++-- mm/vmstat.c | 2 ++ 5 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index cdacc9c..11e0129 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -1336,10 +1336,20 @@ PAGE_SIZE multiple when read back. Amount of scanned pages (in an inactive LRU list) + pgscan_passive + + Amount of scanned pages due to memory pressure outside this + memcg + pgsteal Amount of reclaimed pages + pgsteal_passive + + Amount of reclaimed pages due to memory pressure outside + this memcg + pgactivate Amount of pages moved to the active LRU list diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h index 47a3441..0fcdaa3 100644 --- a/include/linux/vm_event_item.h +++ b/include/linux/vm_event_item.h @@ -32,8 +32,10 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, PGREFILL, PGSTEAL_KSWAPD, PGSTEAL_DIRECT, + PGSTEAL_PASSIVE, PGSCAN_KSWAPD, PGSCAN_DIRECT, + PGSCAN_PASSIVE, PGSCAN_DIRECT_THROTTLE, #ifdef CONFIG_NUMA PGSCAN_ZONE_RECLAIM_FAILED, diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 9da4ef9..0a2bf9a 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1443,9 +1443,13 @@ static char *memory_stat_format(struct mem_cgroup *memcg) seq_buf_printf(&s, "pgscan %lu\n", memcg_events(memcg, PGSCAN_KSWAPD) + memcg_events(memcg, PGSCAN_DIRECT)); + seq_buf_printf(&s, "%s %lu\n", vm_event_name(PGSCAN_PASSIVE), + memcg_events(memcg, PGSCAN_PASSIVE)); seq_buf_printf(&s, "pgsteal %lu\n", memcg_events(memcg, PGSTEAL_KSWAPD) + memcg_events(memcg, PGSTEAL_DIRECT)); + seq_buf_printf(&s, "%s %lu\n", vm_event_name(PGSTEAL_PASSIVE), + memcg_events(memcg, PGSTEAL_PASSIVE)); seq_buf_printf(&s, "%s %lu\n", vm_event_name(PGACTIVATE), memcg_events(memcg, PGACTIVATE)); seq_buf_printf(&s, "%s %lu\n", vm_event_name(PGDEACTIVATE), diff --git a/mm/vmscan.c b/mm/vmscan.c index 3b08e85..0ea6c4a0 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1910,6 +1910,7 @@ static int current_may_throttle(void) struct pglist_data *pgdat = lruvec_pgdat(lruvec); struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat; bool stalled = false; + struct mem_cgroup *memcg; while (unlikely(too_many_isolated(pgdat, file, sc))) { if (stalled) @@ -1934,10 +1935,13 @@ static int current_may_throttle(void) __mod_node_page_state(pgdat, NR_ISOLATED_ANON + file, nr_taken); reclaim_stat->recent_scanned[file] += nr_taken; + memcg = lruvec_memcg(lruvec); item = current_is_kswapd() ? PGSCAN_KSWAPD : PGSCAN_DIRECT; if (!cgroup_reclaim(sc)) __count_vm_events(item, nr_scanned); - __count_memcg_events(lruvec_memcg(lruvec), item, nr_scanned); + if (memcg != sc->target_mem_cgroup) + __count_memcg_events(memcg, PGSCAN_PASSIVE, nr_scanned); + __count_memcg_events(memcg, item, nr_scanned); spin_unlock_irq(&pgdat->lru_lock); if (nr_taken == 0) @@ -1948,10 +1952,13 @@ static int current_may_throttle(void) spin_lock_irq(&pgdat->lru_lock); + memcg = lruvec_memcg(lruvec); item = current_is_kswapd() ? PGSTEAL_KSWAPD : PGSTEAL_DIRECT; if (!cgroup_reclaim(sc)) __count_vm_events(item, nr_reclaimed); - __count_memcg_events(lruvec_memcg(lruvec), item, nr_reclaimed); + if (memcg != sc->target_mem_cgroup) + __count_memcg_events(memcg, PGSTEAL_PASSIVE, nr_reclaimed); + __count_memcg_events(memcg, item, nr_reclaimed); reclaim_stat->recent_rotated[0] += stat.nr_activate[0]; reclaim_stat->recent_rotated[1] += stat.nr_activate[1]; diff --git a/mm/vmstat.c b/mm/vmstat.c index 78d5337..5d2a053 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1196,8 +1196,10 @@ int fragmentation_index(struct zone *zone, unsigned int order) "pgrefill", "pgsteal_kswapd", "pgsteal_direct", + "pgsteal_passive", "pgscan_kswapd", "pgscan_direct", + "pgscan_passive", "pgscan_direct_throttle", #ifdef CONFIG_NUMA -- 1.8.3.1