mirror of
https://github.com/torvalds/linux.git
synced 2026-11-10 17:11:02 +01:00
mm: memcg: skip the RCU lock when the memcg is not dying
get_non_dying_memcg_start() takes rcu_read_lock() on every stat update,
but the lock only protects the upward walk to a non-dying ancestor, which
happens solely while a memcg is being offlined. The dying check itself
reads the CSS_DYING flag of a memcg the caller already holds a reference
to, so it is safe without the lock.
Check memcg_is_dying() first and return immediately when the memcg is
alive, taking the RCU lock only on the rare dying path. On an anon
fault/charge churn workload in a memcg this recovers the ~0.6% overhead
added by the previous patch (4368077 vs 4343159 pages/s before, back to
~4377000 pages/s after).
Link: https://lore.kernel.org/9ffdbdfc96312e3e13cb8f056bfe26649492d949.1789096175.git.zhuhui@kylinos.cn
Fixes: 7404bd37cf ("mm: workingset: use lruvec_lru_size() to get the number of lru pages")
Signed-off-by: Hui Zhu <zhuhui@kylinos.cn>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Barry Song <baohua@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Kairui Song <kasong@tencent.com>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Wei Xu <weixugc@google.com>
Cc: Yuanchu Xie <yuanchu@google.com>
Cc: <stable@vger.kernel.org>
This commit is contained in:
parent
c7a37bac3c
commit
7c0a645068
|
|
@ -881,6 +881,17 @@ static long memcg_state_val_in_pages(int idx, long val)
|
|||
static inline struct mem_cgroup *
|
||||
get_non_dying_memcg_start(struct mem_cgroup *memcg, bool *rcu_locked)
|
||||
{
|
||||
/*
|
||||
* Fast path: the caller holds a reference to @memcg, so reading
|
||||
* its CSS_DYING flag without the RCU lock is safe. The RCU lock
|
||||
* is only needed to walk up to a non-dying ancestor, which
|
||||
* happens only while a memcg is actually being offlined.
|
||||
*/
|
||||
if (!memcg_is_dying(memcg)) {
|
||||
*rcu_locked = false;
|
||||
return memcg;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
*rcu_locked = true;
|
||||
|
||||
|
|
@ -892,6 +903,9 @@ get_non_dying_memcg_start(struct mem_cgroup *memcg, bool *rcu_locked)
|
|||
|
||||
static inline void get_non_dying_memcg_end(bool rcu_locked)
|
||||
{
|
||||
if (!rcu_locked)
|
||||
return;
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user