* [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
@ 2026-08-21 18:56 Eric Chanudet
2026-08-21 18:56 ` [PATCH 01/11] mm/cma: drop const for struct page on release API Eric Chanudet
` (13 more replies)
0 siblings, 14 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:56 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
CMA allocations are currently unaccounted for by cgroup memory
controllers. As system resources, they should fall under memcg, but CMA
areas partition the available space for different purposes and memcg
doesn't have a good representation for that.
Add a memory_cma_accounting cgroupfs option in preparation for the
following new behavior. Make it disabled by default since it will
account for CMA allocations in memcg which may affect existing systems.
Provide CMA charge/uncharge functions to memcg that introduce a CMA area
specific counter per CMA area. Charges are issued to memcg and to a page
counter for the CMA area used. The allocation's folios are marked with
the cgroup via commit_charge() (once for large folios, per-page for
0-order ones) so they can be later uncharged correctly.
Add the new memcg calls into the cma allocator under __cma_alloc_frozen,
for both cma and hugetlb_cma allocations accounting.
Finally register the per-area usage counters in the cgroupfs. Each CMA
area creates a memory.cma.<area>.{current,max} pair for reporting and
limitation for each area.
Selftests and a vmtest script are added to this series for convenience.
The tests are simple accounting and limit enforcement verification using
the default reserved CMA area (cma=) and hugetlb_cma.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
Eric Chanudet (11):
mm/cma: drop const for struct page on release API
mm/cma: include linux/cma.h in cma.h
cgroup: add memory_cma_accounting mount option
memcg: add cma charge/uncharge functions for area counters
mm/cma: charge cma allocation to memcg per area counters
memcg: register per-area usage counters in cgroupfs
selftests: cgroup: add cma configs for cgroup selftest suite
selftests: cgroup: add memcg cma tests
selftests: cgroup: add a vmtest script for memcg
selftests: cgroup: add memcg hugetlb_cma tests
selftests: cgroup: amend vmtest-memcg to run the hugetlb cma tests
Documentation/admin-guide/cgroup-v2.rst | 35 +++
include/linux/cgroup-defs.h | 5 +
include/linux/cma.h | 4 +-
include/linux/memcontrol.h | 19 ++
kernel/cgroup/cgroup.c | 15 +-
mm/cma.c | 14 +-
mm/cma.h | 6 +
mm/cma_debug.c | 1 -
mm/cma_sysfs.c | 1 -
mm/memcontrol.c | 205 ++++++++++++
tools/testing/selftests/cgroup/.gitignore | 1 +
tools/testing/selftests/cgroup/Makefile | 2 +
tools/testing/selftests/cgroup/config | 5 +
tools/testing/selftests/cgroup/test_cma_memcg.c | 402 ++++++++++++++++++++++++
tools/testing/selftests/cgroup/vmtest-memcg.sh | 197 ++++++++++++
15 files changed, 903 insertions(+), 9 deletions(-)
---
base-commit: 98f21c54f99519329c18e2625b0ea6db14524d09
change-id: 20260706-cma-memcg-regions-696cb5ef7998
Best regards,
--
Eric Chanudet <echanude@redhat.com>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 01/11] mm/cma: drop const for struct page on release API
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
@ 2026-08-21 18:56 ` Eric Chanudet
2026-08-21 18:56 ` [PATCH 02/11] mm/cma: include linux/cma.h in cma.h Eric Chanudet
` (12 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:56 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
The const is not honored. Both cma_release and cma_release_frozen do a
struct page -> pfn -> struct page round-trip to convert the const struct
page pointer to struct page and modify it:
cma_release calls put_page_testzero() directly, which modifies the page;
cma_release_frozen calls free_contig_frozen_range(pfn),
__free_contig_frozen_range, then __free_contig_range_common which
modifies the page as well.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
include/linux/cma.h | 4 ++--
mm/cma.c | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/linux/cma.h b/include/linux/cma.h
index 8555d38a97b1..16e2136421b7 100644
--- a/include/linux/cma.h
+++ b/include/linux/cma.h
@@ -49,12 +49,12 @@ extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
struct cma **res_cma);
extern struct page *cma_alloc(struct cma *cma, unsigned long count, unsigned int align,
bool no_warn);
-extern bool cma_release(struct cma *cma, const struct page *pages, unsigned long count);
+extern bool cma_release(struct cma *cma, struct page *pages, unsigned long count);
struct page *cma_alloc_frozen(struct cma *cma, unsigned long count,
unsigned int align, bool no_warn);
struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order);
-bool cma_release_frozen(struct cma *cma, const struct page *pages,
+bool cma_release_frozen(struct cma *cma, struct page *pages,
unsigned long count);
extern int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data);
diff --git a/mm/cma.c b/mm/cma.c
index a13ce4999b39..e1820fb451e4 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -992,7 +992,7 @@ static struct cma_memrange *find_cma_memrange(struct cma *cma,
}
static void __cma_release_frozen(struct cma *cma, struct cma_memrange *cmr,
- const struct page *pages, unsigned long count)
+ struct page *pages, unsigned long count)
{
unsigned long pfn = page_to_pfn(pages);
@@ -1014,7 +1014,7 @@ static void __cma_release_frozen(struct cma *cma, struct cma_memrange *cmr,
* It returns false when provided pages do not belong to contiguous area and
* true otherwise.
*/
-bool cma_release(struct cma *cma, const struct page *pages,
+bool cma_release(struct cma *cma, struct page *pages,
unsigned long count)
{
struct cma_memrange *cmr;
@@ -1037,7 +1037,7 @@ bool cma_release(struct cma *cma, const struct page *pages,
}
EXPORT_SYMBOL_GPL(cma_release);
-bool cma_release_frozen(struct cma *cma, const struct page *pages,
+bool cma_release_frozen(struct cma *cma, struct page *pages,
unsigned long count)
{
struct cma_memrange *cmr;
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 02/11] mm/cma: include linux/cma.h in cma.h
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
2026-08-21 18:56 ` [PATCH 01/11] mm/cma: drop const for struct page on release API Eric Chanudet
@ 2026-08-21 18:56 ` Eric Chanudet
2026-08-21 18:56 ` [PATCH 03/11] cgroup: add memory_cma_accounting mount option Eric Chanudet
` (11 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:56 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
cma.h needs definitions from linux/cma.h (e.g, MAX_CMA_AREAS,
CMA_MAX_NAME), so including mm/cma.h requires including linux/cma.h.
Make the dependency explicit by including the header directly.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
mm/cma.c | 1 -
mm/cma.h | 1 +
mm/cma_debug.c | 1 -
mm/cma_sysfs.c | 1 -
4 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/mm/cma.c b/mm/cma.c
index e1820fb451e4..03f98f6d45a5 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -25,7 +25,6 @@
#include <linux/string.h>
#include <linux/string_choices.h>
#include <linux/log2.h>
-#include <linux/cma.h>
#include <linux/highmem.h>
#include <linux/io.h>
#include <linux/kmemleak.h>
diff --git a/mm/cma.h b/mm/cma.h
index c70180c36559..0c9de38d6bff 100644
--- a/mm/cma.h
+++ b/mm/cma.h
@@ -4,6 +4,7 @@
#include <linux/debugfs.h>
#include <linux/kobject.h>
+#include <linux/cma.h>
struct cma_kobject {
struct kobject kobj;
diff --git a/mm/cma_debug.c b/mm/cma_debug.c
index 523ba4a0f9f7..70bfc6fbeeca 100644
--- a/mm/cma_debug.c
+++ b/mm/cma_debug.c
@@ -7,7 +7,6 @@
#include <linux/debugfs.h>
-#include <linux/cma.h>
#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/slab.h>
diff --git a/mm/cma_sysfs.c b/mm/cma_sysfs.c
index d5bf792c6245..e4ee35bc682b 100644
--- a/mm/cma_sysfs.c
+++ b/mm/cma_sysfs.c
@@ -5,7 +5,6 @@
* Copyright (c) 2021 Minchan Kim <minchan@kernel.org>
*/
-#include <linux/cma.h>
#include <linux/kernel.h>
#include <linux/slab.h>
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 03/11] cgroup: add memory_cma_accounting mount option
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
2026-08-21 18:56 ` [PATCH 01/11] mm/cma: drop const for struct page on release API Eric Chanudet
2026-08-21 18:56 ` [PATCH 02/11] mm/cma: include linux/cma.h in cma.h Eric Chanudet
@ 2026-08-21 18:56 ` Eric Chanudet
2026-08-24 7:02 ` Maxime Ripard
2026-08-21 18:56 ` [PATCH 04/11] memcg: add cma charge/uncharge functions for area counters Eric Chanudet
` (10 subsequent siblings)
13 siblings, 1 reply; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:56 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
Add a cgroup v2 mount option that will be used later in this series to
enable CMA memory accounting under memcg.
The option is made opt-in as it will charge allocations to the cgroup's
overall memory usage, which changes existing expectations.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
Documentation/admin-guide/cgroup-v2.rst | 20 ++++++++++++++++++++
include/linux/cgroup-defs.h | 5 +++++
kernel/cgroup/cgroup.c | 15 ++++++++++++++-
3 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index aed195a71cbf..3dfc13f31a0c 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -246,6 +246,26 @@ cgroup v2 currently supports the following mount options.
will not be tracked by the memory controller (even if cgroup
v2 is remounted later on).
+ memory_cma_accounting
+ Count CMA memory usage towards the cgroup's overall memory usage for
+ the memory controller, and expose per-CMA-area usage counters. This
+ behavior is opt-in, so as to not cause regression on existing setups.
+
+ A few caveats to keep in mind:
+
+ * CMA areas are reserved at boot time, memory is only charged to a
+ cgroup when a CMA allocation is performed on its behalf.
+ * CMA pages allocated while this option is not enabled will not be
+ tracked by the memory controller, even if cgroup v2 is remounted
+ later on with this option. Charges happen at allocation.
+ * CMA allocations are charged both to the cgroup's memory counter
+ (limited by memory.max) and the per-area CMA counter (limited by
+ memory.cma.<area>.max). Hitting either limit can cause an allocation
+ to fail. If CMA usage pushes the cgroup over memory.high or
+ memory.max, the memory controller will attempt to reclaim other
+ memory only. CMA memory charged to the cgroup is not reclaimable.
+ Limits should be sized to accommodate the expected CMA pressure.
+
pids_localevents
The option restores v1-like behavior of pids.events:max, that is only
local (inside cgroup proper) fork failures are counted. Without this
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index de2cd6238c2a..15f3f7110c5b 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -129,6 +129,11 @@ enum {
* Enable legacy local pids.events.
*/
CGRP_ROOT_PIDS_LOCAL_EVENTS = (1 << 20),
+
+ /*
+ * Enable cma accounting for the memory controller.
+ */
+ CGRP_ROOT_MEMORY_CMA_ACCOUNTING = (1 << 21),
};
/* cftype->flags */
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index b5b461d4418b..12184f85ad10 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1985,6 +1985,7 @@ enum cgroup2_param {
Opt_memory_recursiveprot,
Opt_memory_hugetlb_accounting,
Opt_pids_localevents,
+ Opt_memory_cma_accounting,
nr__cgroup2_params
};
@@ -1995,6 +1996,7 @@ static const struct fs_parameter_spec cgroup2_fs_parameters[] = {
fsparam_flag("memory_recursiveprot", Opt_memory_recursiveprot),
fsparam_flag("memory_hugetlb_accounting", Opt_memory_hugetlb_accounting),
fsparam_flag("pids_localevents", Opt_pids_localevents),
+ fsparam_flag("memory_cma_accounting", Opt_memory_cma_accounting),
{}
};
@@ -2027,6 +2029,9 @@ static int cgroup2_parse_param(struct fs_context *fc, struct fs_parameter *param
case Opt_pids_localevents:
ctx->flags |= CGRP_ROOT_PIDS_LOCAL_EVENTS;
return 0;
+ case Opt_memory_cma_accounting:
+ ctx->flags |= CGRP_ROOT_MEMORY_CMA_ACCOUNTING;
+ return 0;
}
return -EINVAL;
}
@@ -2068,6 +2073,11 @@ static void apply_cgroup_root_flags(unsigned int root_flags)
cgrp_dfl_root.flags |= CGRP_ROOT_PIDS_LOCAL_EVENTS;
else
cgrp_dfl_root.flags &= ~CGRP_ROOT_PIDS_LOCAL_EVENTS;
+
+ if (root_flags & CGRP_ROOT_MEMORY_CMA_ACCOUNTING)
+ cgrp_dfl_root.flags |= CGRP_ROOT_MEMORY_CMA_ACCOUNTING;
+ else
+ cgrp_dfl_root.flags &= ~CGRP_ROOT_MEMORY_CMA_ACCOUNTING;
}
}
@@ -2085,6 +2095,8 @@ static int cgroup_show_options(struct seq_file *seq, struct kernfs_root *kf_root
seq_puts(seq, ",memory_hugetlb_accounting");
if (cgrp_dfl_root.flags & CGRP_ROOT_PIDS_LOCAL_EVENTS)
seq_puts(seq, ",pids_localevents");
+ if (cgrp_dfl_root.flags & CGRP_ROOT_MEMORY_CMA_ACCOUNTING)
+ seq_puts(seq, ",memory_cma_accounting");
return 0;
}
@@ -7520,7 +7532,8 @@ static ssize_t features_show(struct kobject *kobj, struct kobj_attribute *attr,
"memory_localevents\n"
"memory_recursiveprot\n"
"memory_hugetlb_accounting\n"
- "pids_localevents\n");
+ "pids_localevents\n"
+ "memory_cma_accounting\n");
}
static struct kobj_attribute cgroup_features_attr = __ATTR_RO(features);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 04/11] memcg: add cma charge/uncharge functions for area counters
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (2 preceding siblings ...)
2026-08-21 18:56 ` [PATCH 03/11] cgroup: add memory_cma_accounting mount option Eric Chanudet
@ 2026-08-21 18:56 ` Eric Chanudet
2026-08-21 18:56 ` [PATCH 05/11] mm/cma: charge cma allocation to memcg per " Eric Chanudet
` (9 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:56 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
Introduce mem_cgroup_charge_cma() and mem_cgroup_uncharge_cma() to
account CMA allocations under memcg when memory_cma_accounting is
enabled in cgroupfs.
memcg counters to account for allocation in each CMA area are kcalloc'd
in mem_cgroup_alloc() and added to the page-counter hierarchy in
mem_cgroup_css_alloc(). cma_area_count is used to size the array. It is
calculated during setup_arch(), before mem_cgroup_alloc() is called
(for the first time in cgroup_init()).
On cma_alloc(), pages are charged both to the cgroup's memory controller
(with try_charge_memcg()) and to the per area page counter for the CMA
region used.
CMA ranges can be either pages with a 0-order folio (cma_alloc_frozen,
!__GFP_COMP) or pages under a large folio (cma_alloc_frozen_compound,
__GFP_COMP). In the first case, mark each page's folio with the cgroup's
obj_cgroup. In the second case, only mark the large folio from the first
page.
On cma_release(), get the first page's folio and uncharge both counters
accordingly if it is a large folio or not.
A small cma_area_index() helper is introduced to succinctly get the
counter of a given CMA region in the memcg CMA area counters array.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
include/linux/memcontrol.h | 19 ++++++++
mm/cma.h | 5 ++
mm/memcontrol.c | 116 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 140 insertions(+)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 8170bb8066a2..801fbde94137 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -320,6 +320,10 @@ struct mem_cgroup {
spinlock_t event_list_lock;
#endif /* CONFIG_MEMCG_V1 */
+#ifdef CONFIG_CMA
+ struct page_counter *cma_counters;
+#endif /* CONFIG_CMA */
+
struct mem_cgroup_per_node *nodeinfo[];
};
@@ -662,6 +666,11 @@ int mem_cgroup_charge_hugetlb(struct folio* folio, gfp_t gfp);
int mem_cgroup_swapin_charge_folio(struct folio *folio, unsigned short id,
struct mm_struct *mm, gfp_t gfp);
+int mem_cgroup_charge_cma(struct page *page, unsigned long count,
+ struct cma *cma);
+void mem_cgroup_uncharge_cma(struct page *page, unsigned long count,
+ struct cma *cma);
+
void __mem_cgroup_uncharge(struct folio *folio);
/**
@@ -1160,6 +1169,16 @@ static inline int mem_cgroup_swapin_charge_folio(struct folio *folio,
return 0;
}
+static inline int mem_cgroup_charge_cma(struct page *page, unsigned long count,
+ struct cma *cma)
+{
+ return 0;
+}
+static inline void mem_cgroup_uncharge_cma(struct page *page,
+ unsigned long count, struct cma *cma)
+{
+}
+
static inline void mem_cgroup_uncharge(struct folio *folio)
{
}
diff --git a/mm/cma.h b/mm/cma.h
index 0c9de38d6bff..52b7d4be5170 100644
--- a/mm/cma.h
+++ b/mm/cma.h
@@ -81,6 +81,11 @@ static inline unsigned long cma_bitmap_maxno(struct cma *cma,
return cmr->count >> cma->order_per_bit;
}
+static inline int cma_area_index(const struct cma *cma)
+{
+ return cma - cma_areas;
+}
+
#ifdef CONFIG_CMA_SYSFS
void cma_sysfs_account_success_pages(struct cma *cma, unsigned long nr_pages);
void cma_sysfs_account_fail_pages(struct cma *cma, unsigned long nr_pages);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 6dc4888a90f3..8eca00d30fc5 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -68,6 +68,7 @@
#include <net/ip.h>
#include "slab.h"
#include "memcontrol-v1.h"
+#include "cma.h"
#include <linux/uaccess.h>
@@ -4062,6 +4063,9 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
{
int node;
+#ifdef CONFIG_CMA
+ kfree(memcg->cma_counters);
+#endif
for_each_node(node) {
struct mem_cgroup_per_node *pn = memcg->nodeinfo[node];
if (!pn)
@@ -4144,6 +4148,15 @@ static struct mem_cgroup *mem_cgroup_alloc(struct mem_cgroup *parent)
for (i = 0; i < MEMCG_CGWB_FRN_CNT; i++)
memcg->cgwb_frn[i].done =
__WB_COMPLETION_INIT(&memcg_cgwb_frn_waitq);
+#endif
+#ifdef CONFIG_CMA
+ if (cma_area_count) {
+ memcg->cma_counters = kcalloc(cma_area_count,
+ sizeof(struct page_counter),
+ GFP_KERNEL);
+ if (!memcg->cma_counters)
+ goto fail;
+ }
#endif
lru_gen_init_memcg(memcg);
return memcg;
@@ -4159,6 +4172,7 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
struct mem_cgroup *parent = mem_cgroup_from_css(parent_css);
struct mem_cgroup *memcg, *old_memcg;
bool memcg_on_dfl = cgroup_subsys_on_dfl(memory_cgrp_subsys);
+ unsigned int __maybe_unused i;
old_memcg = set_active_memcg(parent);
memcg = mem_cgroup_alloc(parent);
@@ -4171,6 +4185,12 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
#ifdef CONFIG_ZSWAP
memcg->zswap_max = PAGE_COUNTER_MAX;
WRITE_ONCE(memcg->zswap_writeback, true);
+#endif
+#ifdef CONFIG_CMA
+ for (i = 0; i < cma_area_count; ++i)
+ page_counter_init(&memcg->cma_counters[i],
+ parent ? &parent->cma_counters[i] : NULL,
+ false);
#endif
page_counter_set_high(&memcg->swap, PAGE_COUNTER_MAX);
if (parent) {
@@ -5213,6 +5233,102 @@ int mem_cgroup_swapin_charge_folio(struct folio *folio, unsigned short id,
return ret;
}
+#ifdef CONFIG_CMA
+static bool memcg_accounts_cma(void)
+{
+ return cgrp_dfl_root.flags & CGRP_ROOT_MEMORY_CMA_ACCOUNTING;
+}
+
+int mem_cgroup_charge_cma(struct page *page, unsigned long count,
+ struct cma *cma)
+{
+ struct page_counter *counter, *fail;
+ struct obj_cgroup *objcg;
+ struct mem_cgroup *memcg;
+ unsigned int i;
+ int rc = 0;
+
+ if (mem_cgroup_disabled() || !memcg_accounts_cma())
+ return 0;
+
+ memcg = get_mem_cgroup_from_current();
+ if (!memcg)
+ return 0;
+
+ if (mem_cgroup_is_root(memcg))
+ goto cgroup_put;
+
+ rc = try_charge_memcg(memcg, GFP_KERNEL, count);
+ if (rc)
+ goto cgroup_put;
+
+ counter = &memcg->cma_counters[cma_area_index(cma)];
+ if (!page_counter_try_charge(counter, count, &fail)) {
+ refill_stock(memcg, count);
+ rc = -ENOMEM;
+ goto cgroup_put;
+ }
+
+ objcg = get_obj_cgroup_from_memcg(memcg);
+ if (folio_test_large(page_folio(page))) {
+ commit_charge(page_folio(page), objcg);
+ } else {
+ obj_cgroup_get_many(objcg, count - 1);
+ for (i = 0; i < count; i++)
+ commit_charge(page_folio(page + i), objcg);
+ }
+
+cgroup_put:
+ mem_cgroup_put(memcg);
+ return rc;
+}
+
+void mem_cgroup_uncharge_cma(struct page *page, unsigned long count,
+ struct cma *cma)
+{
+ struct page_counter *counter;
+ struct obj_cgroup *objcg;
+ struct mem_cgroup *memcg;
+ struct folio *folio;
+ unsigned int i;
+
+ if (mem_cgroup_disabled() || !memcg_accounts_cma())
+ return;
+
+ /*
+ * Get the objcg from the first page.
+ * page_objcg() expects MEMCG_DATA_KMEM, but for CMA we used
+ * commit_charge() which sets folio->memcg_data = objcg
+ * without flags, so we cannot use it.
+ */
+ objcg = folio_objcg(page_folio(page));
+ if (!objcg)
+ return;
+
+ rcu_read_lock();
+ memcg = obj_cgroup_memcg(objcg);
+
+ counter = &memcg->cma_counters[cma_area_index(cma)];
+ page_counter_uncharge(counter, count);
+
+ memcg_uncharge(memcg, count);
+
+ rcu_read_unlock();
+
+ folio = page_folio(page);
+ if (folio_test_large(folio)) {
+ folio->memcg_data = 0;
+ obj_cgroup_put(objcg);
+ } else {
+ for (i = 0; i < count; ++i) {
+ folio = page_folio(page + i);
+ folio->memcg_data = 0;
+ obj_cgroup_put(objcg);
+ }
+ }
+}
+#endif /* CONFIG_CMA */
+
struct uncharge_gather {
struct obj_cgroup *objcg;
unsigned long nr_memory;
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 05/11] mm/cma: charge cma allocation to memcg per area counters
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (3 preceding siblings ...)
2026-08-21 18:56 ` [PATCH 04/11] memcg: add cma charge/uncharge functions for area counters Eric Chanudet
@ 2026-08-21 18:56 ` Eric Chanudet
2026-08-21 18:56 ` [PATCH 06/11] memcg: register per-area usage counters in cgroupfs Eric Chanudet
` (8 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:56 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
Hook mem_cgroup_charge_cma() and mem_cgroup_uncharge_cma() into the CMA
alloc/release paths.
In __cma_alloc_frozen(), charge the pages to the current task's cgroup
if the allocation succeeds. Should charging fail (e.g, reaches a limit),
release the pages. Uncharge in __cma_release_frozen().
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
mm/cma.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/mm/cma.c b/mm/cma.c
index 03f98f6d45a5..03eb3acbd3c7 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -904,6 +904,12 @@ static struct page *__cma_alloc_frozen(struct cma *cma,
cma_debug_show_areas(cma);
}
+ if (page && mem_cgroup_charge_cma(page, count, cma)) {
+ free_contig_frozen_range(page_to_pfn(page), count);
+ cma_clear_bitmap(cma, &cma->ranges[r], page_to_pfn(page), count);
+ page = NULL;
+ }
+
pr_debug("%s(): returned %p\n", __func__, page);
trace_cma_alloc_finish(name, page ? page_to_pfn(page) : 0,
page, count, align, ret);
@@ -997,6 +1003,7 @@ static void __cma_release_frozen(struct cma *cma, struct cma_memrange *cmr,
pr_debug("%s(page %p, count %lu)\n", __func__, (void *)pages, count);
+ mem_cgroup_uncharge_cma(pages, count, cma);
free_contig_frozen_range(pfn, count);
cma_clear_bitmap(cma, cmr, pfn, count);
cma_sysfs_account_release_pages(cma, count);
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 06/11] memcg: register per-area usage counters in cgroupfs
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (4 preceding siblings ...)
2026-08-21 18:56 ` [PATCH 05/11] mm/cma: charge cma allocation to memcg per " Eric Chanudet
@ 2026-08-21 18:56 ` Eric Chanudet
2026-08-21 18:56 ` [PATCH 07/11] selftests: cgroup: add cma configs for cgroup selftest suite Eric Chanudet
` (7 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:56 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
Expose memory.cma.<area>.{current,max} files under each non-root cgroup
when cgroupfs memory_cma_accounting option is enabled.
memory.cma.<area>.current reports the cgroup's CMA usage for that area.
memory.cma.<area>.max is a read-write limit (default: max).
Each CMA area gets a cftype template with its name set from the CMA
area's name.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
Documentation/admin-guide/cgroup-v2.rst | 15 ++++++
mm/memcontrol.c | 89 +++++++++++++++++++++++++++++++++
2 files changed, 104 insertions(+)
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index 3dfc13f31a0c..39871a7a08a8 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -1928,6 +1928,21 @@ The following nested keys are defined.
This setting has no effect if zswap is disabled, and swapping
is allowed unless memory.swap.max is set to 0.
+ memory.cma.<area>.current
+ A read-only single value file which exists on non-root cgroups. <area>
+ is the CMA area name (e.g. "reserved" for the default DMA CMA area).
+
+ The total amount of CMA memory currently charged to the cgroup for the
+ given CMA area. Only accounted when memory_cma_accounting is enabled.
+
+ memory.cma.<area>.max
+ A read-write single value file which exists on non-root cgroups. The
+ default is "max".
+
+ CMA usage hard limit for the given area. If a cgroup's CMA usage for
+ this area exceeds this limit, the allocation will fail. Only enforced
+ when memory_cma_accounting is enabled.
+
memory.pressure
A read-only nested-keyed file.
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 8eca00d30fc5..f28d610a59ce 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -6182,3 +6182,92 @@ void mem_cgroup_show_protected_memory(struct mem_cgroup *memcg)
K(atomic_long_read(&memcg->memory.children_min_usage)),
K(atomic_long_read(&memcg->memory.children_low_usage)));
}
+
+#ifdef CONFIG_CMA
+static int memory_cma_current_show(struct seq_file *m, void *v)
+{
+ struct mem_cgroup *memcg = mem_cgroup_from_seq(m);
+ int idx = seq_cft(m)->private;
+ unsigned long cur = page_counter_read(&memcg->cma_counters[idx]);
+
+ seq_printf(m, "%lu\n", cur * PAGE_SIZE);
+
+ return 0;
+}
+
+static int memory_cma_max_show(struct seq_file *m, void *v)
+{
+ struct mem_cgroup *memcg = mem_cgroup_from_seq(m);
+ int idx = seq_cft(m)->private;
+ unsigned long max = READ_ONCE(memcg->cma_counters[idx].max);
+
+ return seq_puts_memcg_tunable(m, max);
+}
+
+static ssize_t memory_cma_max_write(struct kernfs_open_file *of, char *buf,
+ size_t nbytes, loff_t off)
+{
+ struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
+ int idx = of_cft(of)->private;
+ unsigned long max;
+ int rc;
+
+ buf = strstrip(buf);
+ rc = page_counter_memparse(buf, "max", &max);
+ if (rc)
+ return rc;
+
+ xchg(&memcg->cma_counters[idx].max, max);
+
+ return nbytes;
+}
+
+static struct cftype cma_dfl_tmpl[] = {
+ {
+ .name = "current",
+ .seq_show = memory_cma_current_show,
+ .flags = CFTYPE_NOT_ON_ROOT,
+ },
+ {
+ .name = "max",
+ .seq_show = memory_cma_max_show,
+ .write = memory_cma_max_write,
+ .flags = CFTYPE_NOT_ON_ROOT,
+ },
+ { }
+};
+#define CMA_DFL_TMPL_SIZE (ARRAY_SIZE(cma_dfl_tmpl) - 1)
+
+static struct cftype *cma_dfl_files;
+
+static int __init mem_cgroup_cma_init(void)
+{
+ struct cftype *cft;
+ unsigned int i, j;
+ int count;
+
+ if (mem_cgroup_disabled() || !cma_area_count)
+ return 0;
+
+ count = cma_area_count * CMA_DFL_TMPL_SIZE;
+ cma_dfl_files = kcalloc(count + 1, sizeof(*cma_dfl_tmpl), GFP_KERNEL);
+ if (!cma_dfl_files)
+ return -ENOMEM;
+
+ for (i = 0; i < cma_area_count; ++i)
+ for (j = 0; j < CMA_DFL_TMPL_SIZE; ++j) {
+ cft = &cma_dfl_files[i * CMA_DFL_TMPL_SIZE + j];
+ *cft = cma_dfl_tmpl[j];
+ snprintf(cft->name, MAX_CFTYPE_NAME, "cma.%s.%s",
+ cma_get_name(&cma_areas[i]),
+ cma_dfl_tmpl[j].name);
+ cft->private = i; /* cma area index for counters in callbacks. */
+ lockdep_register_key(&cft->lockdep_key);
+ }
+
+ WARN_ON(cgroup_add_dfl_cftypes(&memory_cgrp_subsys, cma_dfl_files));
+
+ return 0;
+}
+subsys_initcall(mem_cgroup_cma_init);
+#endif /* CONFIG_CMA */
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 07/11] selftests: cgroup: add cma configs for cgroup selftest suite
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (5 preceding siblings ...)
2026-08-21 18:56 ` [PATCH 06/11] memcg: register per-area usage counters in cgroupfs Eric Chanudet
@ 2026-08-21 18:56 ` Eric Chanudet
2026-08-21 18:57 ` [PATCH 08/11] selftests: cgroup: add memcg cma tests Eric Chanudet
` (6 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:56 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
Enable CMA and the dma-buf CMA heap. The CMA memcg tests will use the
dma-buf heap to allocate in the CMA and exercise the charge/uncharge
accounting.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
tools/testing/selftests/cgroup/config | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/testing/selftests/cgroup/config b/tools/testing/selftests/cgroup/config
index 39f979690dd3..c4f7df4f1b24 100644
--- a/tools/testing/selftests/cgroup/config
+++ b/tools/testing/selftests/cgroup/config
@@ -4,3 +4,7 @@ CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_SCHED=y
CONFIG_MEMCG=y
CONFIG_PAGE_COUNTER=y
+CONFIG_CMA=y
+CONFIG_DMA_CMA=y
+CONFIG_DMABUF_HEAPS=y
+CONFIG_DMABUF_HEAPS_CMA=y
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 08/11] selftests: cgroup: add memcg cma tests
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (6 preceding siblings ...)
2026-08-21 18:56 ` [PATCH 07/11] selftests: cgroup: add cma configs for cgroup selftest suite Eric Chanudet
@ 2026-08-21 18:57 ` Eric Chanudet
2026-08-21 18:57 ` [PATCH 09/11] selftests: cgroup: add a vmtest script for memcg Eric Chanudet
` (5 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:57 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
Add test_cma_memcg with two simple tests to exercise CMA memcg
accounting using the dma-buf CMA heap
(/dev/dma_heap/default_cma_region).
test_cma_charge allocates a 4MB buffer in the default CMA area, verifies
memory.cma.reserved.current increased by that amount, then frees the
buffer and verifies that the counter returns to its original value.
test_cma_limit sets memory.cma.reserved.max to 2MB, attempts a 4MB
allocation in the default CMA area and verifies it fails as expected.
Skip the test if memory_cma_accounting is not enabled on the cgroupfs.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
tools/testing/selftests/cgroup/.gitignore | 1 +
tools/testing/selftests/cgroup/Makefile | 2 +
tools/testing/selftests/cgroup/test_cma_memcg.c | 193 ++++++++++++++++++++++++
3 files changed, 196 insertions(+)
diff --git a/tools/testing/selftests/cgroup/.gitignore b/tools/testing/selftests/cgroup/.gitignore
index 952e4448bf07..b9a4298d4944 100644
--- a/tools/testing/selftests/cgroup/.gitignore
+++ b/tools/testing/selftests/cgroup/.gitignore
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
test_core
+test_cma_memcg
test_cpu
test_cpuset
test_freezer
diff --git a/tools/testing/selftests/cgroup/Makefile b/tools/testing/selftests/cgroup/Makefile
index e01584c2189a..601d930160a4 100644
--- a/tools/testing/selftests/cgroup/Makefile
+++ b/tools/testing/selftests/cgroup/Makefile
@@ -8,6 +8,7 @@ TEST_PROGS := test_stress.sh test_cpuset_prs.sh test_cpuset_v1_hp.sh
TEST_GEN_FILES := wait_inotify
# Keep the lists lexicographically sorted
TEST_GEN_PROGS = test_core
+TEST_GEN_PROGS += test_cma_memcg
TEST_GEN_PROGS += test_cpu
TEST_GEN_PROGS += test_cpuset
TEST_GEN_PROGS += test_freezer
@@ -24,6 +25,7 @@ include ../lib.mk
include lib/libcgroup.mk
$(OUTPUT)/test_core: $(LIBCGROUP_O)
+$(OUTPUT)/test_cma_memcg: $(LIBCGROUP_O)
$(OUTPUT)/test_cpu: $(LIBCGROUP_O)
$(OUTPUT)/test_cpuset: $(LIBCGROUP_O)
$(OUTPUT)/test_freezer: $(LIBCGROUP_O)
diff --git a/tools/testing/selftests/cgroup/test_cma_memcg.c b/tools/testing/selftests/cgroup/test_cma_memcg.c
new file mode 100644
index 000000000000..b5b5ea140518
--- /dev/null
+++ b/tools/testing/selftests/cgroup/test_cma_memcg.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+
+#include <linux/limits.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <linux/dma-heap.h>
+#include <sys/ioctl.h>
+#include "kselftest.h"
+#include "cgroup_util.h"
+
+#define CMA_HEAP_DEFAULT_PATH "/dev/dma_heap/default_cma_region"
+#define CMA_RESERVED_CURRENT "memory.cma.reserved.current"
+#define CMA_RESERVED_MAX "memory.cma.reserved.max"
+
+static int cma_heap_alloc(int heap_fd, size_t size)
+{
+ struct dma_heap_allocation_data data = {
+ .len = size,
+ .fd_flags = O_RDWR | O_CLOEXEC,
+ };
+
+ if (ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &data) < 0)
+ return -1;
+
+ return data.fd;
+}
+
+static int test_cma_charge(const char *root)
+{
+ int heap_fd = -1, buf_fd = -1;
+ int rc = KSFT_FAIL, in_cg = 0;
+ size_t size = 4UL << 20;
+ long before, after;
+ char *cg;
+
+ cg = cg_name(root, "memcg_cma_charge");
+ if (!cg)
+ goto cleanup;
+
+ if (cg_create(cg))
+ goto cleanup;
+
+ if (cg_enter_current(cg))
+ goto cleanup;
+ in_cg = 1;
+
+ heap_fd = open(CMA_HEAP_DEFAULT_PATH, O_RDONLY | O_CLOEXEC);
+ if (heap_fd < 0) {
+ ksft_print_msg("cannot open CMA heap (%m)\n");
+ goto cleanup;
+ }
+
+ before = cg_read_long(cg, CMA_RESERVED_CURRENT);
+
+ buf_fd = cma_heap_alloc(heap_fd, size);
+ if (buf_fd < 0) {
+ ksft_print_msg("cannot allocate in CMA heap (%m)\n");
+ goto cleanup;
+ }
+
+ after = cg_read_long(cg, CMA_RESERVED_CURRENT);
+
+ if (after - before < (long)size) {
+ ksft_print_msg(
+ "invalid CMA counter after charge: before=%ld after=%ld\n",
+ before, after);
+ goto cleanup;
+ }
+
+ close(buf_fd);
+ buf_fd = -1;
+
+ after = cg_read_long(cg, CMA_RESERVED_CURRENT);
+ if (!values_close(before, after, 3)) {
+ ksft_print_msg(
+ "invalid CMA counter after uncharge: before=%ld after=%ld\n",
+ before, after);
+ goto cleanup;
+ }
+
+ rc = KSFT_PASS;
+
+cleanup:
+ if (buf_fd >= 0)
+ close(buf_fd);
+ if (heap_fd >= 0)
+ close(heap_fd);
+
+ if (in_cg)
+ cg_enter_current(root);
+ cg_destroy(cg);
+ free(cg);
+
+ return rc;
+}
+
+static int test_cma_limit(const char *root)
+{
+ int heap_fd = -1, buf_fd = -1;
+ int rc = KSFT_FAIL, in_cg = 0;
+ size_t size = 4UL << 20;
+ char *cg;
+
+ cg = cg_name(root, "memcg_cma_limit");
+ if (!cg)
+ goto cleanup;
+
+ if (cg_create(cg))
+ goto cleanup;
+
+ if (cg_enter_current(cg))
+ goto cleanup;
+ in_cg = 1;
+
+ if (cg_write(cg, CMA_RESERVED_MAX, "2M")) {
+ ksft_print_msg("cannot set CMA limit (%m)\n");
+ goto cleanup;
+ }
+
+ heap_fd = open(CMA_HEAP_DEFAULT_PATH, O_RDONLY | O_CLOEXEC);
+ if (heap_fd < 0) {
+ ksft_print_msg("cannot open CMA heap (%m)\n");
+ goto cleanup;
+ }
+
+ buf_fd = cma_heap_alloc(heap_fd, size);
+ if (buf_fd >= 0) {
+ ksft_print_msg("CMA limit not enforced.\n");
+ close(buf_fd);
+ } else
+ rc = KSFT_PASS;
+
+cleanup:
+ if (heap_fd >= 0)
+ close(heap_fd);
+
+ if (in_cg)
+ cg_enter_current(root);
+ cg_destroy(cg);
+ free(cg);
+
+ return rc;
+}
+
+#define T(x) { x, #x }
+struct cma_memcg_tests {
+ int (*fn)(const char *root);
+ const char *name;
+} tests[] = {
+ T(test_cma_charge),
+ T(test_cma_limit),
+};
+#undef T
+
+int main(int argc, char *argv[])
+{
+ char root[PATH_MAX];
+ int has_memory_cma_acc, i;
+
+ ksft_print_header();
+ ksft_set_plan(ARRAY_SIZE(tests));
+
+ has_memory_cma_acc = proc_mount_contains("memory_cma_accounting");
+ if (has_memory_cma_acc < 0)
+ ksft_exit_skip("cannot query cgroup mount option.\n");
+ else if (!has_memory_cma_acc)
+ ksft_exit_skip("CMA accounting is disabled.\n");
+
+ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroupfs is not available.\n");
+
+ if (cg_read_strstr(root, "cgroup.controllers", "memory"))
+ ksft_exit_skip("memory controller is not available (CONFIG_CGROUP_MEMCG?)\n");
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+ switch (tests[i].fn(root)) {
+ case KSFT_PASS:
+ ksft_test_result_pass("%s\n", tests[i].name);
+ break;
+ case KSFT_SKIP:
+ ksft_test_result_skip("%s\n", tests[i].name);
+ break;
+ default:
+ ksft_test_result_fail("%s\n", tests[i].name);
+ break;
+ }
+ }
+
+ ksft_finished();
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 09/11] selftests: cgroup: add a vmtest script for memcg
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (7 preceding siblings ...)
2026-08-21 18:57 ` [PATCH 08/11] selftests: cgroup: add memcg cma tests Eric Chanudet
@ 2026-08-21 18:57 ` Eric Chanudet
2026-08-21 18:57 ` [PATCH 10/11] selftests: cgroup: add memcg hugetlb_cma tests Eric Chanudet
` (4 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:57 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
Following dmem's example[1], add a vmtest-memcg.sh to provide a
repeatable VM workflow using virtme-ng for memcg tests.
Boot a VM using virtme-ng with cma=64M in its kargs and enable
memory_cma_accounting on cgroupfs, then run the cgroup tests inside the
guest.
Provide -b to build the kernel first, -q to use a different qemu binary,
-s to start a shell in the VM, and -v for verbose boot.
[1] https://lore.kernel.org/all/20260706-kunit_cgroups-v5-3-6c42c8753468@redhat.com/
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
tools/testing/selftests/cgroup/vmtest-memcg.sh | 196 +++++++++++++++++++++++++
1 file changed, 196 insertions(+)
diff --git a/tools/testing/selftests/cgroup/vmtest-memcg.sh b/tools/testing/selftests/cgroup/vmtest-memcg.sh
new file mode 100755
index 000000000000..b19b96731784
--- /dev/null
+++ b/tools/testing/selftests/cgroup/vmtest-memcg.sh
@@ -0,0 +1,196 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2026 Red Hat, Inc.
+#
+# Run cgroup memory controller selftests inside a virtme-ng VM
+# Dependencies:
+# * virtme-ng
+# * busybox-static (used by virtme-ng)
+# * qemu (used by virtme-ng)
+
+set -euo pipefail
+
+readonly SCRIPT_DIR="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
+readonly KERNEL_CHECKOUT="$(realpath "${SCRIPT_DIR}"/../../../../)"
+
+source "${SCRIPT_DIR}"/../kselftest/ktap_helpers.sh
+
+readonly SSH_GUEST_PORT="${SSH_GUEST_PORT:-22}"
+readonly WAIT_PERIOD=3
+readonly WAIT_PERIOD_MAX=80
+readonly WAIT_TOTAL=$((WAIT_PERIOD * WAIT_PERIOD_MAX))
+readonly QEMU_PIDFILE="$(mktemp /tmp/qemu_memcg_vmtest_XXXX.pid)"
+readonly QEMU_OPTS=" --pidfile ${QEMU_PIDFILE} "
+
+BUILD=0
+QEMU="qemu-system-$(uname -m)"
+VERBOSE=0
+SHELL_MODE=0
+GUEST_TREE="${GUEST_TREE:-$KERNEL_CHECKOUT}"
+
+usage() {
+ cat <<EOF
+$0 [OPTIONS]
+ -b Build kernel from source tree before booting
+ -q <qemu> QEMU binary/path (default: $QEMU)
+ -s Start interactive shell in VM
+ -v Verbose output (vng boot logs on stdout)
+EOF
+ exit 1
+}
+
+die() {
+ echo "$*" >&2
+ exit "${KSFT_FAIL}"
+}
+
+cleanup() {
+ if [[ -s "$QEMU_PIDFILE" ]]; then
+ pkill -SIGTERM -F "$QEMU_PIDFILE" >/dev/null 2>&1 || true
+ fi
+
+ if [[ -e "$QEMU_PIDFILE" ]]; then
+ rm -f "$QEMU_PIDFILE"
+ fi
+}
+
+vm_ssh() {
+ stdbuf -oL ssh -q \
+ -F "$HOME/.cache/virtme-ng/.ssh/virtme-ng-ssh.conf" \
+ -l root "virtme-ng%$SSH_GUEST_PORT" \
+ "$@"
+}
+
+check_deps() {
+ for dep in vng "$QEMU" busybox pkill ssh; do
+ if ! command -v "$dep" >/dev/null 2>&1; then
+ echo "skip: dependency $dep not found"
+ exit "$KSFT_SKIP"
+ fi
+ done
+}
+
+handle_build() {
+ if [[ ! "$BUILD" -eq 1 ]]; then
+ return
+ fi
+
+ if [[ ! -d "$KERNEL_CHECKOUT" ]]; then
+ echo "-b requires $0 to be called from the kernel source tree" >&2
+ exit 1
+ fi
+
+ pushd "$KERNEL_CHECKOUT" &>/dev/null
+
+ if ! vng --kconfig --config "$SCRIPT_DIR"/config; then
+ die "failed to generate .config for kernel source tree ($KERNEL_CHECKOUT)"
+ fi
+
+ if ! make -j"$(nproc)"; then
+ die "failed to build kernel from source tree ($KERNEL_CHECKOUT)"
+ fi
+
+ popd &>/dev/null
+}
+
+vm_start() {
+ local logfile=/dev/null
+ local verbose_opt=""
+ local kernel_opt=""
+
+ if [[ "$VERBOSE" -eq 1 ]]; then
+ verbose_opt="--verbose"
+ logfile=/dev/stdout
+ fi
+
+ if [[ "$BUILD" -eq 1 ]]; then
+ kernel_opt="${KERNEL_CHECKOUT}"
+ fi
+
+ vng \
+ --run \
+ ${kernel_opt} \
+ ${verbose_opt} \
+ --qemu-opts="$QEMU_OPTS" \
+ --qemu="$(command -v "$QEMU")" \
+ --user root \
+ --ssh "$SSH_GUEST_PORT" \
+ --append "cma=64M" \
+ --rw &>"$logfile" &
+
+ local vng_pid=$!
+ local elapsed=0
+
+ while [[ ! -s "$QEMU_PIDFILE" ]]; do
+ kill -0 "$vng_pid" 2>/dev/null || \
+ die "vng exited early; failed to boot VM"
+ [[ "$elapsed" -ge "$WAIT_TOTAL" ]] && \
+ die "timed out waiting for VM boot"
+ sleep 1
+ elapsed=$((elapsed + 1))
+ done
+}
+
+vm_wait_for_ssh() {
+ local i=0
+ while true; do
+ vm_ssh -- true && break
+ i=$((i + 1))
+ [[ "${i}" -gt "$WAIT_PERIOD_MAX" ]] && \
+ die "timed out waiting for guest ssh"
+ sleep "$WAIT_PERIOD"
+ done
+}
+
+check_guest_requirements() {
+ vm_ssh -- "grep -q memory /sys/fs/cgroup/cgroup.controllers" \
+ || die "memory controller not available (CONFIG_MEMCG?)"
+ vm_ssh -- "[[ -e /dev/dma_heap/default_cma_region ]]" \
+ || die "CMA heap not available (CONFIG_DMABUF_HEAPS_CMA? cma= cmdline?)"
+}
+
+setup_guest_cma_accounting() {
+ vm_ssh -- "mount -o remount,memory_cma_accounting /sys/fs/cgroup" \
+ || die "failed to enable memory_cma_accounting"
+ vm_ssh -- "echo +memory > /sys/fs/cgroup/cgroup.subtree_control" \
+ || die "failed to enable memory controller"
+}
+
+run_test() {
+ vm_ssh -- "cd '$GUEST_TREE' && make -C tools/testing/selftests TARGETS=cgroup"
+ vm_ssh -- "cd '$GUEST_TREE' && make -C tools/testing/selftests TARGETS=cgroup run_tests"
+}
+
+while getopts ":hvq:sb" opt; do
+ case "$opt" in
+ v) VERBOSE=1 ;;
+ q) QEMU="${OPTARG}" ;;
+ b) BUILD=1 ;;
+ s) SHELL_MODE=1 ;;
+ h|*) usage ;;
+ esac
+done
+
+trap cleanup EXIT
+
+check_deps
+handle_build
+echo "Booting virtme-ng VM..."
+vm_start
+vm_wait_for_ssh
+echo "VM is reachable via SSH."
+
+if [[ "$SHELL_MODE" -eq 1 ]]; then
+ echo "Starting interactive shell in VM. Exit to stop VM."
+ vm_ssh -t -- "cd '$GUEST_TREE' && exec bash --noprofile --norc"
+ exit "$KSFT_PASS"
+fi
+
+check_guest_requirements
+setup_guest_cma_accounting
+
+echo "Running cgroup selftests in VM..."
+run_test
+echo "PASS: cgroup selftests completed"
+exit "$KSFT_PASS"
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 10/11] selftests: cgroup: add memcg hugetlb_cma tests
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (8 preceding siblings ...)
2026-08-21 18:57 ` [PATCH 09/11] selftests: cgroup: add a vmtest script for memcg Eric Chanudet
@ 2026-08-21 18:57 ` Eric Chanudet
2026-08-21 18:57 ` [PATCH 11/11] selftests: cgroup: amend vmtest-memcg to run the hugetlb cma tests Eric Chanudet
` (3 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:57 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
test_hugetlb_cma_charge gets a hugepage by incrementing nr_hugepages,
confirms memory.cma.hugetlb0.current increased as expected, then
releases it and checks the counter returns to its initial value.
test_hugetlb_cma_limit sets memory.cma.hugetlb0.max to 0, tries to
allocate a hugepage and verifies it fails.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
tools/testing/selftests/cgroup/test_cma_memcg.c | 209 ++++++++++++++++++++++++
1 file changed, 209 insertions(+)
diff --git a/tools/testing/selftests/cgroup/test_cma_memcg.c b/tools/testing/selftests/cgroup/test_cma_memcg.c
index b5b5ea140518..9bd41d9a6177 100644
--- a/tools/testing/selftests/cgroup/test_cma_memcg.c
+++ b/tools/testing/selftests/cgroup/test_cma_memcg.c
@@ -4,7 +4,9 @@
#include <linux/limits.h>
#include <sys/mman.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <dirent.h>
#include <fcntl.h>
#include <linux/dma-heap.h>
#include <sys/ioctl.h>
@@ -15,6 +17,10 @@
#define CMA_RESERVED_CURRENT "memory.cma.reserved.current"
#define CMA_RESERVED_MAX "memory.cma.reserved.max"
+#define HUGETLB_CMA_CURRENT "memory.cma.hugetlb0.current"
+#define HUGETLB_CMA_MAX "memory.cma.hugetlb0.max"
+#define HUGEPAGES_DIR "/sys/kernel/mm/hugepages"
+
static int cma_heap_alloc(int heap_fd, size_t size)
{
struct dma_heap_allocation_data data = {
@@ -145,6 +151,207 @@ static int test_cma_limit(const char *root)
return rc;
}
+static long find_largest_hugepage_size_kb(void)
+{
+ DIR *dir;
+ struct dirent *entry;
+ long max_size = 0;
+
+ dir = opendir(HUGEPAGES_DIR);
+ if (!dir)
+ return -1;
+
+ while ((entry = readdir(dir)) != NULL) {
+ long size;
+
+ if (sscanf(entry->d_name, "hugepages-%ldkB", &size) == 1) {
+ if (size > max_size)
+ max_size = size;
+ }
+ }
+ closedir(dir);
+
+ return max_size > 0 ? max_size : -1;
+}
+
+static long read_sysfs_long(const char *path)
+{
+ FILE *f;
+ long val = -1;
+
+ f = fopen(path, "r");
+ if (!f)
+ return -1;
+ if (fscanf(f, "%ld", &val) != 1)
+ val = -1;
+ fclose(f);
+ return val;
+}
+
+static int write_sysfs_long(const char *path, long val)
+{
+ FILE *f;
+ int rc;
+
+ f = fopen(path, "w");
+ if (!f)
+ return -1;
+ rc = fprintf(f, "%ld", val);
+ fclose(f);
+ return rc < 0 ? -1 : 0;
+}
+
+static int test_hugetlb_cma_charge(const char *root)
+{
+ int rc = KSFT_SKIP, in_cg = 0;
+ long hpage_size_kb, hpage_size_bytes;
+ long orig_nr = -1, new_nr, before, after;
+ char nr_path[PATH_MAX];
+ char *cg;
+
+ hpage_size_kb = find_largest_hugepage_size_kb();
+ if (hpage_size_kb < 0) {
+ ksft_print_msg("no hugepage size found\n");
+ return KSFT_SKIP;
+ }
+ hpage_size_bytes = hpage_size_kb * 1024;
+
+ snprintf(nr_path, sizeof(nr_path),
+ HUGEPAGES_DIR "/hugepages-%ldkB/nr_hugepages", hpage_size_kb);
+
+ cg = cg_name(root, "memcg_hugetlb_cma_charge");
+ if (!cg)
+ goto cleanup;
+
+ if (cg_create(cg))
+ goto cleanup;
+
+ if (cg_enter_current(cg))
+ goto cleanup;
+ in_cg = 1;
+
+ if (cg_read_long(cg, HUGETLB_CMA_CURRENT) < 0) {
+ ksft_print_msg("hugetlb CMA counters not available\n");
+ goto cleanup;
+ }
+
+ orig_nr = read_sysfs_long(nr_path);
+ if (orig_nr < 0) {
+ ksft_print_msg("cannot read %s\n", nr_path);
+ goto cleanup;
+ }
+
+ before = cg_read_long(cg, HUGETLB_CMA_CURRENT);
+
+ if (write_sysfs_long(nr_path, orig_nr + 1)) {
+ ksft_print_msg("cannot write %s\n", nr_path);
+ goto cleanup;
+ }
+
+ new_nr = read_sysfs_long(nr_path);
+ if (new_nr <= orig_nr) {
+ ksft_print_msg("failed to allocate a hugepage\n");
+ goto cleanup;
+ }
+
+ rc = KSFT_FAIL;
+ after = cg_read_long(cg, HUGETLB_CMA_CURRENT);
+
+ if (after - before < hpage_size_bytes) {
+ ksft_print_msg(
+ "hugetlb CMA counter not charged: before=%ld after=%ld expected +%ld\n",
+ before, after, hpage_size_bytes);
+ goto cleanup;
+ }
+
+ write_sysfs_long(nr_path, orig_nr);
+
+ after = cg_read_long(cg, HUGETLB_CMA_CURRENT);
+ if (!values_close(before, after, 3)) {
+ ksft_print_msg(
+ "hugetlb CMA counter not uncharged: before=%ld after=%ld\n",
+ before, after);
+ goto cleanup;
+ }
+
+ rc = KSFT_PASS;
+
+cleanup:
+ if (orig_nr >= 0)
+ write_sysfs_long(nr_path, orig_nr);
+
+ if (in_cg)
+ cg_enter_current(root);
+ cg_destroy(cg);
+ free(cg);
+
+ return rc;
+}
+
+static int test_hugetlb_cma_limit(const char *root)
+{
+ int rc = KSFT_SKIP, in_cg = 0;
+ long hpage_size_kb;
+ long orig_nr, new_nr;
+ char nr_path[PATH_MAX];
+ char *cg;
+
+ hpage_size_kb = find_largest_hugepage_size_kb();
+ if (hpage_size_kb < 0) {
+ ksft_print_msg("no hugepage size found\n");
+ return KSFT_SKIP;
+ }
+
+ snprintf(nr_path, sizeof(nr_path),
+ HUGEPAGES_DIR "/hugepages-%ldkB/nr_hugepages", hpage_size_kb);
+
+ cg = cg_name(root, "memcg_hugetlb_cma_limit");
+ if (!cg)
+ goto cleanup;
+
+ if (cg_create(cg))
+ goto cleanup;
+
+ if (cg_enter_current(cg))
+ goto cleanup;
+ in_cg = 1;
+
+ if (cg_read_long(cg, HUGETLB_CMA_MAX) < 0) {
+ ksft_print_msg("hugetlb CMA counters not available\n");
+ goto cleanup;
+ }
+
+ if (cg_write(cg, HUGETLB_CMA_MAX, "0")) {
+ ksft_print_msg("cannot set hugetlb CMA limit\n");
+ goto cleanup;
+ }
+
+ orig_nr = read_sysfs_long(nr_path);
+ if (orig_nr < 0) {
+ ksft_print_msg("cannot read %s\n", nr_path);
+ goto cleanup;
+ }
+
+ write_sysfs_long(nr_path, orig_nr + 1);
+ new_nr = read_sysfs_long(nr_path);
+
+ rc = KSFT_FAIL;
+ if (new_nr > orig_nr) {
+ ksft_print_msg("hugetlb CMA limit not enforced\n");
+ write_sysfs_long(nr_path, orig_nr);
+ } else {
+ rc = KSFT_PASS;
+ }
+
+cleanup:
+ if (in_cg)
+ cg_enter_current(root);
+ cg_destroy(cg);
+ free(cg);
+
+ return rc;
+}
+
#define T(x) { x, #x }
struct cma_memcg_tests {
int (*fn)(const char *root);
@@ -152,6 +359,8 @@ struct cma_memcg_tests {
} tests[] = {
T(test_cma_charge),
T(test_cma_limit),
+ T(test_hugetlb_cma_charge),
+ T(test_hugetlb_cma_limit),
};
#undef T
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 11/11] selftests: cgroup: amend vmtest-memcg to run the hugetlb cma tests
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (9 preceding siblings ...)
2026-08-21 18:57 ` [PATCH 10/11] selftests: cgroup: add memcg hugetlb_cma tests Eric Chanudet
@ 2026-08-21 18:57 ` Eric Chanudet
2026-08-23 7:02 ` [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Mike Rapoport
` (2 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-21 18:57 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan
Cc: linux-mm, linux-kernel, cgroups, linux-doc, linux-kselftest,
Maxime Ripard, Albert Esteve, Eric Chanudet
Add HUGETLBFS to the selftest configuration. Amend the vmtest script to
pass hugetlb_cma=1G and hugetlb_cma_only=1. In order for hugepages to be
available, ask qemu for 3G of memory so the CMA reservation succeeds.
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
tools/testing/selftests/cgroup/config | 1 +
tools/testing/selftests/cgroup/vmtest-memcg.sh | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/cgroup/config b/tools/testing/selftests/cgroup/config
index c4f7df4f1b24..1c9034017682 100644
--- a/tools/testing/selftests/cgroup/config
+++ b/tools/testing/selftests/cgroup/config
@@ -8,3 +8,4 @@ CONFIG_CMA=y
CONFIG_DMA_CMA=y
CONFIG_DMABUF_HEAPS=y
CONFIG_DMABUF_HEAPS_CMA=y
+CONFIG_HUGETLBFS=y
diff --git a/tools/testing/selftests/cgroup/vmtest-memcg.sh b/tools/testing/selftests/cgroup/vmtest-memcg.sh
index b19b96731784..534a95ef5e07 100755
--- a/tools/testing/selftests/cgroup/vmtest-memcg.sh
+++ b/tools/testing/selftests/cgroup/vmtest-memcg.sh
@@ -116,7 +116,8 @@ vm_start() {
--qemu="$(command -v "$QEMU")" \
--user root \
--ssh "$SSH_GUEST_PORT" \
- --append "cma=64M" \
+ --memory 3G \
+ --append "cma=64M hugetlb_cma=1G hugetlb_cma_only=1" \
--rw &>"$logfile" &
local vng_pid=$!
--
2.53.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (10 preceding siblings ...)
2026-08-21 18:57 ` [PATCH 11/11] selftests: cgroup: amend vmtest-memcg to run the hugetlb cma tests Eric Chanudet
@ 2026-08-23 7:02 ` Mike Rapoport
2026-08-24 21:58 ` Eric Chanudet
2026-08-24 8:58 ` Michal Hocko
2026-08-24 13:18 ` Michal Koutný
13 siblings, 1 reply; 26+ messages in thread
From: Mike Rapoport @ 2026-08-23 7:02 UTC (permalink / raw)
To: Eric Chanudet
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Suren Baghdasaryan,
Michal Hocko, Tejun Heo, Johannes Weiner, Michal Koutný,
Jonathan Corbet, Shuah Khan, Michal Hocko, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
Hi Eric,
On Fri, Aug 21, 2026 at 02:56:52PM -0400, Eric Chanudet wrote:
> CMA allocations are currently unaccounted for by cgroup memory
> controllers. As system resources, they should fall under memcg, but CMA
> areas partition the available space for different purposes and memcg
> doesn't have a good representation for that.
>
> Add a memory_cma_accounting cgroupfs option in preparation for the
> following new behavior. Make it disabled by default since it will
> account for CMA allocations in memcg which may affect existing systems.
>
> Provide CMA charge/uncharge functions to memcg that introduce a CMA area
> specific counter per CMA area. Charges are issued to memcg and to a page
> counter for the CMA area used. The allocation's folios are marked with
> the cgroup via commit_charge() (once for large folios, per-page for
> 0-order ones) so they can be later uncharged correctly.
>
> Add the new memcg calls into the cma allocator under __cma_alloc_frozen,
> for both cma and hugetlb_cma allocations accounting.
>
> Finally register the per-area usage counters in the cgroupfs. Each CMA
> area creates a memory.cma.<area>.{current,max} pair for reporting and
> limitation for each area.
>
> Selftests and a vmtest script are added to this series for convenience.
> The tests are simple accounting and limit enforcement verification using
> the default reserved CMA area (cma=) and hugetlb_cma.
>
> Signed-off-by: Eric Chanudet <echanude@redhat.com>
> ---
> Eric Chanudet (11):
> mm/cma: drop const for struct page on release API
> mm/cma: include linux/cma.h in cma.h
> cgroup: add memory_cma_accounting mount option
> memcg: add cma charge/uncharge functions for area counters
> mm/cma: charge cma allocation to memcg per area counters
> memcg: register per-area usage counters in cgroupfs
> selftests: cgroup: add cma configs for cgroup selftest suite
> selftests: cgroup: add memcg cma tests
> selftests: cgroup: add a vmtest script for memcg
> selftests: cgroup: add memcg hugetlb_cma tests
> selftests: cgroup: amend vmtest-memcg to run the hugetlb cma tests
CI found issues:
https://github.com/linux-mm/linux-mm/actions/runs/32519133924
> Documentation/admin-guide/cgroup-v2.rst | 35 +++
> include/linux/cgroup-defs.h | 5 +
> include/linux/cma.h | 4 +-
> include/linux/memcontrol.h | 19 ++
> kernel/cgroup/cgroup.c | 15 +-
> mm/cma.c | 14 +-
> mm/cma.h | 6 +
> mm/cma_debug.c | 1 -
> mm/cma_sysfs.c | 1 -
> mm/memcontrol.c | 205 ++++++++++++
> tools/testing/selftests/cgroup/.gitignore | 1 +
> tools/testing/selftests/cgroup/Makefile | 2 +
> tools/testing/selftests/cgroup/config | 5 +
> tools/testing/selftests/cgroup/test_cma_memcg.c | 402 ++++++++++++++++++++++++
> tools/testing/selftests/cgroup/vmtest-memcg.sh | 197 ++++++++++++
> 15 files changed, 903 insertions(+), 9 deletions(-)
> ---
> base-commit: 98f21c54f99519329c18e2625b0ea6db14524d09
> change-id: 20260706-cma-memcg-regions-696cb5ef7998
>
> Best regards,
> --
> Eric Chanudet <echanude@redhat.com>
>
--
Sincerely yours,
Mike.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 03/11] cgroup: add memory_cma_accounting mount option
2026-08-21 18:56 ` [PATCH 03/11] cgroup: add memory_cma_accounting mount option Eric Chanudet
@ 2026-08-24 7:02 ` Maxime Ripard
2026-08-24 22:03 ` Eric Chanudet
0 siblings, 1 reply; 26+ messages in thread
From: Maxime Ripard @ 2026-08-24 7:02 UTC (permalink / raw)
To: Eric Chanudet
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan, linux-mm,
linux-kernel, cgroups, linux-doc, linux-kselftest, Albert Esteve
[-- Attachment #1: Type: text/plain, Size: 1925 bytes --]
On Fri, Aug 21, 2026 at 02:56:55PM -0400, Eric Chanudet wrote:
> Add a cgroup v2 mount option that will be used later in this series to
> enable CMA memory accounting under memcg.
>
> The option is made opt-in as it will charge allocations to the cgroup's
> overall memory usage, which changes existing expectations.
>
> Signed-off-by: Eric Chanudet <echanude@redhat.com>
> ---
> Documentation/admin-guide/cgroup-v2.rst | 20 ++++++++++++++++++++
> include/linux/cgroup-defs.h | 5 +++++
> kernel/cgroup/cgroup.c | 15 ++++++++++++++-
> 3 files changed, 39 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
> index aed195a71cbf..3dfc13f31a0c 100644
> --- a/Documentation/admin-guide/cgroup-v2.rst
> +++ b/Documentation/admin-guide/cgroup-v2.rst
> @@ -246,6 +246,26 @@ cgroup v2 currently supports the following mount options.
> will not be tracked by the memory controller (even if cgroup
> v2 is remounted later on).
>
> + memory_cma_accounting
> + Count CMA memory usage towards the cgroup's overall memory usage for
> + the memory controller, and expose per-CMA-area usage counters. This
> + behavior is opt-in, so as to not cause regression on existing setups.
> +
> + A few caveats to keep in mind:
> +
> + * CMA areas are reserved at boot time, memory is only charged to a
> + cgroup when a CMA allocation is performed on its behalf.
> + * CMA pages allocated while this option is not enabled will not be
> + tracked by the memory controller, even if cgroup v2 is remounted
> + later on with this option. Charges happen at allocation.
And what would happen if it's the other way around, ie mounted with this
option enabled, then remounted with the option disabled?
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (11 preceding siblings ...)
2026-08-23 7:02 ` [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Mike Rapoport
@ 2026-08-24 8:58 ` Michal Hocko
2026-08-25 14:47 ` Eric Chanudet
2026-08-24 13:18 ` Michal Koutný
13 siblings, 1 reply; 26+ messages in thread
From: Michal Hocko @ 2026-08-24 8:58 UTC (permalink / raw)
To: Eric Chanudet
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
On Fri 21-08-26 14:56:52, Eric Chanudet wrote:
> CMA allocations are currently unaccounted for by cgroup memory
> controllers. As system resources, they should fall under memcg, but CMA
> areas partition the available space for different purposes and memcg
> doesn't have a good representation for that.
Which CMA usecases are covered by this work? It would be also great to
spend more time describing usecases.
--
Michal Hocko
SUSE Labs
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
` (12 preceding siblings ...)
2026-08-24 8:58 ` Michal Hocko
@ 2026-08-24 13:18 ` Michal Koutný
2026-08-25 14:54 ` Eric Chanudet
13 siblings, 1 reply; 26+ messages in thread
From: Michal Koutný @ 2026-08-24 13:18 UTC (permalink / raw)
To: Eric Chanudet
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Jonathan Corbet, Shuah Khan, Michal Hocko, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
[-- Attachment #1: Type: text/plain, Size: 418 bytes --]
Hi Eric.
On Fri, Aug 21, 2026 at 02:56:52PM -0400, Eric Chanudet <echanude@redhat.com> wrote:
> Finally register the per-area usage counters in the cgroupfs. Each CMA
> area creates a memory.cma.<area>.{current,max} pair for reporting and
> limitation for each area.
These areas quite resemble dmem regions.
What is the relation to the previous dmem double-charging [1]?
(Successor, alternative,...)
Thanks,
Michal
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-23 7:02 ` [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Mike Rapoport
@ 2026-08-24 21:58 ` Eric Chanudet
2026-08-25 7:40 ` Michal Hocko
0 siblings, 1 reply; 26+ messages in thread
From: Eric Chanudet @ 2026-08-24 21:58 UTC (permalink / raw)
To: Mike Rapoport
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Suren Baghdasaryan,
Michal Hocko, Tejun Heo, Johannes Weiner, Michal Koutný,
Jonathan Corbet, Shuah Khan, Michal Hocko, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
On Sun, Aug 23, 2026 at 10:02:35AM +0300, Mike Rapoport wrote:
> Hi Eric,
>
> On Fri, Aug 21, 2026 at 02:56:52PM -0400, Eric Chanudet wrote:
> > CMA allocations are currently unaccounted for by cgroup memory
> > controllers. As system resources, they should fall under memcg, but CMA
> > areas partition the available space for different purposes and memcg
> > doesn't have a good representation for that.
> >
> > Add a memory_cma_accounting cgroupfs option in preparation for the
> > following new behavior. Make it disabled by default since it will
> > account for CMA allocations in memcg which may affect existing systems.
> >
> > Provide CMA charge/uncharge functions to memcg that introduce a CMA area
> > specific counter per CMA area. Charges are issued to memcg and to a page
> > counter for the CMA area used. The allocation's folios are marked with
> > the cgroup via commit_charge() (once for large folios, per-page for
> > 0-order ones) so they can be later uncharged correctly.
> >
> > Add the new memcg calls into the cma allocator under __cma_alloc_frozen,
> > for both cma and hugetlb_cma allocations accounting.
> >
> > Finally register the per-area usage counters in the cgroupfs. Each CMA
> > area creates a memory.cma.<area>.{current,max} pair for reporting and
> > limitation for each area.
> >
> > Selftests and a vmtest script are added to this series for convenience.
> > The tests are simple accounting and limit enforcement verification using
> > the default reserved CMA area (cma=) and hugetlb_cma.
> >
> > Signed-off-by: Eric Chanudet <echanude@redhat.com>
> > ---
> > Eric Chanudet (11):
> > mm/cma: drop const for struct page on release API
> > mm/cma: include linux/cma.h in cma.h
> > cgroup: add memory_cma_accounting mount option
> > memcg: add cma charge/uncharge functions for area counters
> > mm/cma: charge cma allocation to memcg per area counters
> > memcg: register per-area usage counters in cgroupfs
> > selftests: cgroup: add cma configs for cgroup selftest suite
> > selftests: cgroup: add memcg cma tests
> > selftests: cgroup: add a vmtest script for memcg
> > selftests: cgroup: add memcg hugetlb_cma tests
> > selftests: cgroup: amend vmtest-memcg to run the hugetlb cma tests
>
> CI found issues:
>
> https://github.com/linux-mm/linux-mm/actions/runs/32519133924
Indeed my apologies, I messed up CMA=n it needed a forward declaration
and gating for mm/cma.h content included in mm/memcontrol.c.
I queued this up for a v2, with the other issues reported by Sashiko.
>
> > Documentation/admin-guide/cgroup-v2.rst | 35 +++
> > include/linux/cgroup-defs.h | 5 +
> > include/linux/cma.h | 4 +-
> > include/linux/memcontrol.h | 19 ++
> > kernel/cgroup/cgroup.c | 15 +-
> > mm/cma.c | 14 +-
> > mm/cma.h | 6 +
> > mm/cma_debug.c | 1 -
> > mm/cma_sysfs.c | 1 -
> > mm/memcontrol.c | 205 ++++++++++++
> > tools/testing/selftests/cgroup/.gitignore | 1 +
> > tools/testing/selftests/cgroup/Makefile | 2 +
> > tools/testing/selftests/cgroup/config | 5 +
> > tools/testing/selftests/cgroup/test_cma_memcg.c | 402 ++++++++++++++++++++++++
> > tools/testing/selftests/cgroup/vmtest-memcg.sh | 197 ++++++++++++
> > 15 files changed, 903 insertions(+), 9 deletions(-)
> > ---
> > base-commit: 98f21c54f99519329c18e2625b0ea6db14524d09
> > change-id: 20260706-cma-memcg-regions-696cb5ef7998
> >
> > Best regards,
> > --
> > Eric Chanudet <echanude@redhat.com>
> >
>
> --
> Sincerely yours,
> Mike.
>
--
Eric Chanudet
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 03/11] cgroup: add memory_cma_accounting mount option
2026-08-24 7:02 ` Maxime Ripard
@ 2026-08-24 22:03 ` Eric Chanudet
0 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-24 22:03 UTC (permalink / raw)
To: Maxime Ripard
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Michal Hocko,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan, linux-mm,
linux-kernel, cgroups, linux-doc, linux-kselftest, Albert Esteve
On Mon, Aug 24, 2026 at 09:02:30AM +0200, Maxime Ripard wrote:
> On Fri, Aug 21, 2026 at 02:56:55PM -0400, Eric Chanudet wrote:
> > Add a cgroup v2 mount option that will be used later in this series to
> > enable CMA memory accounting under memcg.
> >
> > The option is made opt-in as it will charge allocations to the cgroup's
> > overall memory usage, which changes existing expectations.
> >
> > Signed-off-by: Eric Chanudet <echanude@redhat.com>
> > ---
> > Documentation/admin-guide/cgroup-v2.rst | 20 ++++++++++++++++++++
> > include/linux/cgroup-defs.h | 5 +++++
> > kernel/cgroup/cgroup.c | 15 ++++++++++++++-
> > 3 files changed, 39 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
> > index aed195a71cbf..3dfc13f31a0c 100644
> > --- a/Documentation/admin-guide/cgroup-v2.rst
> > +++ b/Documentation/admin-guide/cgroup-v2.rst
> > @@ -246,6 +246,26 @@ cgroup v2 currently supports the following mount options.
> > will not be tracked by the memory controller (even if cgroup
> > v2 is remounted later on).
> >
> > + memory_cma_accounting
> > + Count CMA memory usage towards the cgroup's overall memory usage for
> > + the memory controller, and expose per-CMA-area usage counters. This
> > + behavior is opt-in, so as to not cause regression on existing setups.
> > +
> > + A few caveats to keep in mind:
> > +
> > + * CMA areas are reserved at boot time, memory is only charged to a
> > + cgroup when a CMA allocation is performed on its behalf.
> > + * CMA pages allocated while this option is not enabled will not be
> > + tracked by the memory controller, even if cgroup v2 is remounted
> > + later on with this option. Charges happen at allocation.
>
> And what would happen if it's the other way around, ie mounted with this
> option enabled, then remounted with the option disabled?
I meant for it to have no more charge issued until remounted with the
option enabled. Pages that have been charged are uncharged when
released, even if memory_cma_accounting is disabled after the charge is
issued. In this version, it is broken[1].
I extended the documentation line with the fix for a potential v2.
[1]https://lore.kernel.org/sashiko-reviews/aoi_OHVZjsY9a9VV@echanude-thinkpadx1carbongen13.rmtusma.csb/
--
Eric Chanudet
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-24 21:58 ` Eric Chanudet
@ 2026-08-25 7:40 ` Michal Hocko
0 siblings, 0 replies; 26+ messages in thread
From: Michal Hocko @ 2026-08-25 7:40 UTC (permalink / raw)
To: Eric Chanudet
Cc: Mike Rapoport, Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Suren Baghdasaryan, Tejun Heo,
Johannes Weiner, Michal Koutný, Jonathan Corbet, Shuah Khan,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan, linux-mm,
linux-kernel, cgroups, linux-doc, linux-kselftest, Maxime Ripard,
Albert Esteve
On Mon 24-08-26 17:58:49, Eric Chanudet wrote:
> On Sun, Aug 23, 2026 at 10:02:35AM +0300, Mike Rapoport wrote:
[...]
> > CI found issues:
> >
> > https://github.com/linux-mm/linux-mm/actions/runs/32519133924
>
> Indeed my apologies, I messed up CMA=n it needed a forward declaration
> and gating for mm/cma.h content included in mm/memcontrol.c.
>
> I queued this up for a v2, with the other issues reported by Sashiko.
Let's focus on the highlevel design and usecase disussion first before
you start chasing specific implementation details.
--
Michal Hocko
SUSE Labs
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-24 8:58 ` Michal Hocko
@ 2026-08-25 14:47 ` Eric Chanudet
2026-08-25 14:59 ` Michal Hocko
2026-08-25 15:45 ` David Hildenbrand (Arm)
0 siblings, 2 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-25 14:47 UTC (permalink / raw)
To: Michal Hocko
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
On Mon, Aug 24, 2026 at 10:58:18AM +0200, Michal Hocko wrote:
> On Fri 21-08-26 14:56:52, Eric Chanudet wrote:
> > CMA allocations are currently unaccounted for by cgroup memory
> > controllers. As system resources, they should fall under memcg, but CMA
> > areas partition the available space for different purposes and memcg
> > doesn't have a good representation for that.
>
> Which CMA usecases are covered by this work? It would be also great to
> spend more time describing usecases.
We would like to offer some usage guaranties to userspace processes
ending up doing allocations in CMA.
For example, a shared CMA area is described in device-tree for an ARM64
platforms. Userspace components could then, for example, allocate from
it through the dmabuf heap, or a device or framework-specific ioctl for
that matter, to use the buffer with sensors. The dtb may have other CMA
areas described additionally that may or may not be used by that
component. In this context, we would like the ability to limit one of
the userspace component to over-allocate and choke the other(s). memcg
looked like a good fit to achieve this, albeit handling the areas, so a
cgroup has a quota in a given CMA resource.
This trails from an earlier post where we tried doing this using
dmem[1], but I was unable to reconcile the requirement for memcg
accounting[2] since from dmem I didn't have memory objects to charge nor
the guaranty there was one. Given CMA is always system memory, it looked
like a better fit to try something without dmem.
Best,
[1] https://lore.kernel.org/all/20260519-cgroup-dmem-memcg-double-charge-v2-0-db4d1407062b@redhat.com/
[2] https://lore.kernel.org/all/ahB7pCu_G4vuswc0@linux.dev/
> --
> Michal Hocko
> SUSE Labs
>
--
Eric Chanudet
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-24 13:18 ` Michal Koutný
@ 2026-08-25 14:54 ` Eric Chanudet
0 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-25 14:54 UTC (permalink / raw)
To: Michal Koutný
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Tejun Heo, Johannes Weiner,
Jonathan Corbet, Shuah Khan, Michal Hocko, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
On Mon, Aug 24, 2026 at 03:18:54PM +0200, Michal Koutný wrote:
> Hi Eric.
>
> On Fri, Aug 21, 2026 at 02:56:52PM -0400, Eric Chanudet <echanude@redhat.com> wrote:
> > Finally register the per-area usage counters in the cgroupfs. Each CMA
> > area creates a memory.cma.<area>.{current,max} pair for reporting and
> > limitation for each area.
>
> These areas quite resemble dmem regions.
> What is the relation to the previous dmem double-charging [1]?
> (Successor, alternative,...)
They are, although I did not make it clear in the cover letter, my bad.
This is a CMA centric alternative to the other series that tried to
issue the memcg charge through dmem[1]. CMA seemed to better fit under
memcg directly as I couldn't find a solution on how to correctly charge
memcg once in dmem where it was determined to double-charge or not.
[1] https://lore.kernel.org/all/20260519-cgroup-dmem-memcg-double-charge-v2-0-db4d1407062b@redhat.com/
>
> Thanks,
> Michal
--
Eric Chanudet
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-25 14:47 ` Eric Chanudet
@ 2026-08-25 14:59 ` Michal Hocko
2026-08-25 18:33 ` Eric Chanudet
2026-08-25 15:45 ` David Hildenbrand (Arm)
1 sibling, 1 reply; 26+ messages in thread
From: Michal Hocko @ 2026-08-25 14:59 UTC (permalink / raw)
To: Eric Chanudet
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
On Tue 25-08-26 10:47:53, Eric Chanudet wrote:
> On Mon, Aug 24, 2026 at 10:58:18AM +0200, Michal Hocko wrote:
> > On Fri 21-08-26 14:56:52, Eric Chanudet wrote:
> > > CMA allocations are currently unaccounted for by cgroup memory
> > > controllers. As system resources, they should fall under memcg, but CMA
> > > areas partition the available space for different purposes and memcg
> > > doesn't have a good representation for that.
> >
> > Which CMA usecases are covered by this work? It would be also great to
> > spend more time describing usecases.
>
> We would like to offer some usage guaranties to userspace processes
> ending up doing allocations in CMA.
>
> For example, a shared CMA area is described in device-tree for an ARM64
> platforms. Userspace components could then, for example, allocate from
> it through the dmabuf heap, or a device or framework-specific ioctl for
> that matter, to use the buffer with sensors. The dtb may have other CMA
> areas described additionally that may or may not be used by that
> component. In this context, we would like the ability to limit one of
> the userspace component to over-allocate and choke the other(s).
How exactly is this supposed to work? How is the CMA access controled
and opted in for accounting. What happens when memcg limits are hit. And
many more details, please.
> memcg
> looked like a good fit to achieve this, albeit handling the areas, so a
> cgroup has a quota in a given CMA resource.
Please expand more on why do you think this fits into the memcg model.
AFAIU we are talking about a unreclaimable memory and reservations of
CMA areas.
> This trails from an earlier post where we tried doing this using
> dmem[1], but I was unable to reconcile the requirement for memcg
> accounting[2] since from dmem I didn't have memory objects to charge nor
> the guaranty there was one. Given CMA is always system memory, it looked
> like a better fit to try something without dmem.
>
> Best,
>
> [1] https://lore.kernel.org/all/20260519-cgroup-dmem-memcg-double-charge-v2-0-db4d1407062b@redhat.com/
> [2] https://lore.kernel.org/all/ahB7pCu_G4vuswc0@linux.dev/
>
> > --
> > Michal Hocko
> > SUSE Labs
> >
>
> --
> Eric Chanudet
--
Michal Hocko
SUSE Labs
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-25 14:47 ` Eric Chanudet
2026-08-25 14:59 ` Michal Hocko
@ 2026-08-25 15:45 ` David Hildenbrand (Arm)
2026-08-25 16:26 ` Michal Hocko
1 sibling, 1 reply; 26+ messages in thread
From: David Hildenbrand (Arm) @ 2026-08-25 15:45 UTC (permalink / raw)
To: Eric Chanudet, Michal Hocko
Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
On 8/25/26 16:47, Eric Chanudet wrote:
> On Mon, Aug 24, 2026 at 10:58:18AM +0200, Michal Hocko wrote:
>> On Fri 21-08-26 14:56:52, Eric Chanudet wrote:
>>> CMA allocations are currently unaccounted for by cgroup memory
>>> controllers. As system resources, they should fall under memcg, but CMA
>>> areas partition the available space for different purposes and memcg
>>> doesn't have a good representation for that.
>>
>> Which CMA usecases are covered by this work? It would be also great to
>> spend more time describing usecases.
>
> We would like to offer some usage guaranties to userspace processes
> ending up doing allocations in CMA.
How does this e.g., relate to hugetlb allocating from CMA, to then charge to a
hugetlb cgroup?
I always thought of CMA being a low-level allocation mechanism with various
different use cases, and actually the higher-level users should decide how
to/what to charge instead.
--
Cheers,
David
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-25 15:45 ` David Hildenbrand (Arm)
@ 2026-08-25 16:26 ` Michal Hocko
2026-08-25 18:50 ` Eric Chanudet
0 siblings, 1 reply; 26+ messages in thread
From: Michal Hocko @ 2026-08-25 16:26 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Eric Chanudet, Andrew Morton, Lorenzo Stoakes, Liam R. Howlett,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Tejun Heo,
Johannes Weiner, Michal Koutný, Jonathan Corbet, Shuah Khan,
Roman Gushchin, Shakeel Butt, Muchun Song, Shuah Khan, linux-mm,
linux-kernel, cgroups, linux-doc, linux-kselftest, Maxime Ripard,
Albert Esteve
On Tue 25-08-26 17:45:56, David Hildenbrand wrote:
> On 8/25/26 16:47, Eric Chanudet wrote:
> > On Mon, Aug 24, 2026 at 10:58:18AM +0200, Michal Hocko wrote:
> >> On Fri 21-08-26 14:56:52, Eric Chanudet wrote:
> >>> CMA allocations are currently unaccounted for by cgroup memory
> >>> controllers. As system resources, they should fall under memcg, but CMA
> >>> areas partition the available space for different purposes and memcg
> >>> doesn't have a good representation for that.
> >>
> >> Which CMA usecases are covered by this work? It would be also great to
> >> spend more time describing usecases.
> >
> > We would like to offer some usage guaranties to userspace processes
> > ending up doing allocations in CMA.
>
> How does this e.g., relate to hugetlb allocating from CMA, to then charge to a
> hugetlb cgroup?
>
> I always thought of CMA being a low-level allocation mechanism with various
> different use cases, and actually the higher-level users should decide how
> to/what to charge instead.
Exactly. There are many different users of CMA all with different
requirements. Then there is CMA reservations if an area is shared and
the overall memory consumption. That is why I am really not able to
wrap my head around this proposal.
--
Michal Hocko
SUSE Labs
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-25 14:59 ` Michal Hocko
@ 2026-08-25 18:33 ` Eric Chanudet
0 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-25 18:33 UTC (permalink / raw)
To: Michal Hocko
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
On Tue, Aug 25, 2026 at 04:59:52PM +0200, Michal Hocko wrote:
> On Tue 25-08-26 10:47:53, Eric Chanudet wrote:
> > On Mon, Aug 24, 2026 at 10:58:18AM +0200, Michal Hocko wrote:
> > > On Fri 21-08-26 14:56:52, Eric Chanudet wrote:
> > > > CMA allocations are currently unaccounted for by cgroup memory
> > > > controllers. As system resources, they should fall under memcg, but CMA
> > > > areas partition the available space for different purposes and memcg
> > > > doesn't have a good representation for that.
> > >
> > > Which CMA usecases are covered by this work? It would be also great to
> > > spend more time describing usecases.
> >
> > We would like to offer some usage guaranties to userspace processes
> > ending up doing allocations in CMA.
> >
> > For example, a shared CMA area is described in device-tree for an ARM64
> > platforms. Userspace components could then, for example, allocate from
> > it through the dmabuf heap, or a device or framework-specific ioctl for
> > that matter, to use the buffer with sensors. The dtb may have other CMA
> > areas described additionally that may or may not be used by that
> > component. In this context, we would like the ability to limit one of
> > the userspace component to over-allocate and choke the other(s).
>
> How exactly is this supposed to work? How is the CMA access controled
> and opted in for accounting. What happens when memcg limits are hit. And
> many more details, please.
>
The administrator opts in by mounting cgroupfs with
memory_cma_accounting. At which point the cma allocator will charge CMA
allocations against memcg and manages a per area counter depending on
what area the allocation was made into.
Assuming memory_cma_accounting is set, if a non-root cgroup makes a CMA
allocation over either memcg's max limit or the per-area limit set by
the admin, the allocation fails with ENOMEM.
If memory_cma_accounting is dynamically unset, no the CMA allocator no
longer issues charges. Whatever was already charged can be uncharged
when it gets released.
It looked consistent to use memcg since movable pages from regular
allocations may end up in available CMA regions until a CMA allocation
needs the space and has them moved. So in an extreme case, hogging the
CMA space of a large enough area could trigger system memory pressure.
> > memcg
> > looked like a good fit to achieve this, albeit handling the areas, so a
> > cgroup has a quota in a given CMA resource.
>
> Please expand more on why do you think this fits into the memcg model.
> AFAIU we are talking about a unreclaimable memory and reservations of
> CMA areas.
Since memcg already accounts for some unreclaimable memory (kmem,
hugetlb), or induces failure if no reclamation is possible, I did not
see CMA allocations being unreclaimable to be a blocker to track what is
otherwise system memory.
I viewed pages allocated in CMA as guarantying special properties while
being otherwise similar to pages already accounted in memcg to the point
that charging them against memcg made more sense than having an entirely
different pool. I can see how that could be the other way around though,
especially with the per area counters, like how hugetlb have their own
controller.
> > This trails from an earlier post where we tried doing this using
> > dmem[1], but I was unable to reconcile the requirement for memcg
> > accounting[2] since from dmem I didn't have memory objects to charge nor
> > the guaranty there was one. Given CMA is always system memory, it looked
> > like a better fit to try something without dmem.
> >
> > Best,
> >
> > [1] https://lore.kernel.org/all/20260519-cgroup-dmem-memcg-double-charge-v2-0-db4d1407062b@redhat.com/
> > [2] https://lore.kernel.org/all/ahB7pCu_G4vuswc0@linux.dev/
> >
> > > --
> > > Michal Hocko
> > > SUSE Labs
> > >
> >
> > --
> > Eric Chanudet
>
> --
> Michal Hocko
> SUSE Labs
>
--
Eric Chanudet
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters
2026-08-25 16:26 ` Michal Hocko
@ 2026-08-25 18:50 ` Eric Chanudet
0 siblings, 0 replies; 26+ messages in thread
From: Eric Chanudet @ 2026-08-25 18:50 UTC (permalink / raw)
To: Michal Hocko
Cc: David Hildenbrand (Arm), Andrew Morton, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Tejun Heo, Johannes Weiner,
Michal Koutný, Jonathan Corbet, Shuah Khan, Roman Gushchin,
Shakeel Butt, Muchun Song, Shuah Khan, linux-mm, linux-kernel,
cgroups, linux-doc, linux-kselftest, Maxime Ripard, Albert Esteve
On Tue, Aug 25, 2026 at 06:26:42PM +0200, Michal Hocko wrote:
> On Tue 25-08-26 17:45:56, David Hildenbrand wrote:
> > On 8/25/26 16:47, Eric Chanudet wrote:
> > > On Mon, Aug 24, 2026 at 10:58:18AM +0200, Michal Hocko wrote:
> > >> On Fri 21-08-26 14:56:52, Eric Chanudet wrote:
> > >>> CMA allocations are currently unaccounted for by cgroup memory
> > >>> controllers. As system resources, they should fall under memcg, but CMA
> > >>> areas partition the available space for different purposes and memcg
> > >>> doesn't have a good representation for that.
> > >>
> > >> Which CMA usecases are covered by this work? It would be also great to
> > >> spend more time describing usecases.
> > >
> > > We would like to offer some usage guaranties to userspace processes
> > > ending up doing allocations in CMA.
> >
> > How does this e.g., relate to hugetlb allocating from CMA, to then charge to a
> > hugetlb cgroup?
> >
AFAIU the system defines CMA areas to allocate hugepages from. For this
initial series, I failed to handle it. The intend was to consider it as
any other CMA area. It entirely missed that hugepages are already
accounted for by their controller (cgroupfs opt
memory_hugetlb_accounting) and they are charged when faulted in from
their available pool.
> > I always thought of CMA being a low-level allocation mechanism with various
> > different use cases, and actually the higher-level users should decide how
> > to/what to charge instead.
>
> Exactly. There are many different users of CMA all with different
> requirements. Then there is CMA reservations if an area is shared and
> the overall memory consumption. That is why I am really not able to
> wrap my head around this proposal.
It is nonetheless available almost directly to userspace via dmabuf
heap, or as a result of drivers ioctl providing a contiguous buffer, and
unaccounted for by existing controllers, with the exception of CMA
hugepages with memory_hugetlb_accounting. The dmabuf heap use would have
userspace choose the area(s), but allow for no limit to be applied
beyond that, which is desirable for areas shared by multiple userspace
components.
>
>
> --
> Michal Hocko
> SUSE Labs
>
--
Eric Chanudet
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2026-08-25 18:50 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-21 18:56 [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Eric Chanudet
2026-08-21 18:56 ` [PATCH 01/11] mm/cma: drop const for struct page on release API Eric Chanudet
2026-08-21 18:56 ` [PATCH 02/11] mm/cma: include linux/cma.h in cma.h Eric Chanudet
2026-08-21 18:56 ` [PATCH 03/11] cgroup: add memory_cma_accounting mount option Eric Chanudet
2026-08-24 7:02 ` Maxime Ripard
2026-08-24 22:03 ` Eric Chanudet
2026-08-21 18:56 ` [PATCH 04/11] memcg: add cma charge/uncharge functions for area counters Eric Chanudet
2026-08-21 18:56 ` [PATCH 05/11] mm/cma: charge cma allocation to memcg per " Eric Chanudet
2026-08-21 18:56 ` [PATCH 06/11] memcg: register per-area usage counters in cgroupfs Eric Chanudet
2026-08-21 18:56 ` [PATCH 07/11] selftests: cgroup: add cma configs for cgroup selftest suite Eric Chanudet
2026-08-21 18:57 ` [PATCH 08/11] selftests: cgroup: add memcg cma tests Eric Chanudet
2026-08-21 18:57 ` [PATCH 09/11] selftests: cgroup: add a vmtest script for memcg Eric Chanudet
2026-08-21 18:57 ` [PATCH 10/11] selftests: cgroup: add memcg hugetlb_cma tests Eric Chanudet
2026-08-21 18:57 ` [PATCH 11/11] selftests: cgroup: amend vmtest-memcg to run the hugetlb cma tests Eric Chanudet
2026-08-23 7:02 ` [PATCH 00/11] mm/cma: charge cma allocation to memcg using per area counters Mike Rapoport
2026-08-24 21:58 ` Eric Chanudet
2026-08-25 7:40 ` Michal Hocko
2026-08-24 8:58 ` Michal Hocko
2026-08-25 14:47 ` Eric Chanudet
2026-08-25 14:59 ` Michal Hocko
2026-08-25 18:33 ` Eric Chanudet
2026-08-25 15:45 ` David Hildenbrand (Arm)
2026-08-25 16:26 ` Michal Hocko
2026-08-25 18:50 ` Eric Chanudet
2026-08-24 13:18 ` Michal Koutný
2026-08-25 14:54 ` Eric Chanudet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox