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.
Showing the changes to kernel (1 of 1 file). Show all
Unified · Split
| @@ -6117,9 +6117,8 @@ static void ops_dump_exit(void) · 6116 unmodified lines | |||
| 6117 | scx_dump_data.cpu = -1; | 6117 | scx_dump_data.cpu = -1; |
| 6118 | } | 6118 | } |
| 6119 | 6119 | ||
| 6120 | static void scx_dump_task(struct scx_sched *sch, | 6120 | static void scx_dump_task(struct scx_sched *sch, struct seq_buf *s, struct scx_dump_ctx *dctx, |
| 6121 | struct seq_buf *s, struct scx_dump_ctx *dctx, | 6121 | struct rq *rq, struct task_struct *p, char marker) |
| 6122 | struct task_struct *p, char marker) | ||
| 6123 | { | 6122 | { |
| 6124 | static unsigned long bt[SCX_EXIT_BT_LEN]; | 6123 | static unsigned long bt[SCX_EXIT_BT_LEN]; |
| 6125 | struct scx_sched *task_sch = scx_task_sched(p); | 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 | if (SCX_HAS_OP(sch, dump_task)) { | 6160 | if (SCX_HAS_OP(sch, dump_task)) { |
| 6162 | ops_dump_init(s, " "); | 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 | ops_dump_exit(); | 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 | used = seq_buf_used(&ns); | 6283 | used = seq_buf_used(&ns); |
| 6285 | if (SCX_HAS_OP(sch, dump_cpu)) { | 6284 | if (SCX_HAS_OP(sch, dump_cpu)) { |
| 6286 | ops_dump_init(&ns, " "); | 6285 | ops_dump_init(&ns, " "); |
| 6287 | SCX_CALL_OP(sch, dump_cpu, NULL, | 6286 | SCX_CALL_OP(sch, dump_cpu, rq, &dctx, cpu, idle); |
| 6288 | &dctx, cpu, idle); | ||
| 6289 | ops_dump_exit(); | 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 | if (rq->curr->sched_class == &ext_sched_class && | 6307 | if (rq->curr->sched_class == &ext_sched_class && |
| 6310 | (dump_all_tasks || scx_task_on_sched(sch, rq->curr))) | 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 | list_for_each_entry(p, &rq->scx.runnable_list, scx.runnable_node) | 6311 | list_for_each_entry(p, &rq->scx.runnable_list, scx.runnable_node) |
| 6314 | if (dump_all_tasks || scx_task_on_sched(sch, p)) | 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 | next: | 6314 | next: |
| 6317 | rq_unlock_irqrestore(rq, &rf); | 6315 | rq_unlock_irqrestore(rq, &rf); |
| 6318 | } | 6316 | } |