BPF List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Fernand Sieber" <sieberf@amazon.com>
Cc: sched-ext@lists.linux.dev, bpf@vger.kernel.org, tj@kernel.org,
	hannes@cmpxchg.org, mkoutny@suse.com
Subject: Re: [PATCH v2 1/4] sched/fair: expose cpu.max.runtime to set bandwidth runtime directly
Date: Tue, 10 Nov 2026 11:28:40 +0000	[thread overview]
Message-ID: <sashiko-outbox-206937@kernel.org> (raw)
In-Reply-To: <9741224b8d2b19760f85c1f854d61f30fa7d9710.1794303670.git.sieberf@amazon.com>

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Medium] sched/fair: distribute_cfs_runtime() IRQ assert fails on
  PREEMPT_RT
- [Medium] selftests/cgroup: hog burns runtime before period start in
  test_cpu
- [Low] selftests/cgroup: missing CONFIG_CFS_BANDWIDTH skip in test_cpu
--

commit bbd8379bd9e3f88e46c648f7388044e945e9df20
Author: Fernand Sieber <sieberf@amazon.com>

sched/fair: expose cpu.max.runtime to set bandwidth runtime directly

This commit adds the cgroup v2 cpu.max.runtime file to read and set
cfs_b->runtime directly, lifts the burst <= quota restriction, and adds
cgroup selftests for the new interface.

> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index d4cc0caee6265..58e948ed1792f 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -7421,6 +7421,8 @@ static bool distribute_cfs_runtime(struct cfs_bandwidth *cfs_b)
>  	struct cfs_rq *cfs_rq;
>  	struct rq *rq;
>  
> +	lockdep_assert_irqs_disabled();
> +
>  	guard(rcu)();
>  
>  	list_for_each_entry_rcu(cfs_rq, &cfs_b->throttled_cfs_rq,

[Severity: Medium]
Does lockdep_assert_irqs_disabled() trigger a lockdep warning on
CONFIG_PREEMPT_RT when distribute_cfs_runtime() is called from
do_sched_cfs_period_timer() or do_sched_cfs_slack_timer()?

init_cfs_bandwidth() sets up cfs_b->period_timer and cfs_b->slack_timer
without HRTIMER_MODE_HARD, so on CONFIG_PREEMPT_RT their callbacks run in
softirq context with hardware interrupts enabled.  Both
do_sched_cfs_period_timer() and do_sched_cfs_slack_timer() release
cfs_b->lock via raw_spin_unlock_irqrestore() before calling
distribute_cfs_runtime(cfs_b), leaving hardware interrupts enabled on
entry.  (distribute_cfs_runtime() itself uses guard(rq_lock_irqsave)(rq)
and scoped_guard(irqsave) around __cfsb_csd_unthrottle() for that reason.)

> diff --git a/tools/testing/selftests/cgroup/test_cpu.c b/tools/testing/selftests/cgroup/test_cpu.c
> index 3456e3e988c68..278d7e16eeb2c 100644
> --- a/tools/testing/selftests/cgroup/test_cpu.c
> +++ b/tools/testing/selftests/cgroup/test_cpu.c

[ ... ]

> +static int test_cpucg_max_runtime(const char *root)
> +{

[ ... ]

> +	cpucg = cg_name(root, "cpucg_runtime_test");
> +	if (!cpucg)
> +		goto cleanup;
> +
> +	if (cg_create(cpucg))
> +		goto cleanup;
> +
> +	/* Without a quota there is no runtime to set. */
> +	if (!cg_write_numeric(cpucg, "cpu.max.runtime", runtime_usec))
> +		goto cleanup;

[Severity: Low]
Should the new test_cpucg_max_runtime* tests check whether
cpu.max.runtime exists and return KSFT_SKIP when CONFIG_CFS_BANDWIDTH is
disabled (or add CONFIG_CFS_BANDWIDTH=y to
tools/testing/selftests/cgroup/config)?

cpu.max.runtime is only created under CONFIG_CFS_BANDWIDTH, which
defaults to n and is not listed in tools/testing/selftests/cgroup/config,
so all five tests currently return KSFT_FAIL on kernels built without it.

[ ... ]

> +static int test_cpucg_max_runtime_burst_kept(const char *root)
> +{
> +	int ret = KSFT_FAIL;
> +	long burst_before, burst_after, runtime_usec;
> +	char *cpucg;
> +	int pid;
> +
> +	cpucg = cg_name(root, "cpucg_runtime_burst_kept_test");
> +	if (!cpucg)
> +		goto cleanup;
> +
> +	if (cg_create(cpucg))
> +		goto cleanup;
> +
> +	/* 10ms per 1s period, and a runtime of 1s to run on. */
> +	if (cg_write(cpucg, "cpu.max", "10000 1000000"))
> +		goto cleanup;
> +	if (cg_write_numeric(cpucg, "cpu.max.burst", 990000))
> +		goto cleanup;
> +	if (cg_write_numeric(cpucg, "cpu.max.runtime", 1000000))
> +		goto cleanup;
> +
> +	struct cpu_hog_func_param param = {
> +		.nprocs = 1,
> +		.ts = { .tv_sec = 10, .tv_nsec = 0 },
> +		.clock_type = CPU_HOG_CLOCK_WALL,
> +	};
> +	pid = cg_run_nowait(cpucg, hog_cpus_timed, (void *)&param);
> +	if (pid < 0)
> +		goto cleanup;
> +
> +	/* Run some 300ms, all in one period, and stop. */
> +	if (wait_period_start(cpucg)) {
> +		kill(pid, SIGKILL);
> +		waitpid(pid, NULL, 0);
> +		goto cleanup;
> +	}
> +	burst_before = cg_read_key_long(cpucg, "cpu.stat", "burst_usec");
> +	usleep(300000);
> +	kill(pid, SIGKILL);
> +	waitpid(pid, NULL, 0);
> +
> +	/* Write back what is left: the next refill counts the 300ms run. */
> +	runtime_usec = cg_read_long(cpucg, "cpu.max.runtime");
> +	if (cg_write_numeric(cpucg, "cpu.max.runtime", runtime_usec))
> +		goto cleanup;
> +	sleep(1);
> +	burst_after = cg_read_key_long(cpucg, "cpu.stat", "burst_usec");
> +	if (burst_before < 0 || burst_after - burst_before < 250000)
> +		goto cleanup;

[Severity: Medium]
Can hog_cpus_timed burn most of the 1s cpu.max.runtime before
wait_period_start() returns?

Because cfs_b->period_timer starts with a random offset,
wait_period_start() can wait up to 1s for the first period boundary while
the hog is already running.  When that wait exceeds ~750ms, the refill at
the period boundary only adds the 10ms quota, leaving less than 250ms of
runtime for the measured 300ms window and causing the
burst_after - burst_before < 250000 check to fail.  Writing 1000000 to
cpu.max.runtime after wait_period_start() (or starting the hog after it)
would avoid draining the runtime early.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1794303670.git.sieberf@amazon.com?part=1

  reply	other threads:[~2026-11-10 11:28 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 11:08 [PATCH v2 0/4] sched/fair: cpu.max.runtime and idle refill for CPU credits Fernand Sieber
2026-11-10 11:08 ` [PATCH v2 1/4] sched/fair: expose cpu.max.runtime to set bandwidth runtime directly Fernand Sieber
2026-11-10 11:28   ` sashiko-bot [this message]
2026-11-11  8:28   ` bot+bpf-ci
2026-11-10 11:08 ` [PATCH v2 2/4] sched/fair: refill bandwidth for the periods the timer slept through Fernand Sieber
2026-11-10 11:29   ` sashiko-bot
2026-11-10 11:08 ` [PATCH v2 3/4] sched_ext: add cgroup_set_runtime ops callback Fernand Sieber
2026-11-11  8:08   ` bot+bpf-ci
2026-11-10 11:08 ` [PATCH v2 4/4] sched_ext: charge BPF scheduler tasks to cpu.max bandwidth Fernand Sieber
2026-11-10 11:39   ` sashiko-bot
2026-11-11  8:28   ` bot+bpf-ci
2026-11-10 20:10 ` [PATCH v2 0/4] sched/fair: cpu.max.runtime and idle refill for CPU credits Tejun Heo
2026-11-11 12:20   ` Fernand Sieber
2026-11-11 17:26     ` Tejun Heo
2026-11-12  8:11       ` Fernand Sieber

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=sashiko-outbox-206937@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=mkoutny@suse.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=sched-ext@lists.linux.dev \
    --cc=sieberf@amazon.com \
    --cc=tj@kernel.org \
    /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