From: Qinyun Tan <qinyuntan@linux.alibaba.com>
To: akpm@linux-foundation.org
Cc: hannes@cmpxchg.org, mhocko@kernel.org, roman.gushchin@linux.dev,
shakeel.butt@linux.dev, muchun.song@linux.dev, mkoutny@suse.com,
david@kernel.org, ziy@nvidia.com, baolin.wang@linux.alibaba.com,
usama.arif@linux.dev, david@fromorbit.com, qi.zheng@linux.dev,
yosry@kernel.org, nphamcs@gmail.com, chengming.zhou@linux.dev,
xlpang@linux.alibaba.com, ryncsn@gmail.com, gourry@gourry.net,
cgroups@vger.kernel.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org,
Qinyun Tan <qinyuntan@linux.alibaba.com>
Subject: [PATCH v4 2/5] mm: memcontrol: drop kmemcg_id and use mem_cgroup_id() for list_lru indexing
Date: Tue, 13 Oct 2026 11:12:18 +0800 [thread overview]
Message-ID: <20261013031221.1997194-3-qinyuntan@linux.alibaba.com> (raw)
In-Reply-To: <20261013031221.1997194-1-qinyuntan@linux.alibaba.com>
kmemcg_id is a copy of the private memcg ID and serves no purpose
other than indexing the per-memcg list_lru xarray. It is assigned
when kmem accounting goes online, which never happens with
cgroup.memory=nokmem, and the memcgs then all resolve to the
per-node lists. The next patch needs the index to work under nokmem
as well.
Index the lists with mem_cgroup_id(). The cgroup ID is unique per
memcg and is only recycled once the cgroup is destroyed, long after
offlining has erased the xarray entries, so a recycled ID cannot
resurrect a stale entry.
Also drop the nokmem early return from the offline path, so that the
reparenting covers lrus that stay memcg aware without kmem
accounting. memcg_online_kmem() and memcg_offline_kmem() are each
down to a single statement now; inline them into the css online and
offline hooks, dropping the root check, as css_offline() is never
called for the root and a memcg that failed css_online() cannot have
list_lru entries.
Signed-off-by: Qinyun Tan <qinyuntan@linux.alibaba.com>
---
include/linux/memcontrol.h | 16 --------------
mm/list_lru.c | 16 ++++++++------
mm/memcontrol.c | 45 +++++++-------------------------------
3 files changed, 17 insertions(+), 60 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 74110a324f9e..dc89d46e3d77 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -328,8 +328,6 @@ struct mem_cgroup {
/* Private memcg ID. Used to ID objects that outlive the cgroup */
int private_id;
- int kmemcg_id;
-
/*
* Should the OOM killer kill all belonging tasks, had it kill one?
*/
@@ -1820,15 +1818,6 @@ static inline void memcg_kmem_uncharge_page(struct page *page, int order)
__memcg_kmem_uncharge_page(page, order);
}
-/*
- * A helper for accessing memcg's kmem_id, used for getting
- * corresponding LRU lists.
- */
-static inline int memcg_kmem_id(const struct mem_cgroup *memcg)
-{
- return memcg ? memcg->kmemcg_id : -1;
-}
-
struct mem_cgroup *mem_cgroup_from_virt(void *p);
static inline void count_objcg_events(struct obj_cgroup *objcg,
@@ -1896,11 +1885,6 @@ static inline bool memcg_kmem_online(void)
return false;
}
-static inline int memcg_kmem_id(const struct mem_cgroup *memcg)
-{
- return -1;
-}
-
static inline struct mem_cgroup *mem_cgroup_from_virt(void *p)
{
return NULL;
diff --git a/mm/list_lru.c b/mm/list_lru.c
index 61248b88441c..8e9577c5cb19 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -39,9 +39,10 @@ static inline void unlock_list_lru(struct list_lru_one *l, bool irq_off,
static inline unsigned long list_lru_memcg_idx(const struct mem_cgroup *memcg)
{
- int idx = memcg_kmem_id(memcg);
+ if (!memcg || mem_cgroup_is_root(memcg))
+ return 0;
- return idx < 0 ? 0 : idx;
+ return mem_cgroup_id(memcg);
}
#ifdef CONFIG_MEMCG
@@ -548,7 +549,7 @@ void memcg_reparent_list_lrus(struct mem_cgroup *memcg, struct mem_cgroup *paren
* allocating a new mlru since CSS_DYING is already set for this
* memcg a rcu grace period ago.
*/
- mlru = xa_load(&lru->xa, memcg->kmemcg_id);
+ mlru = xa_load(&lru->xa, list_lru_memcg_idx(memcg));
if (!mlru)
continue;
@@ -563,7 +564,7 @@ void memcg_reparent_list_lrus(struct mem_cgroup *memcg, struct mem_cgroup *paren
for_each_node(i)
memcg_reparent_list_lru_one(lru, i, &mlru->node[i], parent);
- xa_erase_irq(&lru->xa, memcg->kmemcg_id);
+ xa_erase_irq(&lru->xa, list_lru_memcg_idx(memcg));
/*
* Here all list_lrus corresponding to the cgroup are guaranteed
@@ -578,9 +579,10 @@ void memcg_reparent_list_lrus(struct mem_cgroup *memcg, struct mem_cgroup *paren
static inline bool memcg_list_lru_allocated(struct mem_cgroup *memcg,
struct list_lru *lru)
{
- int idx = memcg->kmemcg_id;
+ if (!memcg || mem_cgroup_is_root(memcg))
+ return true;
- return idx < 0 || xa_load(&lru->xa, idx);
+ return xa_load(&lru->xa, list_lru_memcg_idx(memcg));
}
static int __memcg_list_lru_alloc(struct mem_cgroup *memcg,
@@ -614,7 +616,7 @@ static int __memcg_list_lru_alloc(struct mem_cgroup *memcg,
if (!mlru)
return -ENOMEM;
}
- xas_set(&xas, pos->kmemcg_id);
+ xas_set(&xas, list_lru_memcg_idx(pos));
do {
xas_lock_irqsave(&xas, flags);
if (!xas_load(&xas) && !css_is_dying(&pos->css)) {
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index aad0498a7bd6..fcba9eb55659 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3807,33 +3807,6 @@ void folio_split_memcg_refs(struct folio *folio, unsigned old_order,
obj_cgroup_get_many(folio_objcg(folio), new_refs);
}
-static void memcg_online_kmem(struct mem_cgroup *memcg)
-{
- if (mem_cgroup_kmem_disabled())
- return;
-
- if (unlikely(mem_cgroup_is_root(memcg)))
- return;
-
- static_branch_enable(&memcg_kmem_online_key);
-
- memcg->kmemcg_id = memcg->private_id;
-}
-
-static void memcg_offline_kmem(struct mem_cgroup *memcg)
-{
- struct mem_cgroup *parent;
-
- if (mem_cgroup_kmem_disabled())
- return;
-
- if (unlikely(mem_cgroup_is_root(memcg)))
- return;
-
- parent = parent_mem_cgroup(memcg);
- memcg_reparent_list_lrus(memcg, parent);
-}
-
#ifdef CONFIG_CGROUP_WRITEBACK
#include <trace/events/writeback.h>
@@ -4309,7 +4282,6 @@ static struct mem_cgroup *mem_cgroup_alloc(struct mem_cgroup *parent)
seqlock_init(&memcg->socket_pressure_seqlock);
#endif
memcg1_memcg_init(memcg);
- memcg->kmemcg_id = -1;
#ifdef CONFIG_CGROUP_WRITEBACK
INIT_LIST_HEAD(&memcg->cgwb_list);
for (i = 0; i < MEMCG_CGWB_FRN_CNT; i++)
@@ -4383,7 +4355,8 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
struct obj_cgroup *objcg;
int nid;
- memcg_online_kmem(memcg);
+ if (!mem_cgroup_kmem_disabled() && likely(!mem_cgroup_is_root(memcg)))
+ static_branch_enable(&memcg_kmem_online_key);
/*
* A memcg must be visible for expand_shrinker_info()
@@ -4391,7 +4364,7 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
* here, when mem_cgroup_iter() can't skip it.
*/
if (alloc_shrinker_info(memcg))
- goto offline_kmem;
+ goto reparent_lrus;
for_each_node(nid) {
objcg = obj_cgroup_alloc();
@@ -4449,8 +4422,8 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
}
}
free_shrinker_info(memcg);
-offline_kmem:
- memcg_offline_kmem(memcg);
+reparent_lrus:
+ memcg_reparent_list_lrus(memcg, parent_mem_cgroup(memcg));
mem_cgroup_private_id_remove(memcg);
return -ENOMEM;
}
@@ -4466,11 +4439,11 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
zswap_memcg_offline_cleanup(memcg);
- memcg_offline_kmem(memcg);
+ memcg_reparent_list_lrus(memcg, parent_mem_cgroup(memcg));
/*
* The reparenting of objcg must be after the reparenting of
- * the list_lru in memcg_offline_kmem(), which ensures that
- * they will not mistakenly get the parent list_lru.
+ * the list_lru above, which ensures that they will not
+ * mistakenly get the parent list_lru.
*/
memcg_reparent_objcgs(memcg);
reparent_shrinker_deferred(memcg);
@@ -5913,8 +5886,6 @@ static void __init memcg_struct_check(void)
private_id_objcg);
CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_read_mostly,
private_id);
- CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_read_mostly,
- kmemcg_id);
CACHELINE_ASSERT_GROUP_MEMBER(struct mem_cgroup, memcg_read_mostly,
oom_group);
--
2.43.7
next prev parent reply other threads:[~2026-10-13 3:12 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-13 3:12 [PATCH v4 0/5] mm: restore per-memcg reclaim for NONSLAB shrinkers under nokmem Qinyun Tan
2026-10-13 3:12 ` [PATCH v4 1/5] mm: list_lru: pass the memcg index directly to the walker Qinyun Tan
2026-10-13 3:12 ` Qinyun Tan [this message]
2026-10-13 3:12 ` [PATCH v4 3/5] mm: list_lru: keep per-memcg lists with nokmem for NONSLAB-backed lrus Qinyun Tan
2026-10-13 3:12 ` [PATCH v4 4/5] mm: thp: restore SHRINKER_NONSLAB on the deferred split shrinker Qinyun Tan
2026-10-13 3:12 ` [PATCH v4 5/5] mm: zswap: mark the zswap shrinker SHRINKER_NONSLAB Qinyun Tan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261013031221.1997194-3-qinyuntan@linux.alibaba.com \
--to=qinyuntan@linux.alibaba.com \
--cc=akpm@linux-foundation.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=cgroups@vger.kernel.org \
--cc=chengming.zhou@linux.dev \
--cc=david@fromorbit.com \
--cc=david@kernel.org \
--cc=gourry@gourry.net \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@kernel.org \
--cc=mkoutny@suse.com \
--cc=muchun.song@linux.dev \
--cc=nphamcs@gmail.com \
--cc=qi.zheng@linux.dev \
--cc=roman.gushchin@linux.dev \
--cc=ryncsn@gmail.com \
--cc=shakeel.butt@linux.dev \
--cc=usama.arif@linux.dev \
--cc=xlpang@linux.alibaba.com \
--cc=yosry@kernel.org \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®