@@ -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
@@ -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,
@@ -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),
@@ -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];
@@ -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
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@gmail.com> --- 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(-)