Commit 15ca4fa9 authored by Shakeel Butt's avatar Shakeel Butt Committed by Andrew Morton
Browse files

memcg: nmi-safe slab stats updates

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: default avatarShakeel Butt <shakeel.butt@linux.dev>
Acked-by: default avatarVlastimil 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: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 9d3edf96
Loading
Loading
Loading
Loading
+33 −3
Original line number Diff line number Diff line
@@ -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();
}