From: Jiayuan Chen <jiayuan.chen@shopee.com>
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=nkOw@mail.gmail.com/
Acked-by: Nhat Pham <nphamcs@gmail.com>
Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
---
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 */
+ 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
On Fri, 6 Feb 2026 15:22:15 +0800 Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
> From: Jiayuan Chen <jiayuan.chen@shopee.com>
>
> 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.
Sounds like a useful new stat, thank you for making this!
>
> [1]: https://lore.kernel.org/linux-mm/CAF8kJuONDFj4NAksaR4j_WyDbNwNGYLmTe-o76rqU17La=nkOw@mail.gmail.com/
> Acked-by: Nhat Pham <nphamcs@gmail.com>
Nit. It would look better to have one line before tags lines, or use 'Link:'
tag with '# [1]' like trailing comment for the link.
> Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
Reviewed-by: SeongJae Park <sj@kernel.org>
Thanks,
SJ
[...]
On Fri, Feb 06, 2026 at 03:22:15PM +0800, Jiayuan Chen wrote:
> From: Jiayuan Chen <jiayuan.chen@shopee.com>
>
> 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=nkOw@mail.gmail.com/
> Acked-by: Nhat Pham <nphamcs@gmail.com>
> Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
On Fri, Feb 06, 2026 at 03:22:15PM +0800, Jiayuan Chen wrote:
> From: Jiayuan Chen <jiayuan.chen@shopee.com>
>
> 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=nkOw@mail.gmail.com/
> Acked-by: Nhat Pham <nphamcs@gmail.com>
> Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
> ---
> 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 <yosry.ahmed@linux.dev>
> + 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
>
© 2016 - 2026 Red Hat, Inc.