From: Tejun Heo Date: Tue, 21 Apr 2026 16:30:11 +0000 (-1000) Subject: Merge branch 'for-7.1-fixes' into for-7.2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9af5d67065c31ae9d3ba5723e252baed532c73a4;p=thirdparty%2Fkernel%2Flinux.git Merge branch 'for-7.1-fixes' into for-7.2 Pull to receive: 05909810a946 ("tools/sched_ext: scx_qmap: Silence task_ctx lookup miss") which conflicts with the cid-form qmap rework on for-7.2. Resolved by applying the same silence-on-NULL semantics to the arena-backed lookup_task_ctx() and qmap_select_cpu() on for-7.2. Signed-off-by: Tejun Heo --- 9af5d67065c31ae9d3ba5723e252baed532c73a4 diff --cc tools/sched_ext/scx_qmap.bpf.c index a73a2dcbaeb73,aad698fe294bf..ba4879031dac8 --- a/tools/sched_ext/scx_qmap.bpf.c +++ b/tools/sched_ext/scx_qmap.bpf.c @@@ -178,112 -157,19 +178,110 @@@ static s32 pick_direct_dispatch_cpu(str return -1; } -static struct task_ctx *lookup_task_ctx(struct task_struct *p) +/* + * Force a reference to the arena map. The verifier associates an arena with + * a program by finding an LD_IMM64 instruction that loads the arena's BPF + * map; programs that only use arena pointers returned from task-local + * storage (like qmap_select_cpu) never reference @arena directly. Without + * this, the verifier rejects addr_space_cast with "addr_space_cast insn + * can only be used in a program that has an associated arena". + */ +#define QMAP_TOUCH_ARENA() do { asm volatile("" :: "r"(&arena)); } while (0) + +static task_ctx_t *lookup_task_ctx(struct task_struct *p) +{ + struct task_ctx_stor_val *v; + + QMAP_TOUCH_ARENA(); + + v = bpf_task_storage_get(&task_ctx_stor, p, 0, 0); - if (!v || !v->taskc) { - scx_bpf_error("task_ctx lookup failed"); ++ if (!v || !v->taskc) + return NULL; - } + return v->taskc; +} + +/* Append @taskc to the tail of @fifo. Must not already be queued. */ +static void qmap_fifo_enqueue(struct qmap_fifo __arena *fifo, task_ctx_t *taskc) +{ + struct bpf_res_spin_lock *lock = qa_q_lock(fifo->idx); + + if (!lock || qmap_spin_lock(lock)) + return; + taskc->fifo = fifo; + taskc->q_next = NULL; + taskc->q_prev = fifo->tail; + if (fifo->tail) + fifo->tail->q_next = taskc; + else + fifo->head = taskc; + fifo->tail = taskc; + bpf_res_spin_unlock(lock); +} + +/* Pop the head of @fifo. Returns NULL if empty. */ +static task_ctx_t *qmap_fifo_pop(struct qmap_fifo __arena *fifo) { - return bpf_task_storage_get(&task_ctx_stor, p, 0, 0); + struct bpf_res_spin_lock *lock = qa_q_lock(fifo->idx); + task_ctx_t *taskc; + + if (!lock || qmap_spin_lock(lock)) + return NULL; + taskc = fifo->head; + if (taskc) { + fifo->head = taskc->q_next; + if (taskc->q_next) + taskc->q_next->q_prev = NULL; + else + fifo->tail = NULL; + taskc->q_next = NULL; + taskc->q_prev = NULL; + taskc->fifo = NULL; + } + bpf_res_spin_unlock(lock); + return taskc; +} + +/* Remove @taskc from its fifo. No-op if not queued. */ +static void qmap_fifo_remove(task_ctx_t *taskc) +{ + struct qmap_fifo __arena *fifo = taskc->fifo; + struct bpf_res_spin_lock *lock; + + if (!fifo) + return; + + lock = qa_q_lock(fifo->idx); + if (!lock || qmap_spin_lock(lock)) + return; + + /* Re-check under lock — a concurrent pop may have cleared fifo. */ + if (taskc->fifo != fifo) { + bpf_res_spin_unlock(lock); + return; + } + + if (taskc->q_next) + taskc->q_next->q_prev = taskc->q_prev; + else + fifo->tail = taskc->q_prev; + if (taskc->q_prev) + taskc->q_prev->q_next = taskc->q_next; + else + fifo->head = taskc->q_next; + taskc->q_next = NULL; + taskc->q_prev = NULL; + taskc->fifo = NULL; + bpf_res_spin_unlock(lock); } s32 BPF_STRUCT_OPS(qmap_select_cpu, struct task_struct *p, s32 prev_cpu, u64 wake_flags) { - struct task_ctx *tctx; + task_ctx_t *taskc; s32 cpu; - if (!(tctx = lookup_task_ctx(p))) + if (!(taskc = lookup_task_ctx(p))) - return -ESRCH; + return prev_cpu; if (p->scx.weight < 2 && !(p->flags & PF_KTHREAD)) return prev_cpu;