[PATCH 2/6] memcg: split mem_cgroup_private_id into two fields

From: Shakeel Butt

Date: Fri Sep 04 2026 - 23:07:33 EST


The two members of struct mem_cgroup_private_id have different access
patterns. The id is read on every eviction and refault through
mem_cgroup_private_id(), and is only written when the memcg is created
and destroyed. The ref is written on every swap charge and uncharge.

Split them into private_id and private_id_ref so a later patch can put
them into different cache line groups. A struct member cannot be split
across two groups.

No functional change.

Signed-off-by: Shakeel Butt <shakeel.butt@xxxxxxxxx>
---
include/linux/memcontrol.h | 10 +++-------
mm/memcontrol.c | 18 +++++++++---------
2 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index ac575fcc5f1e..46fc99786ebd 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -66,11 +66,6 @@ struct mem_cgroup_reclaim_cookie {

#define MEM_CGROUP_ID_SHIFT 16

-struct mem_cgroup_private_id {
- int id;
- refcount_t ref;
-};
-
struct memcg_vmstats_percpu;
struct memcg1_events_percpu;
struct memcg_vmstats;
@@ -189,7 +184,8 @@ struct mem_cgroup {
struct cgroup_subsys_state css;

/* Private memcg ID. Used to ID objects that outlive the cgroup */
- struct mem_cgroup_private_id id;
+ int private_id;
+ refcount_t private_id_ref;

/* Accounted resources */
struct page_counter memory; /* Both v1 & v2 */
@@ -811,7 +807,7 @@ static inline unsigned short mem_cgroup_private_id(struct mem_cgroup *memcg)
if (mem_cgroup_disabled())
return 0;

- return memcg->id.id;
+ return memcg->private_id;
}
struct mem_cgroup *mem_cgroup_from_private_id(unsigned short id);

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 9a65d7148c22..c42297ae3b0e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3797,7 +3797,7 @@ static void memcg_online_kmem(struct mem_cgroup *memcg)

static_branch_enable(&memcg_kmem_online_key);

- memcg->kmemcg_id = memcg->id.id;
+ memcg->kmemcg_id = memcg->private_id;
}

static void memcg_offline_kmem(struct mem_cgroup *memcg)
@@ -4056,15 +4056,15 @@ static DEFINE_XARRAY_ALLOC1(mem_cgroup_private_ids);

static void mem_cgroup_private_id_remove(struct mem_cgroup *memcg)
{
- if (memcg->id.id > 0) {
- xa_erase(&mem_cgroup_private_ids, memcg->id.id);
- memcg->id.id = 0;
+ if (memcg->private_id > 0) {
+ xa_erase(&mem_cgroup_private_ids, memcg->private_id);
+ memcg->private_id = 0;
}
}

static inline void mem_cgroup_private_id_put(struct mem_cgroup *memcg, unsigned int n)
{
- if (refcount_sub_and_test(n, &memcg->id.ref)) {
+ if (refcount_sub_and_test(n, &memcg->private_id_ref)) {
mem_cgroup_private_id_remove(memcg);

/* Memcg ID pins CSS */
@@ -4074,7 +4074,7 @@ static inline void mem_cgroup_private_id_put(struct mem_cgroup *memcg, unsigned

struct mem_cgroup *mem_cgroup_private_id_get_online(struct mem_cgroup *memcg, unsigned int n)
{
- while (!refcount_add_not_zero(n, &memcg->id.ref)) {
+ while (!refcount_add_not_zero(n, &memcg->private_id_ref)) {
/*
* The root cgroup cannot be destroyed, so it's refcount must
* always be >= 1.
@@ -4198,7 +4198,7 @@ static struct mem_cgroup *mem_cgroup_alloc(struct mem_cgroup *parent)
if (!memcg)
return ERR_PTR(-ENOMEM);

- error = xa_alloc(&mem_cgroup_private_ids, &memcg->id.id, NULL,
+ error = xa_alloc(&mem_cgroup_private_ids, &memcg->private_id, NULL,
XA_LIMIT(1, MEM_CGROUP_ID_MAX), GFP_KERNEL);
if (error)
goto fail;
@@ -4345,7 +4345,7 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
lru_gen_online_memcg(memcg);

/* Online state pins memcg ID, memcg ID pins CSS */
- refcount_set(&memcg->id.ref, 1);
+ refcount_set(&memcg->private_id_ref, 1);
css_get(css);

/*
@@ -4358,7 +4358,7 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
* publish it here at the end of onlining. This matches the
* regular ID destruction during offlining.
*/
- xa_store(&mem_cgroup_private_ids, memcg->id.id, memcg, GFP_KERNEL);
+ xa_store(&mem_cgroup_private_ids, memcg->private_id, memcg, GFP_KERNEL);

return 0;
free_objcg:
--
2.53.0-Meta