summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-10-26 14:17:45 -1000
committerTejun Heo <tj@kernel.org>2026-10-27 09:40:56 -1000
commit53cc8dd06944979fd6a4754958aa8d6fa159f2da (patch)
treeb29f6a986b6164136d54b93762a49db2a303735f /kernel
parent947dd3eb80df8e83683182271d2782867befd333 (diff)
sched_ext: Fix the bypass load balancer stranding tasks on cpus where the host lacks SCX_CAP_BASE
The bypass load balancer spreads a host's bypassed tasks over the cpus of a node by moving them between its per-cpu bypass DSQs. It counts every cpu of the node as capacity and takes any cpu below the target as a donee. A cpu's dispatch only descends into schedulers holding SCX_CAP_BASE on it, so a bypass DSQ on a cpu where the host lacks BASE is never consumed. A task moved there sits until the host regains the cap or the bypass window ends. Count only cpus where the host holds BASE as capacity and pick donees from them. The target rises to spread the node's tasks over the cpus that can run them, and a capless cpu receives nothing. A capless cpu with tasks is still an ordinary donor, offloaded down to the donor target when its queue grows past the threshold; draining it is left to the following patches. Fixes: 147d1885f390 ("sched_ext: Add the SCX_CAP_ENQ_IMMED cap") Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/ext/ext.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
index 3645a844cfbc..4ee802fad9df 100644
--- a/kernel/sched/ext/ext.c
+++ b/kernel/sched/ext/ext.c
@@ -6741,7 +6741,9 @@ static void bypass_lb_node(struct scx_sched *sch, int node)
u32 nr = READ_ONCE(scx_bypass_dsq(sch, cpu)->nr);
nr_tasks += nr;
- nr_cpus++;
+ /* only a cpu whose dispatch consumes its DSQ is capacity */
+ if (!scx_missing_caps(sch, cpu, SCX_CAP_BASE))
+ nr_cpus++;
before_min = min(nr, before_min);
before_max = max(nr, before_max);
@@ -6760,7 +6762,9 @@ static void bypass_lb_node(struct scx_sched *sch, int node)
cpumask_clear(donee_mask);
for_each_cpu_and(cpu, cpu_online_mask, node_mask) {
- if (READ_ONCE(scx_bypass_dsq(sch, cpu)->nr) < nr_target)
+ /* a donee's DSQ is consumed only if @sch holds %SCX_CAP_BASE */
+ if (READ_ONCE(scx_bypass_dsq(sch, cpu)->nr) < nr_target &&
+ !scx_missing_caps(sch, cpu, SCX_CAP_BASE))
cpumask_set_cpu(cpu, donee_mask);
}