]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
memcg: nmi-safe slab stats updates
authorShakeel Butt <shakeel.butt@linux.dev>
Mon, 19 May 2025 06:31:41 +0000 (23:31 -0700)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 1 Jun 2025 05:46:09 +0000 (22:46 -0700)
The objcg based kmem [un]charging can be called in nmi context and it may
need to update NR_SLAB_[UN]RECLAIMABLE_B stats.  So, let's correctly
handle the updates of these stats in the nmi context.

Link: https://lkml.kernel.org/r/20250519063142.111219-5-shakeel.butt@linux.dev
Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/memcontrol.c

index 74bb19fcafad00b1568e397a041b8bfac96e6895..74de4e5230946fc0dd5a8a762e50f8f6177dc442 100644 (file)
@@ -2515,17 +2515,47 @@ static void commit_charge(struct folio *folio, struct mem_cgroup *memcg)
        folio->memcg_data = (unsigned long)memcg;
 }
 
+#ifdef CONFIG_MEMCG_NMI_SAFETY_REQUIRES_ATOMIC
+static inline void account_slab_nmi_safe(struct mem_cgroup *memcg,
+                                        struct pglist_data *pgdat,
+                                        enum node_stat_item idx, int nr)
+{
+       struct lruvec *lruvec;
+
+       if (likely(!in_nmi())) {
+               lruvec = mem_cgroup_lruvec(memcg, pgdat);
+               mod_memcg_lruvec_state(lruvec, idx, nr);
+       } else {
+               struct mem_cgroup_per_node *pn = memcg->nodeinfo[pgdat->node_id];
+
+               /* TODO: add to cgroup update tree once it is nmi-safe. */
+               if (idx == NR_SLAB_RECLAIMABLE_B)
+                       atomic_add(nr, &pn->slab_reclaimable);
+               else
+                       atomic_add(nr, &pn->slab_unreclaimable);
+       }
+}
+#else
+static inline void account_slab_nmi_safe(struct mem_cgroup *memcg,
+                                        struct pglist_data *pgdat,
+                                        enum node_stat_item idx, int nr)
+{
+       struct lruvec *lruvec;
+
+       lruvec = mem_cgroup_lruvec(memcg, pgdat);
+       mod_memcg_lruvec_state(lruvec, idx, nr);
+}
+#endif
+
 static inline void mod_objcg_mlstate(struct obj_cgroup *objcg,
                                       struct pglist_data *pgdat,
                                       enum node_stat_item idx, int nr)
 {
        struct mem_cgroup *memcg;
-       struct lruvec *lruvec;
 
        rcu_read_lock();
        memcg = obj_cgroup_memcg(objcg);
-       lruvec = mem_cgroup_lruvec(memcg, pgdat);
-       mod_memcg_lruvec_state(lruvec, idx, nr);
+       account_slab_nmi_safe(memcg, pgdat, idx, nr);
        rcu_read_unlock();
 }