On Fri, Feb 06, 2026 at 03:22:15PM +0800, Jiayuan Chen wrote: > From: Jiayuan Chen <[email protected]> > > 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. > > [1]: > https://lore.kernel.org/linux-mm/CAF8kJuONDFj4NAksaR4j_WyDbNwNGYLmTe-o76rqU17La=n...@mail.gmail.com/ > Acked-by: Nhat Pham <[email protected]> > Signed-off-by: Jiayuan Chen <[email protected]> > --- > Documentation/admin-guide/cgroup-v2.rst | 5 +++++ > include/linux/memcontrol.h | 1 + > mm/memcontrol.c | 8 ++++++++ > 3 files changed, 14 insertions(+) > > diff --git a/Documentation/admin-guide/cgroup-v2.rst > b/Documentation/admin-guide/cgroup-v2.rst > index 7f5b59d95fce..78a329414615 100644 > --- a/Documentation/admin-guide/cgroup-v2.rst > +++ b/Documentation/admin-guide/cgroup-v2.rst > @@ -1737,6 +1737,11 @@ The following nested keys are defined. > zswpwb > Number of pages written from zswap to swap. > > + zswap_incomp > + Number of incompressible pages currently stored in zswap > + without compression. These pages could not be compressed to > + a size smaller than PAGE_SIZE, so they are stored as-is. > + > thp_fault_alloc (npn) > Number of transparent hugepages which were allocated to satisfy > a page fault. This counter is not present when > CONFIG_TRANSPARENT_HUGEPAGE > diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h > index b6c82c8f73e1..d8ec05dd5d43 100644 > --- a/include/linux/memcontrol.h > +++ b/include/linux/memcontrol.h > @@ -39,6 +39,7 @@ enum memcg_stat_item { > MEMCG_KMEM, > MEMCG_ZSWAP_B, > MEMCG_ZSWAPPED, > + MEMCG_ZSWAP_INCOMP, > MEMCG_NR_STAT, > }; > > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index 007413a53b45..a6b6cf5f1aeb 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -341,6 +341,7 @@ static const unsigned int memcg_stat_items[] = { > MEMCG_KMEM, > MEMCG_ZSWAP_B, > MEMCG_ZSWAPPED, > + MEMCG_ZSWAP_INCOMP, > }; > > #define NR_MEMCG_NODE_STAT_ITEMS ARRAY_SIZE(memcg_node_stat_items) > @@ -1346,6 +1347,7 @@ static const struct memory_stat memory_stats[] = { > #ifdef CONFIG_ZSWAP > { "zswap", MEMCG_ZSWAP_B }, > { "zswapped", MEMCG_ZSWAPPED }, > + { "zswap_incomp", MEMCG_ZSWAP_INCOMP }, > #endif > { "file_mapped", NR_FILE_MAPPED }, > { "file_dirty", NR_FILE_DIRTY }, > @@ -5458,6 +5460,9 @@ void obj_cgroup_charge_zswap(struct obj_cgroup *objcg, > size_t size) > memcg = obj_cgroup_memcg(objcg); > mod_memcg_state(memcg, MEMCG_ZSWAP_B, size); > mod_memcg_state(memcg, MEMCG_ZSWAPPED, 1); > + /* size == PAGE_SIZE means compression failed, page is incompressible */
I think the comment is not very useful, but maybe not worth sending a new version. Otherwise LGTM: Reviewed-by: Yosry Ahmed <[email protected]> > + if (size == PAGE_SIZE) > + mod_memcg_state(memcg, MEMCG_ZSWAP_INCOMP, 1); > rcu_read_unlock(); > } > > @@ -5481,6 +5486,9 @@ void obj_cgroup_uncharge_zswap(struct obj_cgroup > *objcg, size_t size) > memcg = obj_cgroup_memcg(objcg); > mod_memcg_state(memcg, MEMCG_ZSWAP_B, -size); > mod_memcg_state(memcg, MEMCG_ZSWAPPED, -1); > + /* size == PAGE_SIZE means compression failed, page is incompressible */ > + if (size == PAGE_SIZE) > + mod_memcg_state(memcg, MEMCG_ZSWAP_INCOMP, -1); > rcu_read_unlock(); > } > > -- > 2.43.0 >
