From: Shakeel Butt <shakeel.butt@linux.dev>
To: Tejun Heo <tj@kernel.org>, Johannes Weiner <hannes@cmpxchg.org>,
Peter Zijlstra <peterz@infradead.org>
Cc: "Michal Koutný" <mkoutny@suse.com>,
"Michal Hocko" <mhocko@kernel.org>,
"Roman Gushchin" <roman.gushchin@linux.dev>,
"Muchun Song" <muchun.song@linux.dev>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Ingo Molnar" <mingo@redhat.com>,
"Juri Lelli" <juri.lelli@redhat.com>,
"Vincent Guittot" <vincent.guittot@linaro.org>,
"Dietmar Eggemann" <dietmar.eggemann@arm.com>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Ben Segall" <bsegall@google.com>, "Mel Gorman" <mgorman@suse.de>,
"Valentin Schneider" <vschneid@redhat.com>,
"K Prateek Nayak" <kprateek.nayak@amd.com>,
"Suren Baghdasaryan" <surenb@google.com>,
"Kumar Kartikeya Dwivedi" <memxor@gmail.com>,
"David Dai" <david.dai@linux.dev>,
"JP Kobryn" <jp.kobryn@linux.dev>,
"Frederic Weisbecker" <frederic@kernel.org>,
"Aaron Lu" <ziqianlu@bytedance.com>,
"Daniel Jordan" <daniel.m.jordan@oracle.com>,
"Hao Lee" <haolee.swjtu@gmail.com>,
kernel-team@meta.com, cgroups@vger.kernel.org,
bpf@vger.kernel.org, linux-mm@kvack.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH 4/7] sched/fair: add cfs_bandwidth_charge() for kernel work done for a cgroup
Date: Thu, 24 Sep 2026 11:47:08 -0700 [thread overview]
Message-ID: <20260924184714.912181-5-shakeel.butt@linux.dev> (raw)
In-Reply-To: <20260924184714.912181-1-shakeel.butt@linux.dev>
set_active_cgroup() charges a kernel thread's CPU time to the cgroup it
works for, but only in cpu.stat. The work still does not count against
that cgroup's cpu.max.
Add cfs_bandwidth_charge(). It takes the time out of the cpu.max pool of
the cgroup's task group and of each limited ancestor, the same way the
group's own run time is taken. The work itself is never throttled: it
has already run. Instead the group's own tasks get less time afterwards.
What the pool cannot cover now becomes debt, paid out of the next
refills. The debt is capped at one period's quota, so a burst of work
cannot starve the group for long. Changing cpu.max clears it.
Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
---
kernel/sched/core.c | 1 +
kernel/sched/fair.c | 43 +++++++++++++++++++++++++++++++++++++++++++
kernel/sched/sched.h | 8 ++++++++
3 files changed, 52 insertions(+)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index b9e288b76da9..a487da494795 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -9809,6 +9809,7 @@ static int tg_set_cfs_bandwidth(struct task_group *tg,
cfs_b->period = ns_to_ktime(period);
cfs_b->quota = quota;
cfs_b->burst = burst;
+ cfs_b->debt = 0;
__refill_cfs_bandwidth_runtime(cfs_b);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 69145dda0df5..84250bd5caa2 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6626,6 +6626,7 @@ static inline u64 sched_cfs_bandwidth_slice(void)
void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b)
{
s64 runtime;
+ u64 pay;
if (unlikely(cfs_b->quota == RUNTIME_INF))
return;
@@ -6638,9 +6639,51 @@ void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b)
}
cfs_b->runtime = min(cfs_b->runtime, cfs_b->quota + cfs_b->burst);
+
+ /* Pay back the kernel work charged by cfs_bandwidth_charge(). */
+ pay = min(cfs_b->runtime, cfs_b->debt);
+ cfs_b->runtime -= pay;
+ cfs_b->debt -= pay;
+
cfs_b->runtime_snap = cfs_b->runtime;
}
+/*
+ * Kernel work used @delta of CPU time for @cgrp, see set_active_cgroup().
+ * Take it out of the quota of @cgrp's task group and of each ancestor with
+ * a limit, the same way the group's own run time is taken. What the pool
+ * cannot cover now becomes debt, paid out of the next refills. The debt is
+ * capped at one period's quota, so the work cannot starve the group for
+ * long.
+ */
+void cfs_bandwidth_charge(struct cgroup *cgrp, u64 delta)
+{
+ struct task_group *tg;
+
+ if (!cfs_bandwidth_used())
+ return;
+
+ guard(rcu)();
+ tg = css_tg(cgroup_e_css(cgrp, &cpu_cgrp_subsys));
+
+ /* No limit here or above. */
+ if (READ_ONCE(tg->cfs_bandwidth.hierarchical_quota) == RUNTIME_INF)
+ return;
+
+ for (; tg; tg = tg->parent) {
+ struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
+ u64 take;
+
+ guard(raw_spinlock_irqsave)(&cfs_b->lock);
+ if (cfs_b->quota == RUNTIME_INF)
+ continue;
+
+ take = min(delta, cfs_b->runtime);
+ cfs_b->runtime -= take;
+ cfs_b->debt = min(cfs_b->debt + delta - take, cfs_b->quota);
+ }
+}
+
static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
{
return &tg->cfs_bandwidth;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 6c3ad70e58b8..2d1adfd7ad37 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -456,6 +456,8 @@ struct cfs_bandwidth {
u64 runtime;
u64 burst;
u64 runtime_snap;
+ /* Kernel work charged by cfs_bandwidth_charge(), not paid yet: */
+ u64 debt;
s64 hierarchical_quota;
u8 idle;
@@ -618,6 +620,12 @@ static inline bool cfs_task_bw_constrained(struct task_struct *p) { return false
#endif /* !CONFIG_CGROUP_SCHED */
+#ifdef CONFIG_CFS_BANDWIDTH
+void cfs_bandwidth_charge(struct cgroup *cgrp, u64 delta);
+#else
+static inline void cfs_bandwidth_charge(struct cgroup *cgrp, u64 delta) { }
+#endif
+
/*
* A weight of 0 or 1 can cause arithmetics problems.
* A weight of a cfs_rq is the sum of weights of which entities
--
2.53.0-Meta
next prev parent reply other threads:[~2026-09-24 18:47 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 18:47 [RFC PATCH 0/7] cgroup: charge kernel work to the cgroup it is done for Shakeel Butt
2026-09-24 18:47 ` [RFC PATCH 1/7] cgroup: add cgroup_account_system_time() Shakeel Butt
2026-09-24 18:47 ` [RFC PATCH 2/7] cgroup: add set_active_cgroup() to charge CPU time to a cgroup Shakeel Butt
2026-09-24 18:47 ` [RFC PATCH 3/7] psi: charge pressure to the task's active cgroup Shakeel Butt
2026-09-24 18:47 ` Shakeel Butt [this message]
2026-09-24 18:47 ` [RFC PATCH 5/7] cgroup: take set_active_cgroup() time out of the cgroup's cpu.max Shakeel Butt
2026-09-24 18:47 ` [RFC PATCH 6/7] memcg: charge high_work reclaim to the memcg Shakeel Butt
2026-09-24 18:47 ` [RFC PATCH 7/7] selftests: cgroup: check that high_work reclaim is charged " Shakeel Butt
2026-09-24 20:28 ` [RFC PATCH 0/7] cgroup: charge kernel work to the cgroup it is done for Tejun Heo
2026-09-24 21:11 ` 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=20260924184714.912181-5-shakeel.butt@linux.dev \
--to=shakeel.butt@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=bpf@vger.kernel.org \
--cc=bsegall@google.com \
--cc=cgroups@vger.kernel.org \
--cc=daniel.m.jordan@oracle.com \
--cc=david.dai@linux.dev \
--cc=dietmar.eggemann@arm.com \
--cc=frederic@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=haolee.swjtu@gmail.com \
--cc=jp.kobryn@linux.dev \
--cc=juri.lelli@redhat.com \
--cc=kernel-team@meta.com \
--cc=kprateek.nayak@amd.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=memxor@gmail.com \
--cc=mgorman@suse.de \
--cc=mhocko@kernel.org \
--cc=mingo@redhat.com \
--cc=mkoutny@suse.com \
--cc=muchun.song@linux.dev \
--cc=peterz@infradead.org \
--cc=roman.gushchin@linux.dev \
--cc=rostedt@goodmis.org \
--cc=surenb@google.com \
--cc=tj@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
--cc=ziqianlu@bytedance.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
all inboxes | Powered by JetHome®