[PATCH 2/2] rv/nomiss: close enable-time task exit race
From: Li Qiang <hidden>
Date: 2026-07-15 06:00:53
Also in:
lkml
Subsystem:
runtime verification (rv), the rest, tracing · Maintainers:
Steven Rostedt, Gabriele Monaco, Linus Torvalds, Masami Hiramatsu
The initial task scan runs before the first patch registers the task exit
tracepoint. A task can begin exiting after it was selected by the scan but
before the exit handler is attached. sched_process_exit runs before
exit_notify() removes the task from the task list, so the scan could then
store a pointer to the exiting task's deadline entity after its cleanup
event had already been missed.
Initialize the shard state and attach the new-task, exit, and syscall
tracepoints before the initial scan. Make the scan use the same
PF_EXITING-aware creation helper as dynamic policy changes. On failure,
detach those tracepoints before destroying the monitor storage.
Fixes: b133207deb72 ("rv: Add nomiss deadline monitor")
Signed-off-by: Li Qiang <redacted>
---
kernel/trace/rv/monitors/deadline/deadline.h | 27 ++++++++++-------
kernel/trace/rv/monitors/nomiss/nomiss.c | 18 +++++++----
2 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/kernel/trace/rv/monitors/deadline/deadline.h b/kernel/trace/rv/monitors/deadline/deadline.h
index b92480e79807..4626d6e2b218 100644
--- a/kernel/trace/rv/monitors/deadline/deadline.h
+++ b/kernel/trace/rv/monitors/deadline/deadline.h@@ -181,6 +181,8 @@ static void deadline_storage_init(void) } } +static int deadline_create_task_storage(struct task_struct *task); + /* * Initialise monitors for all tasks and pre-allocate the storage for servers. * This is necessary since we don't have access to the servers here and
@@ -190,9 +192,7 @@ static void deadline_storage_init(void) static inline int init_storage(bool skip_tasks) { struct task_struct *g, *p; - int cpu; - - deadline_storage_init(); + int cpu, ret; for_each_possible_cpu(cpu) { if (!da_create_empty_storage(fair_server_id(cpu)))
@@ -208,25 +208,25 @@ static inline int init_storage(bool skip_tasks) read_lock(&tasklist_lock); for_each_process_thread(g, p) { if (p->policy == SCHED_DEADLINE) { - if (!da_create_storage(EXPAND_ID_TASK(p), NULL)) { + ret = deadline_create_task_storage(p); + if (ret && ret != -ESRCH) { read_unlock(&tasklist_lock); - goto fail; + return ret; } - atomic_inc(&deadline_storage_shard(p->pid)->users); } } read_unlock(&tasklist_lock); return 0; fail: - da_monitor_destroy(); return -ENOMEM; } -static void deadline_create_task_storage(struct task_struct *task) +static int deadline_create_task_storage(struct task_struct *task) { struct deadline_storage_shard *shard = deadline_storage_shard(task->pid); bool created = false; + int ret = -ESRCH; /* * The temporary reference makes an in-flight creator visible to exit.
@@ -239,14 +239,21 @@ static void deadline_create_task_storage(struct task_struct *task) raw_spin_lock(&shard->lock); if (!(READ_ONCE(task->flags) & PF_EXITING)) { guard(rcu)(); - if (!da_get_monitor(EXPAND_ID_TASK(task)) && - da_create_storage(EXPAND_ID_TASK(task), NULL)) + if (da_get_monitor(EXPAND_ID_TASK(task))) { + ret = 0; + } else if (da_create_storage(EXPAND_ID_TASK(task), NULL)) { created = true; + ret = 0; + } else { + ret = -ENOMEM; + } } raw_spin_unlock(&shard->lock); if (!created) atomic_dec(&shard->users); + + return ret; } static void deadline_destroy_task_storage(struct task_struct *task)
diff --git a/kernel/trace/rv/monitors/nomiss/nomiss.c b/kernel/trace/rv/monitors/nomiss/nomiss.c
index 2e5ee681505b..843262779a41 100644
--- a/kernel/trace/rv/monitors/nomiss/nomiss.c
+++ b/kernel/trace/rv/monitors/nomiss/nomiss.c@@ -231,18 +231,26 @@ static int enable_nomiss(void) if (retval) return retval; + deadline_storage_init(); + rv_attach_trace_probe("nomiss", task_newtask, handle_newtask); + rv_attach_trace_probe("nomiss", sched_process_exit, handle_exit); + if (!should_skip_syscall_handle()) + rv_attach_trace_probe("nomiss", sys_enter, handle_sys_enter); + retval = init_storage(false); - if (retval) + if (retval) { + rv_detach_trace_probe("nomiss", task_newtask, handle_newtask); + rv_detach_trace_probe("nomiss", sched_process_exit, handle_exit); + if (!should_skip_syscall_handle()) + rv_detach_trace_probe("nomiss", sys_enter, handle_sys_enter); + ha_monitor_destroy(); return retval; + } rv_attach_trace_probe("nomiss", sched_dl_replenish_tp, handle_dl_replenish); rv_attach_trace_probe("nomiss", sched_dl_throttle_tp, handle_dl_throttle); rv_attach_trace_probe("nomiss", sched_dl_server_stop_tp, handle_dl_server_stop); rv_attach_trace_probe("nomiss", sched_switch, handle_sched_switch); rv_attach_trace_probe("nomiss", sched_wakeup, handle_sched_wakeup); - if (!should_skip_syscall_handle()) - rv_attach_trace_probe("nomiss", sys_enter, handle_sys_enter); - rv_attach_trace_probe("nomiss", task_newtask, handle_newtask); - rv_attach_trace_probe("nomiss", sched_process_exit, handle_exit); return 0; }
--
2.50.1