Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm: zswap: add per-memcg stat for incompressible pages

Patch series "mm: zswap: add per-memcg stat for incompressible pages", v3.

In containerized environments, knowing which cgroup is contributing
incompressible pages to zswap is essential for effective resource
management. This series adds a new per-memcg stat 'zswap_incomp' to track
incompressible pages, along with a selftest.


This patch (of 2):

The global zswap_stored_incompressible_pages counter was added in commit
dca4437a5861 ("mm/zswap: store <PAGE_SIZE compression failed page as-is")
to track how many pages are stored in raw (uncompressed) form in zswap.
However, in containerized environments, knowing which cgroup is
contributing incompressible pages is essential for effective resource
management [1].

Add a new memcg stat 'zswap_incomp' to track incompressible pages per
cgroup. This helps administrators and orchestrators to:

1. Identify workloads that produce incompressible data (e.g., encrypted
data, already-compressed media, random data) and may not benefit from
zswap.

2. Make informed decisions about workload placement - moving
incompressible workloads to nodes with larger swap backing devices
rather than relying on zswap.

3. Debug zswap efficiency issues at the cgroup level without needing to
correlate global stats with individual cgroups.

While the compression ratio can be estimated from existing stats (zswap /
zswapped * PAGE_SIZE), this doesn't distinguish between "uniformly poor
compression" and "a few completely incompressible pages mixed with highly
compressible ones". The zswap_incomp stat provides direct visibility into
the latter case.

Link: https://lkml.kernel.org/r/20260213071827.5688-1-jiayuan.chen@linux.dev
Link: https://lkml.kernel.org/r/20260213071827.5688-2-jiayuan.chen@linux.dev
Link: https://lore.kernel.org/linux-mm/CAF8kJuONDFj4NAksaR4j_WyDbNwNGYLmTe-o76rqU17La=nkOw@mail.gmail.com/ [1]
Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
Acked-by: Nhat Pham <nphamcs@gmail.com>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Reviewed-by: Yosry Ahmed <yosry.ahmed@linux.dev>
Reviewed-by: SeongJae Park <sj@kernel.org>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Chengming Zhou <chengming.zhou@linux.dev>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Jiayuan Chen and committed by
Andrew Morton
5ad41a38 37cb8cd0

+12
+5
Documentation/admin-guide/cgroup-v2.rst
··· 1734 1734 zswpwb 1735 1735 Number of pages written from zswap to swap. 1736 1736 1737 + zswap_incomp 1738 + Number of incompressible pages currently stored in zswap 1739 + without compression. These pages could not be compressed to 1740 + a size smaller than PAGE_SIZE, so they are stored as-is. 1741 + 1737 1742 thp_fault_alloc (npn) 1738 1743 Number of transparent hugepages which were allocated to satisfy 1739 1744 a page fault. This counter is not present when CONFIG_TRANSPARENT_HUGEPAGE
+1
include/linux/memcontrol.h
··· 39 39 MEMCG_KMEM, 40 40 MEMCG_ZSWAP_B, 41 41 MEMCG_ZSWAPPED, 42 + MEMCG_ZSWAP_INCOMP, 42 43 MEMCG_NR_STAT, 43 44 }; 44 45
+6
mm/memcontrol.c
··· 356 356 MEMCG_KMEM, 357 357 MEMCG_ZSWAP_B, 358 358 MEMCG_ZSWAPPED, 359 + MEMCG_ZSWAP_INCOMP, 359 360 }; 360 361 361 362 #define NR_MEMCG_NODE_STAT_ITEMS ARRAY_SIZE(memcg_node_stat_items) ··· 1369 1368 #ifdef CONFIG_ZSWAP 1370 1369 { "zswap", MEMCG_ZSWAP_B }, 1371 1370 { "zswapped", MEMCG_ZSWAPPED }, 1371 + { "zswap_incomp", MEMCG_ZSWAP_INCOMP }, 1372 1372 #endif 1373 1373 { "file_mapped", NR_FILE_MAPPED }, 1374 1374 { "file_dirty", NR_FILE_DIRTY }, ··· 5522 5520 memcg = obj_cgroup_memcg(objcg); 5523 5521 mod_memcg_state(memcg, MEMCG_ZSWAP_B, size); 5524 5522 mod_memcg_state(memcg, MEMCG_ZSWAPPED, 1); 5523 + if (size == PAGE_SIZE) 5524 + mod_memcg_state(memcg, MEMCG_ZSWAP_INCOMP, 1); 5525 5525 rcu_read_unlock(); 5526 5526 } 5527 5527 ··· 5547 5543 memcg = obj_cgroup_memcg(objcg); 5548 5544 mod_memcg_state(memcg, MEMCG_ZSWAP_B, -size); 5549 5545 mod_memcg_state(memcg, MEMCG_ZSWAPPED, -1); 5546 + if (size == PAGE_SIZE) 5547 + mod_memcg_state(memcg, MEMCG_ZSWAP_INCOMP, -1); 5550 5548 rcu_read_unlock(); 5551 5549 } 5552 5550