scx_dump_state() walks CPUs with rq_lock_irqsave() held and invokes ops.dump_cpu / ops.dump_task with NULL locked_rq, leaving scx_locked_rq_state NULL. If the BPF callback calls a kfunc that re-acquires rq based on scx_locked_rq() - e.g. scx_bpf_cpuperf_set(cpu) - it re-acquires the already-held rq. Pass the held rq to SCX_CALL_OP(). Thread it into scx_dump_task() too. The pre-loop ops.dump call runs before rq_lock_irqsave() so keeps rq=NULL.
Unified · Split
| @@ -6117,9 +6117,8 @@ static void ops_dump_exit(void) · 6116 unmodified lines | ||
| 6117 | 6117 | scx_dump_data.cpu = -1; |
| 6118 | 6118 | } |
| 6119 | 6119 | |
| 6120 | −static void scx_dump_task(struct scx_sched *sch, | |
| 6121 | − struct seq_buf *s, struct scx_dump_ctx *dctx, | |
| 6122 | − struct task_struct *p, char marker) | |
| 6120 | +static void scx_dump_task(struct scx_sched *sch, struct seq_buf *s, struct scx_dump_ctx *dctx, | |
| 6121 | + struct rq *rq, struct task_struct *p, char marker) | |
| 6123 | 6122 | { |
| 6124 | 6123 | static unsigned long bt[SCX_EXIT_BT_LEN]; |
| 6125 | 6124 | struct scx_sched *task_sch = scx_task_sched(p); |
| @@ -6160,7 +6159,7 @@ static void scx_dump_task(struct scx_sched *sch, · 34 unmodified lines | ||
| 6160 | 6159 | |
| 6161 | 6160 | if (SCX_HAS_OP(sch, dump_task)) { |
| 6162 | 6161 | ops_dump_init(s, " "); |
| 6163 | − SCX_CALL_OP(sch, dump_task, NULL, dctx, p); | |
| 6162 | + SCX_CALL_OP(sch, dump_task, rq, dctx, p); | |
| 6164 | 6163 | ops_dump_exit(); |
| 6165 | 6164 | } |
| 6166 | 6165 | |
| @@ -6284,8 +6283,7 @@ static void scx_dump_state(struct scx_sched *sch, struct scx_exit_info *ei, · 117 unmodified lines | ||
| 6284 | 6283 | used = seq_buf_used(&ns); |
| 6285 | 6284 | if (SCX_HAS_OP(sch, dump_cpu)) { |
| 6286 | 6285 | ops_dump_init(&ns, " "); |
| 6287 | − SCX_CALL_OP(sch, dump_cpu, NULL, | |
| 6288 | − &dctx, cpu, idle); | |
| 6286 | + SCX_CALL_OP(sch, dump_cpu, rq, &dctx, cpu, idle); | |
| 6289 | 6287 | ops_dump_exit(); |
| 6290 | 6288 | } |
| 6291 | 6289 | |
| @@ -6308,11 +6306,11 @@ static void scx_dump_state(struct scx_sched *sch, struct scx_exit_info *ei, · 16 unmodified lines | ||
| 6308 | 6306 | |
| 6309 | 6307 | if (rq->curr->sched_class == &ext_sched_class && |
| 6310 | 6308 | (dump_all_tasks || scx_task_on_sched(sch, rq->curr))) |
| 6311 | − scx_dump_task(sch, &s, &dctx, rq->curr, '*'); | |
| 6309 | + scx_dump_task(sch, &s, &dctx, rq, rq->curr, '*'); | |
| 6312 | 6310 | |
| 6313 | 6311 | list_for_each_entry(p, &rq->scx.runnable_list, scx.runnable_node) |
| 6314 | 6312 | if (dump_all_tasks || scx_task_on_sched(sch, p)) |
| 6315 | − scx_dump_task(sch, &s, &dctx, p, ' '); | |
| 6313 | + scx_dump_task(sch, &s, &dctx, rq, p, ' '); | |
| 6316 | 6314 | next: |
| 6317 | 6315 | rq_unlock_irqrestore(rq, &rf); |
| 6318 | 6316 | } |