From: sashiko-bot@kernel.org
To: "Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>
Cc: linux-rt-devel@lists.linux.dev, tj@kernel.org,
hannes@cmpxchg.org, mkoutny@suse.com,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 18/24] sched/deadline: Credit a rebuild to the CPU recorded with the task's bandwidth
Date: Thu, 05 Nov 2026 20:58:52 +0000 [thread overview]
Message-ID: <sashiko-outbox-200171@kernel.org> (raw)
In-Reply-To: <20261105193359.1450487-19-mathieu.desnoyers@efficios.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] sched/deadline: stale HK_TYPE_DOMAIN mask used in dl_get_task_effective_cpus()
- [High] sched/deadline: dl_task_rebuild_cpu() drops cpu from dl_task_offline_migration()
--
commit 8fc0e93077a2156f71e1f02a2a295664e07d7e75
Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
sched/deadline: Credit a rebuild to the CPU recorded with the task's bandwidth
This commit adds dl_task_rebuild_cpu() so that root domain bandwidth
rebuilds credit a deadline task's bandwidth to its previously recorded
CPU when active and allowed, falling back to an active housekeeping or
cpuset-allowed CPU, or skipping the task when no active CPU is available.
> diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
> index a058e0c65eca4..bcf7f88b204ad 100644
> --- a/kernel/sched/deadline.c
> +++ b/kernel/sched/deadline.c
> @@ -3607,6 +3607,36 @@ static void dl_get_task_effective_cpus(struct task_struct *p, struct cpumask *cp
> cpuset_cpus_allowed_locked(p, cpus);
> }
>
> +/*
> + * A CPU of the root domain that a rebuild of the accounting counts @p's
> + * bandwidth in. The one recorded with it, where it is active and the
> + * cpuset of @p allows it: that of the root domain that admitted the
> + * bandwidth, or that the last move put it in, which the cpuset alone does
> + * not tell where it holds CPUs of two root domains, housekeeping ones
> + * beside the ones isolcpus="domain" leaves to the default root domain. The
> + * record answers as well for a task whose own CPUs went offline, moved to
> + * an active one by dl_task_offline_migration(). Else the first active CPU
> + * the cpuset allows, a housekeeping one where it has any; and nr_cpu_ids
> + * where it allows none, which the isolated CPUs allow, no deadline task
> + * of theirs keeping the last of them online.
> + */
> +static unsigned int dl_task_rebuild_cpu(struct task_struct *p)
> +{
> + struct cpumask *msk = this_cpu_cpumask_var_ptr(local_cpu_mask_dl);
> + int recorded = p->dl.dl_bw_cpu;
> + unsigned int cpu;
> +
> + dl_get_task_effective_cpus(p, msk);
> + cpumask_and(msk, msk, cpu_active_mask);
> + if (recorded >= 0 && cpu_active(recorded) &&
> + (cpumask_test_cpu(recorded, msk) || cpumask_empty(msk)))
> + return recorded;
[Severity: High]
As reported by Sashiko on v2 [1], does calling dl_get_task_effective_cpus()
here still observe the lagging HK_TYPE_DOMAIN mask during cpuset partition
transitions?
In kernel/sched/deadline.c, dl_get_task_effective_cpus() checks
housekeeping_cpumask(HK_TYPE_DOMAIN):
hk_msk = housekeeping_cpumask(HK_TYPE_DOMAIN);
if (housekeeping_enabled(HK_TYPE_DOMAIN)) {
if (!cpumask_intersects(p->cpus_ptr, hk_msk)) {
cpumask_andnot(cpus, cpu_active_mask, hk_msk);
return;
}
}
Because cpuset_update_sd_hk_unlock() and cpuset_handle_hotplug() invoke
rebuild_sched_domains_locked() -> dl_rebuild_rd_accounting() before calling
housekeeping_update(), HK_TYPE_DOMAIN still reflects the pre-transition
isolated partitions and excludes all CPUs in any PRS_ISOLATED partition.
For example, if an isolated partition on CPUs 2-3 containing a deadline task
p admitted on CPU 2 (p->dl.dl_bw_cpu == 2) is shrunk to CPU 3, CPU 2 returns
to top_cpuset's root domain while cpuset_update_tasks_cpumask() updates
p->cpus_ptr to {3} without SCA_DL_BW_RESERVED. During the rebuild,
HK_TYPE_DOMAIN still excludes both CPU 2 and CPU 3, so
dl_get_task_effective_cpus() sets msk to {2, 3}. In dl_task_rebuild_cpu(),
cpumask_test_cpu(recorded, msk) then succeeds for CPU 2 (and the fallback
cpumask_first_and(msk, housekeeping_cpumask(HK_TYPE_DOMAIN_BOOT)) would also
pick CPU 2), crediting p's bandwidth to top_cpuset's root domain instead of
def_root_domain.
Similarly, if another CPU (such as CPU 1) is isolated by isolcpus=domain,1
or in another isolated partition while an isolated partition on CPU 2
transitions from PRS_ISOLATED to PRS_ROOT or PRS_MEMBER, HK_TYPE_DOMAIN
still excludes {1, 2} during the rebuild, so dl_get_task_effective_cpus()
sets msk to {1, 2} rather than the cpuset's allowed CPUs {2}. Conversely,
because HK_TYPE_DOMAIN is built from cpu_possible_mask, if a task running on
boot-isolated CPUs in def_root_domain has offline housekeeping CPUs in
p->cpus_ptr, cpumask_intersects(p->cpus_ptr, hk_msk) evaluates to true and
falls through to cpuset_cpus_allowed_locked(), causing dl_task_rebuild_cpu()
to prefer an active housekeeping CPU over remaining active isolated CPUs in
def_root_domain when the recorded CPU goes offline.
> + cpu = cpumask_first_and(msk, housekeeping_cpumask(HK_TYPE_DOMAIN_BOOT));
> + if (cpu < nr_cpu_ids)
> + return cpu;
> + return cpumask_first(msk);
> +}
> +
> /* The caller should hold cpuset_mutex */
> void dl_add_task_root_domain(struct task_struct *p)
> {
> @@ -3614,7 +3644,6 @@ void dl_add_task_root_domain(struct task_struct *p)
> struct rq *rq;
> struct dl_bw *dl_b;
> unsigned int cpu;
> - struct cpumask *msk;
>
> raw_spin_lock_irqsave(&p->pi_lock, rf.flags);
> /*
> @@ -3626,10 +3655,16 @@ void dl_add_task_root_domain(struct task_struct *p)
> return;
> }
>
> - msk = this_cpu_cpumask_var_ptr(local_cpu_mask_dl);
> - dl_get_task_effective_cpus(p, msk);
> - cpu = cpumask_first_and(cpu_active_mask, msk);
> - BUG_ON(cpu >= nr_cpu_ids);
> + cpu = dl_task_rebuild_cpu(p);
> + if (cpu >= nr_cpu_ids) {
> + /*
> + * No active CPU to count this task's bandwidth: leave it out
> + * of this rebuild, where dl_bw_gen keeps its release out as
> + * well, until one has a CPU for it.
> + */
> + raw_spin_unlock_irqrestore(&p->pi_lock, rf.flags);
> + return;
> + }
[Severity: High]
As reported by Sashiko on v2 [2], can a throttled deadline task migrated by
dl_task_offline_migration() still have its bandwidth credited to the wrong
root domain or left unaccounted?
When all CPUs in p->cpus_ptr are offline, dl_task_offline_migration() sees
cpumask_any_and(cpu_active_mask, p->cpus_ptr) >= nr_cpu_ids and falls back to
cpumask_any(cpu_active_mask), moving the task and p->dl.dl_bw_cpu to an
active CPU while p->cpus_ptr still contains only the offline CPUs.
In dl_task_rebuild_cpu(), the check preserving recorded when the task's own
CPUs are offline tests cpumask_empty(msk), where msk is the result of
dl_get_task_effective_cpus(p, msk) & cpu_active_mask rather than
p->cpus_ptr & cpu_active_mask. If other CPUs in msk remain active outside
p->cpus_ptr (for instance, with isolcpus=domain,1,2 when p is affined to
CPU 1 and CPU 1 goes offline while CPU 2 stays online, or when p is pinned
to one CPU of a multi-CPU cpuset with admission control disabled and moved to
another partition's CPU), msk is non-empty ({2}) and does not contain the
fallback CPU recorded by dl_task_offline_migration() (such as CPU 0).
dl_task_rebuild_cpu() then rejects recorded and credits p's bandwidth to
CPU 2's root domain while p runs on CPU 0.
Additionally, during CPU deactivation in sched_cpu_deactivate(),
cpuset_cpu_inactive() runs dl_rebuild_rd_accounting() immediately after
sched_set_rq_offline(), before a throttled task's hrtimer fires
dl_task_timer() -> dl_task_offline_migration(). If the deactivated CPU was
the task's last active CPU in msk, dl_task_rebuild_cpu() returns nr_cpu_ids
and dl_add_task_root_domain() returns early without updating
p->dl.dl_bw_gen. When dl_task_timer() subsequently fires and calls
dl_task_offline_migration():
scoped_guard (raw_spinlock, &dl_departed_lock) {
if (p->dl.dl_bw_gen == dl_bw_gen) {
...
__dl_add(dl_b, p->dl.dl_bw,
cpumask_weight(later_rq->rd->span));
raw_spin_unlock(&dl_b->lock);
}
p->dl.dl_bw_cpu = later_rq->cpu;
}
Because p->dl.dl_bw_gen != dl_bw_gen, doesn't dl_task_offline_migration()
skip adding p->dl.dl_bw to later_rq->rd->dl_bw, leaving the migrated task's
bandwidth unaccounted until another root domain rebuild occurs?
[1] https://lore.kernel.org/r/sashiko-outbox-198343@kernel.org
[2] https://lore.kernel.org/r/sashiko-outbox-198343@kernel.org
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105193359.1450487-1-mathieu.desnoyers@efficios.com?part=18
next prev parent reply other threads:[~2026-11-05 20:58 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 19:33 [PATCH v3 00/24] sched/deadline: bandwidth accounting fixes and selftests Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 01/24] sched: Fix cpuset_mutex double unlock in __sched_setscheduler() Mathieu Desnoyers
2026-11-05 19:51 ` Kayra Cizmeci
2026-11-05 19:54 ` Mathieu Desnoyers
2026-11-05 19:59 ` Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 02/24] sched: Refuse SCHED_FLAG_KEEP_PARAMS that would change the policy or the class Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 03/24] sched/deadline: Do not admit bandwidth for parameters that are kept Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 04/24] sched/deadline: Do not divide by zero active CPUs of a root domain Mathieu Desnoyers
2026-11-05 19:59 ` sashiko-bot
2026-11-05 19:33 ` [PATCH v3 05/24] sched: Take cpuset_mutex for a deadline policy change only with pi Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 06/24] sched/deadline: Do not lose a throttled task switched out and back Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 07/24] sched/deadline: Reset the deadline and the runtime with the parameters Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 08/24] sched/deadline: Release the bandwidth of a task that leaves the class asleep Mathieu Desnoyers
2026-11-05 20:10 ` sashiko-bot
2026-11-05 19:33 ` [PATCH v3 09/24] sched/deadline: Reject SCHED_DEADLINE on exited tasks Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 10/24] sched/deadline: Keep departing bandwidth across a root domain rebuild Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 11/24] sched/deadline: Do not take a waking task's bandwidth off a runqueue it left Mathieu Desnoyers
2026-11-05 20:35 ` sashiko-bot
2026-11-05 19:33 ` [PATCH v3 12/24] sched/deadline: Rebuild the root domains' accounting without cpusets too Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 13/24] sched/deadline: Leave a dying task out of a rebuild of the accounting Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 14/24] sched/deadline: Record the root domain holding a task's bandwidth Mathieu Desnoyers
2026-11-05 20:50 ` sashiko-bot
2026-11-05 19:33 ` [PATCH v3 15/24] sched/deadline: Move a task's bandwidth only where room was made Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 16/24] cgroup/cpuset: Wait for an attach before rebuilding the sched domains Mathieu Desnoyers
2026-11-05 20:36 ` sashiko-bot
2026-11-05 19:33 ` [PATCH v3 17/24] cgroup/cpuset: Give back the bandwidth an attach did not move Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 18/24] sched/deadline: Credit a rebuild to the CPU recorded with the task's bandwidth Mathieu Desnoyers
2026-11-05 20:58 ` sashiko-bot [this message]
2026-11-05 19:33 ` [PATCH v3 19/24] sched/deadline: Cancel the replenishment timer with the parameters Mathieu Desnoyers
2026-11-05 21:05 ` sashiko-bot
2026-11-05 19:33 ` [PATCH v3 20/24] sched/deadline: Count the bandwidth a boosted task is given Mathieu Desnoyers
2026-11-05 21:13 ` sashiko-bot
2026-11-05 19:33 ` [PATCH v3 21/24] sched/debug: Show the deadline bandwidth of each runqueue Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 22/24] selftests/sched: Add a test of SCHED_DEADLINE policy round trips Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 23/24] selftests/sched: Test SCHED_DEADLINE bandwidth across a root domain rebuild Mathieu Desnoyers
2026-11-05 19:33 ` [PATCH v3 24/24] selftests/sched: Add a test of SCHED_DEADLINE bandwidth accounting Mathieu Desnoyers
2026-11-05 21:17 ` sashiko-bot
2026-11-05 21:20 ` [PATCH v3 00/24] sched/deadline: bandwidth accounting fixes and selftests Mathieu Desnoyers
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-200171@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=mathieu.desnoyers@efficios.com \
--cc=mkoutny@suse.com \
--cc=sashiko-reviews@lists.linux.dev \
--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.