From: JP Kobryn <inwardvessel@gmail.com>
To: shakeel.butt@linux.dev, hannes@cmpxchg.org,
yosryahmed@google.com, akpm@linux-foundation.org
Cc: linux-mm@kvack.org, cgroups@vger.kernel.org
Subject: [PATCH 5/9 RFC] cgroup: separate locking between base css and others
Date: Mon, 23 Dec 2024 17:13:58 -0800 [thread overview]
Message-ID: <20241224011402.134009-6-inwardvessel@gmail.com> (raw)
In-Reply-To: <20241224011402.134009-1-inwardvessel@gmail.com>
Separate locks can be used to eliminate contention across subsystems that make
use of rstat. The base stats also get their own lock. Where applicable, check
for the existence of a subsystem pointer to determine if the given
cgroup_subsys_state is the base css or not.
Signed-off-by: JP Kobryn <inwardvessel@gmail.com>
---
include/linux/cgroup-defs.h | 2 +
kernel/cgroup/rstat.c | 92 +++++++++++++++++++++++++------------
2 files changed, 65 insertions(+), 29 deletions(-)
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 1932f8ae7995..4d87519ff023 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -790,6 +790,8 @@ struct cgroup_subsys {
* specifies the mask of subsystems that this one depends on.
*/
unsigned int depends_on;
+
+ spinlock_t rstat_lock;
};
extern struct percpu_rw_semaphore cgroup_threadgroup_rwsem;
diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c
index 4381eb9ac426..958bdccf0359 100644
--- a/kernel/cgroup/rstat.c
+++ b/kernel/cgroup/rstat.c
@@ -9,8 +9,9 @@
#include <trace/events/cgroup.h>
-static DEFINE_SPINLOCK(cgroup_rstat_lock);
-static DEFINE_PER_CPU(raw_spinlock_t, cgroup_rstat_cpu_lock);
+static DEFINE_SPINLOCK(cgroup_rstat_base_lock);
+static DEFINE_PER_CPU(raw_spinlock_t, cgroup_rstat_base_cpu_lock);
+static DEFINE_PER_CPU(raw_spinlock_t, cgroup_rstat_cpu_lock[CGROUP_SUBSYS_COUNT]);
static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu);
@@ -86,7 +87,7 @@ void _cgroup_rstat_cpu_unlock(raw_spinlock_t *cpu_lock, int cpu,
__bpf_kfunc void cgroup_rstat_updated(struct cgroup_subsys_state *css, int cpu)
{
struct cgroup *cgrp = css->cgroup;
- raw_spinlock_t *cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock, cpu);
+ raw_spinlock_t *cpu_lock;
unsigned long flags;
/*
@@ -100,6 +101,11 @@ __bpf_kfunc void cgroup_rstat_updated(struct cgroup_subsys_state *css, int cpu)
if (data_race(css_rstat_cpu(css, cpu)->updated_next))
return;
+ if (css->ss)
+ cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock[css->ss->id], cpu);
+ else
+ cpu_lock = per_cpu_ptr(&cgroup_rstat_base_cpu_lock, cpu);
+
flags = _cgroup_rstat_cpu_lock(cpu_lock, cpu, cgrp, true);
/* put @cgrp and all ancestors on the corresponding updated lists */
@@ -207,11 +213,16 @@ static struct cgroup_subsys_state *cgroup_rstat_push_children(
static struct cgroup_subsys_state *cgroup_rstat_updated_list(
struct cgroup_subsys_state *root, int cpu)
{
- raw_spinlock_t *cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock, cpu);
struct cgroup_rstat_cpu *rstatc = css_rstat_cpu(root, cpu);
struct cgroup_subsys_state *head = NULL, *parent, *child;
+ raw_spinlock_t *cpu_lock;
unsigned long flags;
+ if (root->ss)
+ cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock[root->ss->id], cpu);
+ else
+ cpu_lock = per_cpu_ptr(&cgroup_rstat_base_cpu_lock, cpu);
+
flags = _cgroup_rstat_cpu_lock(cpu_lock, cpu, root->cgroup, false);
/* Return NULL if this subtree is not on-list */
@@ -285,37 +296,44 @@ __bpf_hook_end();
* number processed last.
*/
static inline void __cgroup_rstat_lock(struct cgroup_subsys_state *css,
- int cpu_in_loop)
- __acquires(&cgroup_rstat_lock)
+ spinlock_t *lock, int cpu_in_loop)
+ __acquires(lock)
{
struct cgroup *cgrp = css->cgroup;
bool contended;
- contended = !spin_trylock_irq(&cgroup_rstat_lock);
+ contended = !spin_trylock_irq(lock);
if (contended) {
trace_cgroup_rstat_lock_contended(cgrp, cpu_in_loop, contended);
- spin_lock_irq(&cgroup_rstat_lock);
+ spin_lock_irq(lock);
}
trace_cgroup_rstat_locked(cgrp, cpu_in_loop, contended);
}
static inline void __cgroup_rstat_unlock(struct cgroup_subsys_state *css,
- int cpu_in_loop)
- __releases(&cgroup_rstat_lock)
+ spinlock_t *lock, int cpu_in_loop)
+ __releases(lock)
{
struct cgroup *cgrp = css->cgroup;
trace_cgroup_rstat_unlock(cgrp, cpu_in_loop, false);
- spin_unlock_irq(&cgroup_rstat_lock);
+ spin_unlock_irq(lock);
}
/* see cgroup_rstat_flush() */
static void cgroup_rstat_flush_locked(struct cgroup_subsys_state *css)
- __releases(&cgroup_rstat_lock) __acquires(&cgroup_rstat_lock)
+ __releases(&css->ss->rstat_lock) __acquires(&css->ss->rstat_lock)
{
+ spinlock_t *lock;
int cpu;
- lockdep_assert_held(&cgroup_rstat_lock);
+ if (!css->ss) {
+ pr_warn("cannot use generic flush on base subsystem\n");
+ return;
+ }
+
+ lock = &css->ss->rstat_lock;
+ lockdep_assert_held(lock);
for_each_possible_cpu(cpu) {
struct cgroup_subsys_state *pos = cgroup_rstat_updated_list(css, cpu);
@@ -334,11 +352,11 @@ static void cgroup_rstat_flush_locked(struct cgroup_subsys_state *css)
}
/* play nice and yield if necessary */
- if (need_resched() || spin_needbreak(&cgroup_rstat_lock)) {
- __cgroup_rstat_unlock(css, cpu);
+ if (need_resched() || spin_needbreak(lock)) {
+ __cgroup_rstat_unlock(css, lock, cpu);
if (!cond_resched())
cpu_relax();
- __cgroup_rstat_lock(css, cpu);
+ __cgroup_rstat_lock(css, lock, cpu);
}
}
}
@@ -358,11 +376,22 @@ static void cgroup_rstat_flush_locked(struct cgroup_subsys_state *css)
*/
__bpf_kfunc void cgroup_rstat_flush(struct cgroup_subsys_state *css)
{
+ spinlock_t *lock;
+
+ if (!css->ss) {
+ int cpu;
+
+ for_each_possible_cpu(cpu)
+ cgroup_base_stat_flush(css->cgroup, cpu);
+ return;
+ }
+
might_sleep();
- __cgroup_rstat_lock(css, -1);
+ lock = &css->ss->rstat_lock;
+ __cgroup_rstat_lock(css, lock, -1);
cgroup_rstat_flush_locked(css);
- __cgroup_rstat_unlock(css, -1);
+ __cgroup_rstat_unlock(css, lock, -1);
}
/**
@@ -374,11 +403,11 @@ __bpf_kfunc void cgroup_rstat_flush(struct cgroup_subsys_state *css)
*
* This function may block.
*/
-void cgroup_rstat_flush_hold(struct cgroup_subsys_state *css)
- __acquires(&cgroup_rstat_lock)
+static void cgroup_rstat_base_flush_hold(struct cgroup_subsys_state *css)
+ __acquires(&cgroup_rstat_base_lock)
{
might_sleep();
- __cgroup_rstat_lock(css, -1);
+ __cgroup_rstat_lock(css, &cgroup_rstat_base_lock, -1);
cgroup_rstat_flush_locked(css);
}
@@ -386,10 +415,10 @@ void cgroup_rstat_flush_hold(struct cgroup_subsys_state *css)
* cgroup_rstat_flush_release - release cgroup_rstat_flush_hold()
* @cgrp: cgroup used by tracepoint
*/
-void cgroup_rstat_flush_release(struct cgroup_subsys_state *css)
- __releases(&cgroup_rstat_lock)
+static void cgroup_rstat_base_flush_release(struct cgroup_subsys_state *css)
+ __releases(&cgroup_rstat_base_lock)
{
- __cgroup_rstat_unlock(css, -1);
+ __cgroup_rstat_unlock(css, &cgroup_rstat_base_lock, -1);
}
int cgroup_rstat_init(struct cgroup_subsys_state *css)
@@ -435,10 +464,15 @@ void cgroup_rstat_exit(struct cgroup_subsys_state *css)
void __init cgroup_rstat_boot(void)
{
- int cpu;
+ struct cgroup_subsys *ss;
+ int cpu, ssid;
+
+ for_each_possible_cpu(cpu) {
+ raw_spin_lock_init(per_cpu_ptr(&cgroup_rstat_base_cpu_lock, cpu));
- for_each_possible_cpu(cpu)
- raw_spin_lock_init(per_cpu_ptr(&cgroup_rstat_cpu_lock, cpu));
+ for_each_subsys(ss, ssid)
+ raw_spin_lock_init(per_cpu_ptr(&cgroup_rstat_cpu_lock[ssid], cpu));
+ }
}
/*
@@ -629,12 +663,12 @@ void cgroup_base_stat_cputime_show(struct seq_file *seq)
u64 usage, utime, stime, ntime;
if (cgroup_parent(cgrp)) {
- cgroup_rstat_flush_hold(css);
+ cgroup_rstat_base_flush_hold(css);
usage = cgrp->bstat.cputime.sum_exec_runtime;
cputime_adjust(&cgrp->bstat.cputime, &cgrp->prev_cputime,
&utime, &stime);
ntime = cgrp->bstat.ntime;
- cgroup_rstat_flush_release(css);
+ cgroup_rstat_base_flush_release(css);
} else {
/* cgrp->bstat of root is not actually used, reuse it */
root_cgroup_cputime(&cgrp->bstat);
--
2.47.1
next prev parent reply other threads:[~2024-12-24 1:14 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-24 1:13 [PATCH 0/9 RFC] cgroup: separate rstat trees JP Kobryn
2024-12-24 1:13 ` [PATCH 1/9 RFC] change cgroup to css in rstat updated and flush api JP Kobryn
2024-12-24 1:13 ` [PATCH 2/9 RFC] cgroup: change cgroup to css in rstat internal flush and lock funcs JP Kobryn
2024-12-24 1:13 ` [PATCH 3/9 RFC] cgroup: change cgroup to css in rstat init and exit api JP Kobryn
2024-12-24 1:13 ` [PATCH 4/9 RFC] cgroup: split rstat from cgroup into separate css JP Kobryn
2024-12-24 1:13 ` JP Kobryn [this message]
2024-12-24 1:13 ` [PATCH 6/9 RFC] cgroup: isolate base stat flush JP Kobryn
2024-12-24 1:14 ` [PATCH 7/9 RFC] cgroup: remove unneeded rcu list JP Kobryn
2024-12-24 1:14 ` [PATCH 8/9 RFC] cgroup: remove bpf rstat flush from css generic flush JP Kobryn
2024-12-24 1:14 ` [PATCH 9/9 RFC] cgroup: avoid allocating rstat when flush func not present JP Kobryn
2024-12-24 4:57 ` [PATCH 0/9 RFC] cgroup: separate rstat trees Shakeel Butt
2025-01-08 18:16 ` Michal Koutný
2025-01-13 18:25 ` Shakeel Butt
2025-01-15 1:33 ` JP Kobryn
2025-01-15 1:39 ` Yosry Ahmed
2025-01-15 19:38 ` JP Kobryn
2025-01-15 21:36 ` Yosry Ahmed
2025-01-16 18:20 ` JP Kobryn
2025-01-16 15:19 ` Michal Koutný
2025-01-16 15:35 ` Yosry Ahmed
2025-01-16 19:03 ` Shakeel Butt
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=20241224011402.134009-6-inwardvessel@gmail.com \
--to=inwardvessel@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=cgroups@vger.kernel.org \
--cc=hannes@cmpxchg.org \
--cc=linux-mm@kvack.org \
--cc=shakeel.butt@linux.dev \
--cc=yosryahmed@google.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.