Re: [PATCH v2] sched: fair: Prevent negative lag increase during delayed dequeue

From: Vincent Guittot

Date: Thu Apr 23 2026 - 03:28:56 EST


On Thu, 23 Apr 2026 at 00:20, Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
> On Wed, Apr 22, 2026 at 04:28:28PM +0200, Peter Zijlstra wrote:
>
> > Let me ponder this a bit...
>
> Like this? Or am I still making a mess of things? AFAICT this is the
> exact same as your initial version.
>
> ---
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index 69361c63353a..24e8c78b110a 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -847,13 +847,13 @@ static s64 entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 avrunt
> * Similarly, check that the entity didn't gain positive lag when DELAY_ZERO
> * is set.
> *
> - * Return true if the lag has been adjusted.
> + * Return true if the lag of a delayed entity has been adjusted.
> */
> static __always_inline
> bool update_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se)
> {
> s64 vlag = entity_lag(cfs_rq, se, avg_vruntime(cfs_rq));
> - bool ret;
> + bool ret = false;
>
> WARN_ON_ONCE(!se->on_rq);
>
> @@ -862,8 +862,9 @@ bool update_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se)
> vlag = max(vlag, se->vlag);
> if (sched_feat(DELAY_ZERO))
> vlag = min(vlag, 0);
> +
> + ret = (vlag != se->vlag);

No this is not enough.

As an example:
se->vlag = -2 when the entity is delayed dequeued
When the entity is requeued:
update_entity_lag()
vlag = entity_lag() == -3, i.e. its negative lag has increased.
We cap it to the value saved at delayed dequeue (-2) with vlag
= max(vlag, se->vlag);
vlag == se->vlag but we need to place the entity with the new vlag
se->vlag = vlag

We want to check if the new value that we will set to se->vlag in
update_entity_lag() will be different from the returned value of
entity_lag(). entity_lag() reflects the current lag of the entity. If
the value sets in se->vlag is different than entity_lag() and we want
to keep the entity enqueued then we need to place it with the new
vlag.

And the opposite example
se->vlag = -2 when the entity is delayed dequeued
When the entity is requeued:
update_entity_lag()
vlag = entity_lag() == +1
We cap it at 0 with vlag = min(vlag, 0);
vlag != se->vlag which is okay as we need to place the entity
with the new vlag
se->vlag = vlag

and the last use case

se->vlag = -2 when the entity is delayed dequeued
When the entity is requeued:
update_entity_lag()
vlag = entity_lag() == -1
We don't modifiy vlag
vlag != se->vlag but we don't need to place_the entity which
is already correctly placed
se->vlag = vlag


> }
> - ret = (vlag == se->vlag);
> se->vlag = vlag;
>
> return ret;