Re: [PATCH] sched/eevdf: Fix vprot across reweighting

From: Kayra Cizmeci

Date: Mon Oct 12 2026 - 15:03:26 EST


> I send one mail, one more to reply comes. Ah.. I love it tho :-)

> > Before 819224e506bc ("sched/fair: Remove dead code on
> > enqueue_task_fair()"), the reweight_eevdf() was not called for curr so
> > the false was always true. If we can finally have enqueue curr then we
> > should skip this case

> Yeah. The beast I created kills me. Pretty nice.

> On sched_change_begin(), cfs_rq->curr is set to NULL. So while entering enqueue_task_fair(), curr is false.
> on_rq is false too. But the tasks weight is changed and vprot never gets touched so it got wrong. Then on set_next_task_fair(),
> the task is curr again.

Would something like this works?

This diff was coded in the middle of the night, so there might be some little issues about it.
Not even 1% tested. But it should 100% work since I'm too smart, right? Right? :-)

(Also, I'll test it tomorrow. Normally I was going to test this, but I lost my test script. And tbh
I'm too tired to make it right now. I mean normally I wouldn't test it, since I'm too smart and this
is 100% correct. And because of this 'dead' code removal patch, there could be some extra handy issues.
Ah... I wanna swear so bad. But, I'll be a good and kind. Goodnight, good morning, good afternoon and good-whatever.)


diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index b42a0ca2a69e..1bea7b7e9cb3 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4731,7 +4731,7 @@ static void reweight_eevdf(struct cfs_rq *cfs_rq, struct sched_entity *se,
se->vlag = entity_lag(cfs_rq, se, avruntime);
se->deadline -= avruntime;
se->rel_deadline = 1;
- if (curr && protect_slice(se)) {
+ if (curr) {
se->vprot -= avruntime;
rel_vprot = true;
}
@@ -7990,7 +7990,9 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
int task_new = !(flags & ENQUEUE_WAKEUP);
struct sched_entity *se = &p->se;
struct cfs_rq *cfs_rq = &rq->cfs;
- unsigned long weight;
+ unsigned long weight, old_weight;
+ bool live;
+ u64 dist;

if (task_is_throttled(p) && enqueue_throttled_task(p))
return;
@@ -8024,8 +8026,23 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
requeue_delayed_entity(cfs_rq, se);

weight = enqueue_hierarchy(p, flags);
+ live = protect_slice(se);
+
+ if (live) {
+ old_weight = se->h_load.weight;
+ dist = se->vprot - se->vruntime;
+ }
reweight_eevdf(cfs_rq, se, weight, false);
place_entity(cfs_rq, se, flags | ENQUEUE_QUEUED);
+ if (!live)
+ cancel_protect_slice(se);
+ else {
+ if (weight != old_weight)
+ dist = div64_long(dist * old_weight, weight);
+
+ se->vprot = se->vruntime + dist;
+ }
+
__enqueue_entity(cfs_rq, se);

if (!rq_h_nr_queued && rq->cfs.h_nr_queued)