Re: [PATCH 09/12] sched_ext: Eject the top rescue consumer on overload

[email protected] Sat, 01 Aug 2026 09:11:14 +0000
Newsgroups dev.linux.lists.sched-ext
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 1 potential issue(=
s) to consider:
- [Medium] The `time_before()` check in `scx_rescue_check_overload()` suffe=
rs from a 32-bit jiffies wraparound vulnerability, disabling rescue overloa=
d protection for 24.8-day intervals on systems with 32-bit `unsigned long`.
--

--- Patch [9]: [PATCH 09/12] sched_ext: Eject the top rescue consumer on ov=
erload ---
commit 50e2ffc187a8450dacf680dcf11b98c2167b7621
Author: Tejun Heo <[email protected]>

sched_ext: Eject the top rescue consumer on overload

This patch tracks each scheduler's recent rescue consumption per CPU as a
decaying average. If the oldest waiter on a CPU's rescue DSQ waits past a
configured threshold, the sub-scheduler with the highest recent consumption
is ejected. This prevents the generic stall watchdog from unfairly blaming
the waiting task's owner instead of the misbehaving party.

> diff --git a/kernel/sched/ext/sub.c b/kernel/sched/ext/sub.c
> index 3c1f11268e7f3..fdbe1c1bfaa8d 100644
> --- a/kernel/sched/ext/sub.c
> +++ b/kernel/sched/ext/sub.c

[ ... ]

> @@ -434,6 +459,63 @@ static bool scx_rescue_try_admit(struct rq *rq, stru=
ct task_struct *p)
>  	return false;
>  }
> =20
> +/**
> + * scx_rescue_check_overload - Eject the top rescue consumer on a stuck =
rescue
> + * @rq: rq whose rescue timer fired
> + *
> + * If the oldest waiter on @rq's rescue DSQ has been queued for too long=
, rescue
> + * demand on this cpu persistently exceeds the configured bandwidth. Eje=
ct the
> + * sub with the highest recent rescue consumption instead of letting the
> + * scheduler stall path blame the waiter's owner, who may just be crowde=
d out.
> + */
> +static void scx_rescue_check_overload(struct rq *rq)
> +{
> +	struct scx_sched *victim =3D NULL, *pos;
> +	struct task_struct *p;
> +	int cpu =3D cpu_of(rq);
> +	u64 max_avg =3D 0;
> +	u32 dur_ms;
> +
> +	lockdep_assert_rq_held(rq);
> +
> +	p =3D list_first_entry_or_null(&rq->scx.rescue.dsq.list, struct task_st=
ruct,
> +				     scx.dsq_list.node);
> +	if (!p)
> +		return;
> +
> +	/* has the head waiter been queued for longer than the threshold? */
> +	if (time_before(jiffies, p->scx.rescue_at + scx_rescue_overload_after))
> +		return;
> +
> +	/*
> +	 * Grace period after the last ejection on this cpu - the freed
> +	 * bandwidth gets one threshold's worth of time to drain the backlog
> +	 * before another sub is judged.
> +	 */
> +	if (time_before(jiffies, rq->scx.rescue.kill_at + scx_rescue_overload_a=
fter))
> +		return;

[Severity: Medium]
Does this time_before() check have an issue with jiffies wraparound on 32-b=
it
systems?

If no rescue ejection occurs for LONG_MAX jiffies (about 24.8 days at HZ=3D=
1000
on 32-bit systems), jiffies - rq->scx.rescue.kill_at will exceed LONG_MAX.
Because the time_before() macro uses signed arithmetic, the difference wraps
around to a negative value.

This causes time_before() to incorrectly evaluate to true, falsely trapping
the CPU in a continuous grace period. Would this disable overload ejections
for the next 24.8 days and cause the scheduler to fall back to the generic
stall watchdog instead?

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260801085150.2697=
[email protected]?part=3D9