]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Merge branch 'for-7.1-fixes' into for-7.2
authorTejun Heo <tj@kernel.org>
Tue, 21 Apr 2026 16:30:11 +0000 (06:30 -1000)
committerTejun Heo <tj@kernel.org>
Tue, 21 Apr 2026 16:35:42 +0000 (06:35 -1000)
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 <tj@kernel.org>
1  2 
tools/sched_ext/scx_qmap.bpf.c

index a73a2dcbaeb73904f28ea3e6d120eb88ee0f0486,aad698fe294bf4136058f9eda18693f1736de220..ba4879031dac88cd1380e9d92c67544c52eaf47e
@@@ -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;