From: Andrea Righi Date: Sat, 7 Mar 2026 09:56:31 +0000 (+0100) Subject: sched_ext: Pass full dequeue flags to ops.quiescent() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03f5304aad0f90907475437be8052e7e70376319;p=thirdparty%2Fkernel%2Flinux.git sched_ext: Pass full dequeue flags to ops.quiescent() ops.quiescent() is invoked with the same deq_flags as ops.dequeue(), so the BPF scheduler is able to distinguish sleep vs property changes in both callbacks. However, dequeue_task_scx() receives deq_flags as an int from the sched_class interface, so SCX flags above bit 32 (%SCX_DEQ_SCHED_CHANGE) are truncated. ops_dequeue() reconstructs the full u64 for ops.dequeue(), but ops.quiescent() is still called with the original int and can never see %SCX_DEQ_SCHED_CHANGE. Fix this by constructing the full u64 deq_flags in dequeue_task_scx() (renaming the int parameter to core_deq_flags) and passing the complete flags to both ops_dequeue() and ops.quiescent(). Fixes: ebf1ccff79c4 ("sched_ext: Fix ops.dequeue() semantics") Signed-off-by: Andrea Righi Signed-off-by: Tejun Heo --- diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c index 72b7a87f66ec9..47f65041b363d 100644 --- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c @@ -1782,14 +1782,6 @@ static void ops_dequeue(struct rq *rq, struct task_struct *p, u64 deq_flags) { struct scx_sched *sch = scx_task_sched(p); unsigned long opss; - u64 op_deq_flags = deq_flags; - - /* - * Set %SCX_DEQ_SCHED_CHANGE when the dequeue is due to a property - * change (not sleep or core-sched pick). - */ - if (!(op_deq_flags & (DEQUEUE_SLEEP | SCX_DEQ_CORE_SCHED_EXEC))) - op_deq_flags |= SCX_DEQ_SCHED_CHANGE; /* dequeue is always temporary, don't reset runnable_at */ clr_task_runnable(p, false); @@ -1846,12 +1838,20 @@ static void ops_dequeue(struct rq *rq, struct task_struct *p, u64 deq_flags) * NONE but the task may still have %SCX_TASK_IN_CUSTODY set until * it is enqueued on the destination. */ - call_task_dequeue(sch, rq, p, op_deq_flags); + call_task_dequeue(sch, rq, p, deq_flags); } -static bool dequeue_task_scx(struct rq *rq, struct task_struct *p, int deq_flags) +static bool dequeue_task_scx(struct rq *rq, struct task_struct *p, int core_deq_flags) { struct scx_sched *sch = scx_task_sched(p); + u64 deq_flags = core_deq_flags; + + /* + * Set %SCX_DEQ_SCHED_CHANGE when the dequeue is due to a property + * change (not sleep or core-sched pick). + */ + if (!(deq_flags & (DEQUEUE_SLEEP | SCX_DEQ_CORE_SCHED_EXEC))) + deq_flags |= SCX_DEQ_SCHED_CHANGE; if (!(p->scx.flags & SCX_TASK_QUEUED)) { WARN_ON_ONCE(task_runnable(p));