From: Pingfan Liu <piliu@redhat.com>
To: Waiman Long <llong@redhat.com>
Cc: linux-kernel@vger.kernel.org, cgroups@vger.kernel.org,
"Peter Zijlstra" <peterz@infradead.org>,
"Juri Lelli" <juri.lelli@redhat.com>,
"Pierre Gondois" <pierre.gondois@arm.com>,
"Frederic Weisbecker" <frederic@kernel.org>,
"Ingo Molnar" <mingo@redhat.com>, "Tejun Heo" <tj@kernel.org>,
"Johannes Weiner" <hannes@cmpxchg.org>,
"Michal Koutný" <mkoutny@suse.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>
Subject: Re: [PATCHv4 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug
Date: Thu, 30 Oct 2025 18:41:22 +0800 [thread overview]
Message-ID: <aQNA0m5U2KgyeCby@fedora> (raw)
In-Reply-To: <52252077-30cb-4a71-ba2a-1c4ecb36df37@redhat.com>
On Wed, Oct 29, 2025 at 11:31:23AM -0400, Waiman Long wrote:
> On 10/27/25 11:43 PM, Pingfan Liu wrote:
> > *** Bug description ***
> > When testing kexec-reboot on a 144 cpus machine with
> > isolcpus=managed_irq,domain,1-71,73-143 in kernel command line, I
> > encounter the following bug:
> >
> > [ 97.114759] psci: CPU142 killed (polled 0 ms)
> > [ 97.333236] Failed to offline CPU143 - error=-16
> > [ 97.333246] ------------[ cut here ]------------
> > [ 97.342682] kernel BUG at kernel/cpu.c:1569!
> > [ 97.347049] Internal error: Oops - BUG: 00000000f2000800 [#1] SMP
> > [...]
> >
> > In essence, the issue originates from the CPU hot-removal process, not
> > limited to kexec. It can be reproduced by writing a SCHED_DEADLINE
> > program that waits indefinitely on a semaphore, spawning multiple
> > instances to ensure some run on CPU 72, and then offlining CPUs 1–143
> > one by one. When attempting this, CPU 143 failed to go offline.
> > bash -c 'taskset -cp 0 $$ && for i in {1..143}; do echo 0 > /sys/devices/system/cpu/cpu$i/online 2>/dev/null; done'
> >
> > `
> > *** Issue ***
> > Tracking down this issue, I found that dl_bw_deactivate() returned
> > -EBUSY, which caused sched_cpu_deactivate() to fail on the last CPU.
> > But that is not the fact, and contributed by the following factors:
> > When a CPU is inactive, cpu_rq()->rd is set to def_root_domain. For an
> > blocked-state deadline task (in this case, "cppc_fie"), it was not
> > migrated to CPU0, and its task_rq() information is stale. So its rq->rd
> > points to def_root_domain instead of the one shared with CPU0. As a
> > result, its bandwidth is wrongly accounted into a wrong root domain
> > during domain rebuild.
> >
> > The key point is that root_domain is only tracked through active rq->rd.
> > To avoid using a global data structure to track all root_domains in the
> > system, there should be a method to locate an active CPU within the
> > corresponding root_domain.
> >
> > *** Solution ***
> > To locate the active cpu, the following rules for deadline
> > sub-system is useful
> > -1.any cpu belongs to a unique root domain at a given time
> > -2.DL bandwidth checker ensures that the root domain has active cpus.
> >
> > Now, let's examine the blocked-state task P.
> > If P is attached to a cpuset that is a partition root, it is
> > straightforward to find an active CPU.
> > If P is attached to a cpuset that has changed from 'root' to 'member',
> > the active CPUs are grouped into the parent root domain. Naturally, the
> > CPUs' capacity and reserved DL bandwidth are taken into account in the
> > ancestor root domain. (In practice, it may be unsafe to attach P to an
> > arbitrary root domain, since that domain may lack sufficient DL
> > bandwidth for P.) Again, it is straightforward to find an active CPU in
> > the ancestor root domain.
> >
> > This patch groups CPUs into isolated and housekeeping sets. For the
> > housekeeping group, it walks up the cpuset hierarchy to find active CPUs
> > in P's root domain and retrieves the valid rd from cpu_rq(cpu)->rd.
> >
> > Signed-off-by: Pingfan Liu <piliu@redhat.com>
> > Cc: Waiman Long <longman@redhat.com>
> > Cc: Tejun Heo <tj@kernel.org>
> > Cc: Johannes Weiner <hannes@cmpxchg.org>
> > Cc: "Michal Koutný" <mkoutny@suse.com>
> > Cc: Ingo Molnar <mingo@redhat.com>
> > Cc: Peter Zijlstra <peterz@infradead.org>
> > Cc: Juri Lelli <juri.lelli@redhat.com>
> > Cc: Pierre Gondois <pierre.gondois@arm.com>
> > Cc: Vincent Guittot <vincent.guittot@linaro.org>
> > Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
> > Cc: Steven Rostedt <rostedt@goodmis.org>
> > Cc: Ben Segall <bsegall@google.com>
> > Cc: Mel Gorman <mgorman@suse.de>
> > Cc: Valentin Schneider <vschneid@redhat.com>
> > To: cgroups@vger.kernel.org
> > To: linux-kernel@vger.kernel.org
> > ---
> > v3 -> v4:
> > rename function with cpuset_ prefix
> > improve commit log
> >
> > include/linux/cpuset.h | 18 ++++++++++++++++++
> > kernel/cgroup/cpuset.c | 26 ++++++++++++++++++++++++++
> > kernel/sched/deadline.c | 30 ++++++++++++++++++++++++------
> > 3 files changed, 68 insertions(+), 6 deletions(-)
> >
> > diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
> > index 2ddb256187b51..d4da93e51b37b 100644
> > --- a/include/linux/cpuset.h
> > +++ b/include/linux/cpuset.h
> > @@ -12,6 +12,7 @@
> > #include <linux/sched.h>
> > #include <linux/sched/topology.h>
> > #include <linux/sched/task.h>
> > +#include <linux/sched/housekeeping.h>
> > #include <linux/cpumask.h>
> > #include <linux/nodemask.h>
> > #include <linux/mm.h>
> > @@ -130,6 +131,7 @@ extern void rebuild_sched_domains(void);
> > extern void cpuset_print_current_mems_allowed(void);
> > extern void cpuset_reset_sched_domains(void);
> > +extern void cpuset_get_task_effective_cpus(struct task_struct *p, struct cpumask *cpus);
> > /*
> > * read_mems_allowed_begin is required when making decisions involving
> > @@ -276,6 +278,22 @@ static inline void cpuset_reset_sched_domains(void)
> > partition_sched_domains(1, NULL, NULL);
> > }
> > +static inline void cpuset_get_task_effective_cpus(struct task_struct *p,
> > + struct cpumask *cpus)
> > +{
> > + const struct cpumask *hk_msk;
> > +
> > + hk_msk = housekeeping_cpumask(HK_TYPE_DOMAIN);
> > + if (housekeeping_enabled(HK_TYPE_DOMAIN)) {
> > + if (!cpumask_intersects(p->cpus_ptr, hk_msk)) {
> > + /* isolated cpus belong to a root domain */
> > + cpumask_andnot(cpus, cpu_active_mask, hk_msk);
> > + return;
> > + }
> > + }
> > + cpumask_and(cpus, cpu_active_mask, hk_msk);
> > +}
> > +
> > static inline void cpuset_print_current_mems_allowed(void)
> > {
> > }
> > diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> > index 27adb04df675d..6ad88018f1a4e 100644
> > --- a/kernel/cgroup/cpuset.c
> > +++ b/kernel/cgroup/cpuset.c
> > @@ -1102,6 +1102,32 @@ void cpuset_reset_sched_domains(void)
> > mutex_unlock(&cpuset_mutex);
> > }
> > +/* caller hold RCU read lock */
> > +void cpuset_get_task_effective_cpus(struct task_struct *p, struct cpumask *cpus)
> > +{
> > + const struct cpumask *hk_msk;
> > + struct cpuset *cs;
> > +
> > + hk_msk = housekeeping_cpumask(HK_TYPE_DOMAIN);
> > + if (housekeeping_enabled(HK_TYPE_DOMAIN)) {
> > + if (!cpumask_intersects(p->cpus_ptr, hk_msk)) {
> > + /* isolated cpus belong to a root domain */
> > + cpumask_andnot(cpus, cpu_active_mask, hk_msk);
> > + return;
> > + }
> > + }
> > + /* In HK_TYPE_DOMAIN, cpuset can be applied */
> > + cs = task_cs(p);
> > + while (cs != &top_cpuset) {
> > + if (is_sched_load_balance(cs))
> > + break;
> > + cs = parent_cs(cs);
> > + }
> > +
> > + /* For top_cpuset, its effective_cpus does not exclude isolated cpu */
> > + cpumask_and(cpus, cs->effective_cpus, hk_msk);
> > +}
> > +
>
> It looks like you are trying to find a set of CPUs that are definitely in a
> active sched domain. The difference between this version and the
> !CONFIG_CPUSETS version in cpuset.h is the going up the cpuset hierarchy to
> find one with load balancing enabled. I would suggest you extract just this
> part out as a cpuset helper function and put the rests into deadline.c as a
> separate helper function without the cpuset prefix. In that way, you don't
> create a new housekeeping.h header file.
>
A good suggestion, thanks!
Best Regards,
Pingfan
next prev parent reply other threads:[~2025-10-30 10:41 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20251028034357.11055-1-piliu@redhat.com>
2025-10-28 3:43 ` [PATCHv4 2/2] sched/deadline: Walk up cpuset hierarchy to decide root domain when hot-unplug Pingfan Liu
2025-10-29 2:37 ` Chen Ridong
2025-10-29 11:18 ` Pingfan Liu
2025-10-30 6:44 ` Chen Ridong
2025-10-30 10:45 ` Pingfan Liu
2025-10-31 0:47 ` Chen Ridong
2025-10-31 14:21 ` Pingfan Liu
2025-11-03 3:17 ` Pingfan Liu
2025-10-29 15:31 ` Waiman Long
2025-10-30 10:41 ` Pingfan Liu [this message]
2025-11-03 13:50 ` Juri Lelli
2025-11-04 3:34 ` Pingfan Liu
2025-11-04 3:42 ` Waiman Long
2025-11-05 2:23 ` Chen Ridong
2025-11-05 7:11 ` Pingfan Liu
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=aQNA0m5U2KgyeCby@fedora \
--to=piliu@redhat.com \
--cc=bsegall@google.com \
--cc=cgroups@vger.kernel.org \
--cc=dietmar.eggemann@arm.com \
--cc=frederic@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=juri.lelli@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=llong@redhat.com \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=mkoutny@suse.com \
--cc=peterz@infradead.org \
--cc=pierre.gondois@arm.com \
--cc=rostedt@goodmis.org \
--cc=tj@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.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).