All of lore.kernel.org
 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: 18+ 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
2026-11-11 12:29 ` [PATCH v3 0/2] sched/fair: cpu.max.runtime and idle refill for a burstable budget Fernand Sieber
2026-11-11 12:29   ` [PATCH v3 1/2] sched/fair: expose cpu.max.runtime to set bandwidth runtime directly Fernand Sieber
2026-11-11 12:29   ` [PATCH v3 2/2] sched/fair: refill bandwidth for the periods the timer slept through 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 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.