From: JP Kobryn <inwardvessel@gmail.com>
To: shakeel.butt@linux.dev, tj@kernel.org, mhocko@kernel.org,
hannes@cmpxchg.org, yosryahmed@google.com,
akpm@linux-foundation.org
Cc: linux-mm@kvack.org, cgroups@vger.kernel.org, kernel-team@meta.com
Subject: [PATCH 04/11] cgroup: introduce cgroup_rstat_ops
Date: Mon, 17 Feb 2025 19:14:41 -0800 [thread overview]
Message-ID: <20250218031448.46951-5-inwardvessel@gmail.com> (raw)
In-Reply-To: <20250218031448.46951-1-inwardvessel@gmail.com>
The cgroup_rstat_ops interface provides a way for type-specific
operations to be hidden from the common rstat operations. Use it to
decouple the cgroup_subsys_type from within the internal rstat
updated/flush routines. The new ops interface allows for greater
extensibility in terms of future changes. i.e. public updated/flush
api's can be created that accept a arbitrary types, as long as that type
has an associated ops interface.
Signed-off-by: JP Kobryn <inwardvessel@gmail.com>
---
kernel/cgroup/rstat.c | 131 +++++++++++++++++++++++++++---------------
1 file changed, 85 insertions(+), 46 deletions(-)
diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c
index a32bcd7942a5..a8bb304e49c4 100644
--- a/kernel/cgroup/rstat.c
+++ b/kernel/cgroup/rstat.c
@@ -9,6 +9,12 @@
#include <trace/events/cgroup.h>
+struct cgroup_rstat_ops {
+ struct cgroup_rstat *(*parent_fn)(struct cgroup_rstat *);
+ struct cgroup *(*cgroup_fn)(struct cgroup_rstat *);
+ void (*flush_fn)(struct cgroup_rstat *, int);
+};
+
static DEFINE_SPINLOCK(cgroup_rstat_lock);
static DEFINE_PER_CPU(raw_spinlock_t, cgroup_rstat_cpu_lock);
@@ -19,7 +25,17 @@ static struct cgroup_rstat_cpu *rstat_cpu(struct cgroup_rstat *rstat, int cpu)
return per_cpu_ptr(rstat->rstat_cpu, cpu);
}
-static struct cgroup_rstat *rstat_parent(struct cgroup_rstat *rstat)
+static inline bool is_base_css(struct cgroup_subsys_state *css)
+{
+ /* css for base stats has no subsystem */
+ if (!css->ss)
+ return true;
+
+ return false;
+}
+
+static struct cgroup_rstat *rstat_parent_via_css(
+ struct cgroup_rstat *rstat)
{
struct cgroup_subsys_state *css = container_of(
rstat, typeof(*css), rstat);
@@ -30,6 +46,33 @@ static struct cgroup_rstat *rstat_parent(struct cgroup_rstat *rstat)
return &(css->parent->rstat);
}
+static struct cgroup *rstat_cgroup_via_css(struct cgroup_rstat *rstat)
+{
+ struct cgroup_subsys_state *css =
+ container_of(rstat, struct cgroup_subsys_state, rstat);
+
+ return css->cgroup;
+}
+
+static void rstat_flush_via_css(struct cgroup_rstat *rstat, int cpu)
+{
+ struct cgroup_subsys_state *css = container_of(
+ rstat, typeof(*css), rstat);
+
+ if (is_base_css(css)) {
+ cgroup_base_stat_flush(css->cgroup, cpu);
+ return;
+ }
+
+ css->ss->css_rstat_flush(css, cpu);
+}
+
+static struct cgroup_rstat_ops rstat_css_ops = {
+ .parent_fn = rstat_parent_via_css,
+ .cgroup_fn = rstat_cgroup_via_css,
+ .flush_fn = rstat_flush_via_css,
+};
+
/*
* Helper functions for rstat per CPU lock (cgroup_rstat_cpu_lock).
*
@@ -84,11 +127,11 @@ void _cgroup_rstat_cpu_unlock(raw_spinlock_t *cpu_lock, int cpu,
raw_spin_unlock_irqrestore(cpu_lock, flags);
}
-static void __cgroup_rstat_updated(struct cgroup_rstat *rstat, int cpu)
+static void __cgroup_rstat_updated(struct cgroup_rstat *rstat, int cpu,
+ struct cgroup_rstat_ops *ops)
{
- struct cgroup_subsys_state *css = container_of(
- rstat, typeof(*css), rstat);
- struct cgroup *cgrp = css->cgroup;
+ struct cgroup *cgrp;
+
raw_spinlock_t *cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock, cpu);
unsigned long flags;
@@ -103,12 +146,13 @@ static void __cgroup_rstat_updated(struct cgroup_rstat *rstat, int cpu)
if (data_race(rstat_cpu(rstat, cpu)->updated_next))
return;
+ cgrp = ops->cgroup_fn(rstat);
flags = _cgroup_rstat_cpu_lock(cpu_lock, cpu, cgrp, true);
/* put @rstat and all ancestors on the corresponding updated lists */
while (true) {
struct cgroup_rstat_cpu *rstatc = rstat_cpu(rstat, cpu);
- struct cgroup_rstat *parent = rstat_parent(rstat);
+ struct cgroup_rstat *parent = ops->parent_fn(rstat);
struct cgroup_rstat_cpu *prstatc;
/*
@@ -145,7 +189,7 @@ static void __cgroup_rstat_updated(struct cgroup_rstat *rstat, int cpu)
*/
__bpf_kfunc void cgroup_rstat_updated(struct cgroup_subsys_state *css, int cpu)
{
- __cgroup_rstat_updated(&css->rstat, cpu);
+ __cgroup_rstat_updated(&css->rstat, cpu, &rstat_css_ops);
}
/**
@@ -161,7 +205,8 @@ __bpf_kfunc void cgroup_rstat_updated(struct cgroup_subsys_state *css, int cpu)
* cgroups into a stack. The root is pushed by the caller.
*/
static struct cgroup_rstat *cgroup_rstat_push_children(
- struct cgroup_rstat *head, struct cgroup_rstat *child, int cpu)
+ struct cgroup_rstat *head, struct cgroup_rstat *child, int cpu,
+ struct cgroup_rstat_ops *ops)
{
struct cgroup_rstat *chead = child; /* Head of child cgroup level */
struct cgroup_rstat *ghead = NULL; /* Head of grandchild cgroup level */
@@ -174,7 +219,7 @@ static struct cgroup_rstat *cgroup_rstat_push_children(
while (chead) {
child = chead;
chead = child->rstat_flush_next;
- parent = rstat_parent(child);
+ parent = ops->parent_fn(child);
/* updated_next is parent cgroup terminated */
while (child != parent) {
@@ -220,16 +265,15 @@ static struct cgroup_rstat *cgroup_rstat_push_children(
* here is the cgroup root whose updated_next can be self terminated.
*/
static struct cgroup_rstat *cgroup_rstat_updated_list(
- struct cgroup_rstat *root, int cpu)
+ struct cgroup_rstat *root, int cpu, struct cgroup_rstat_ops *ops)
{
- struct cgroup_subsys_state *css = container_of(
- root, typeof(*css), rstat);
- struct cgroup *cgrp = css->cgroup;
raw_spinlock_t *cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock, cpu);
struct cgroup_rstat_cpu *rstatc = rstat_cpu(root, cpu);
struct cgroup_rstat *head = NULL, *parent, *child;
+ struct cgroup *cgrp;
unsigned long flags;
+ cgrp = ops->cgroup_fn(root);
flags = _cgroup_rstat_cpu_lock(cpu_lock, cpu, cgrp, false);
/* Return NULL if this subtree is not on-list */
@@ -240,7 +284,7 @@ static struct cgroup_rstat *cgroup_rstat_updated_list(
* Unlink @root from its parent. As the updated_children list is
* singly linked, we have to walk it to find the removal point.
*/
- parent = rstat_parent(root);
+ parent = ops->parent_fn(root);
if (parent) {
struct cgroup_rstat_cpu *prstatc;
struct cgroup_rstat **nextp;
@@ -265,7 +309,7 @@ static struct cgroup_rstat *cgroup_rstat_updated_list(
child = rstatc->updated_children;
rstatc->updated_children = root;
if (child != root)
- head = cgroup_rstat_push_children(head, child, cpu);
+ head = cgroup_rstat_push_children(head, child, cpu, ops);
unlock_ret:
_cgroup_rstat_cpu_unlock(cpu_lock, cpu, cgrp, flags, false);
return head;
@@ -323,34 +367,30 @@ static inline void __cgroup_rstat_unlock(struct cgroup *cgrp, int cpu_in_loop)
}
/* see cgroup_rstat_flush() */
-static void cgroup_rstat_flush_locked(struct cgroup_rstat *rstat)
+static void cgroup_rstat_flush_locked(struct cgroup_rstat *rstat,
+ struct cgroup_rstat_ops *ops)
__releases(&cgroup_rstat_lock) __acquires(&cgroup_rstat_lock)
{
- struct cgroup_subsys_state *css = container_of(
- rstat, typeof(*css), rstat);
- struct cgroup *cgrp = css->cgroup;
int cpu;
lockdep_assert_held(&cgroup_rstat_lock);
for_each_possible_cpu(cpu) {
- struct cgroup_rstat *pos = cgroup_rstat_updated_list(rstat, cpu);
+ struct cgroup_rstat *pos = cgroup_rstat_updated_list(
+ rstat, cpu, ops);
for (; pos; pos = pos->rstat_flush_next) {
- struct cgroup_subsys_state *pos_css = container_of(
- pos, typeof(*pos_css), rstat);
- struct cgroup *pos_cgroup = pos_css->cgroup;
-
- if (!pos_css->ss)
- cgroup_base_stat_flush(pos_cgroup, cpu);
- else
- pos_css->ss->css_rstat_flush(pos_css, cpu);
+ struct cgroup *pos_cgroup = ops->cgroup_fn(pos);
+ ops->flush_fn(pos, cpu);
bpf_rstat_flush(pos_cgroup, cgroup_parent(pos_cgroup), cpu);
}
/* play nice and yield if necessary */
if (need_resched() || spin_needbreak(&cgroup_rstat_lock)) {
+ struct cgroup *cgrp;
+
+ cgrp = ops->cgroup_fn(rstat);
__cgroup_rstat_unlock(cgrp, cpu);
if (!cond_resched())
cpu_relax();
@@ -359,16 +399,15 @@ static void cgroup_rstat_flush_locked(struct cgroup_rstat *rstat)
}
}
-static void __cgroup_rstat_flush(struct cgroup_rstat *rstat)
+static void __cgroup_rstat_flush(struct cgroup_rstat *rstat,
+ struct cgroup_rstat_ops *ops)
{
- struct cgroup_subsys_state *css = container_of(
- rstat, typeof(*css), rstat);
- struct cgroup *cgrp = css->cgroup;
+ struct cgroup *cgrp;
might_sleep();
-
+ cgrp = ops->cgroup_fn(rstat);
__cgroup_rstat_lock(cgrp, -1);
- cgroup_rstat_flush_locked(rstat);
+ cgroup_rstat_flush_locked(rstat, ops);
__cgroup_rstat_unlock(cgrp, -1);
}
@@ -387,19 +426,19 @@ static void __cgroup_rstat_flush(struct cgroup_rstat *rstat)
*/
__bpf_kfunc void cgroup_rstat_flush(struct cgroup_subsys_state *css)
{
- __cgroup_rstat_flush(&css->rstat);
+ __cgroup_rstat_flush(&css->rstat, &rstat_css_ops);
}
-static void __cgroup_rstat_flush_hold(struct cgroup_rstat *rstat)
+static void __cgroup_rstat_flush_hold(struct cgroup_rstat *rstat,
+ struct cgroup_rstat_ops *ops)
__acquires(&cgroup_rstat_lock)
{
- struct cgroup_subsys_state *css = container_of(
- rstat, typeof(*css), rstat);
- struct cgroup *cgrp = css->cgroup;
+ struct cgroup *cgrp;
might_sleep();
+ cgrp = ops->cgroup_fn(rstat);
__cgroup_rstat_lock(cgrp, -1);
- cgroup_rstat_flush_locked(rstat);
+ cgroup_rstat_flush_locked(rstat, ops);
}
/**
@@ -413,20 +452,20 @@ static void __cgroup_rstat_flush_hold(struct cgroup_rstat *rstat)
*/
void cgroup_rstat_flush_hold(struct cgroup_subsys_state *css)
{
- __cgroup_rstat_flush_hold(&css->rstat);
+ __cgroup_rstat_flush_hold(&css->rstat, &rstat_css_ops);
}
/**
* cgroup_rstat_flush_release - release cgroup_rstat_flush_hold()
* @rstat: rstat node used to find associated cgroup used by tracepoint
*/
-static void __cgroup_rstat_flush_release(struct cgroup_rstat *rstat)
+static void __cgroup_rstat_flush_release(struct cgroup_rstat *rstat,
+ struct cgroup_rstat_ops *ops)
__releases(&cgroup_rstat_lock)
{
- struct cgroup_subsys_state *css = container_of(
- rstat, typeof(*css), rstat);
- struct cgroup *cgrp = css->cgroup;
+ struct cgroup *cgrp;
+ cgrp = ops->cgroup_fn(rstat);
__cgroup_rstat_unlock(cgrp, -1);
}
@@ -436,7 +475,7 @@ static void __cgroup_rstat_flush_release(struct cgroup_rstat *rstat)
*/
void cgroup_rstat_flush_release(struct cgroup_subsys_state *css)
{
- __cgroup_rstat_flush_release(&css->rstat);
+ __cgroup_rstat_flush_release(&css->rstat, &rstat_css_ops);
}
static void __cgroup_rstat_init(struct cgroup_rstat *rstat)
--
2.48.1
next prev parent reply other threads:[~2025-02-18 3:15 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-18 3:14 [PATCH 00/11] cgroup: separate rstat trees JP Kobryn
2025-02-18 3:14 ` [PATCH 01/11] cgroup: move rstat pointers into struct of their own JP Kobryn
2025-02-19 1:05 ` Shakeel Butt
2025-02-19 1:23 ` Shakeel Butt
2025-02-20 16:53 ` Yosry Ahmed
2025-02-24 17:06 ` JP Kobryn
2025-02-24 18:36 ` Yosry Ahmed
2025-02-18 3:14 ` [PATCH 02/11] cgroup: add level of indirection for cgroup_rstat struct JP Kobryn
2025-02-19 2:26 ` Shakeel Butt
2025-02-20 17:08 ` Yosry Ahmed
2025-02-19 5:57 ` kernel test robot
2025-02-18 3:14 ` [PATCH 03/11] cgroup: move cgroup_rstat from cgroup to cgroup_subsys_state JP Kobryn
2025-02-20 17:06 ` Shakeel Butt
2025-02-20 17:22 ` Yosry Ahmed
2025-02-25 19:20 ` JP Kobryn
2025-02-18 3:14 ` JP Kobryn [this message]
2025-02-19 7:21 ` [PATCH 04/11] cgroup: introduce cgroup_rstat_ops kernel test robot
2025-02-20 17:50 ` Shakeel Butt
2025-02-18 3:14 ` [PATCH 05/11] cgroup: separate rstat for bpf cgroups JP Kobryn
2025-02-21 18:14 ` Shakeel Butt
2025-02-18 3:14 ` [PATCH 06/11] cgroup: rstat lock indirection JP Kobryn
2025-02-21 22:09 ` Shakeel Butt
2025-02-18 3:14 ` [PATCH 07/11] cgroup: fetch cpu-specific lock in rstat cpu lock helpers JP Kobryn
2025-02-21 22:35 ` Shakeel Butt
2025-02-18 3:14 ` [PATCH 08/11] cgroup: rstat cpu lock indirection JP Kobryn
2025-02-19 8:48 ` kernel test robot
2025-02-22 0:18 ` Shakeel Butt
2025-02-18 3:14 ` [PATCH 09/11] cgroup: separate rstat locks for bpf cgroups JP Kobryn
2025-02-18 3:14 ` [PATCH 10/11] cgroup: separate rstat locks for subsystems JP Kobryn
2025-02-22 0:23 ` Shakeel Butt
2025-02-18 3:14 ` [PATCH 11/11] cgroup: separate rstat list pointers from base stats JP Kobryn
2025-02-22 0:28 ` Shakeel Butt
2025-02-20 15:51 ` [PATCH 00/11] cgroup: separate rstat trees Tejun Heo
2025-02-27 23:44 ` JP Kobryn
2025-02-20 17:26 ` Yosry Ahmed
2025-02-20 17:53 ` Shakeel Butt
2025-02-20 17:59 ` Yosry Ahmed
2025-02-20 18:14 ` JP Kobryn
2025-02-20 20:04 ` Yosry Ahmed
2025-02-20 20:22 ` Yosry Ahmed
2025-02-24 21:13 ` Shakeel Butt
2025-02-24 21:54 ` Yosry Ahmed
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=20250218031448.46951-5-inwardvessel@gmail.com \
--to=inwardvessel@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=cgroups@vger.kernel.org \
--cc=hannes@cmpxchg.org \
--cc=kernel-team@meta.com \
--cc=linux-mm@kvack.org \
--cc=mhocko@kernel.org \
--cc=shakeel.butt@linux.dev \
--cc=tj@kernel.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).