From: Crystal Wood <crwood@redhat.com>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: Tomas Glozar <tglozar@redhat.com>, John Kacur <jkacur@redhat.com>,
linux-trace-kernel@vger.kernel.org,
Crystal Wood <crwood@redhat.com>
Subject: [PATCH v6 06/10] tracing/osnoise: Split out per-cpu variable resets
Date: Wed, 28 Oct 2026 17:01:16 -0500 [thread overview]
Message-ID: <20261028220120.4005187-7-crwood@redhat.com> (raw)
In-Reply-To: <20261028220120.4005187-1-crwood@redhat.com>
Reset per-cpu state every time we stop a kthread or detach an fd, rather
than assume everything gets cleaned up properly, and avoiding the need
to explicitly zero individual fields.
Also, stop initializing tlat->thread lazily, add some debug checks to
detect an unclean state, and clear osnoise_data.tainted in
osn_var_reset().
The interrupt counters do not really need to be reset, and resetting them
on CPU detachment is racy because the hooks are still in place, so move
them out of the zero group.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
v2: New patch. Without this, I was seeing sampling = 1 leaking from a
kthread context to an fd context, which confused the latter into
operating with tlat->thread set to the old kernel thread, causing the fd
thread to hang.
v3: Reset the per-cpu context unconditionally in stop_kthread(), so sampling
gets cleared as noted in patch 3/9
v4: Only reset the cpu data if the fdd is a match
v6: Revive patch, but remove the interrupt counters from the zeroed area
---
kernel/trace/trace_osnoise.c | 121 +++++++++++++++++------------------
1 file changed, 60 insertions(+), 61 deletions(-)
diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c
index ce6d02346ea4..f07b62a5ccb8 100644
--- a/kernel/trace/trace_osnoise.c
+++ b/kernel/trace/trace_osnoise.c
@@ -236,15 +236,15 @@ struct osnoise_variables {
struct mutex lock; /* covers kthread and fdd changes */
struct task_struct *kthread;
struct fd_data *fdd;
+ struct osn_nmi nmi;
+ struct osn_irq irq;
+ struct osn_softirq softirq;
+ struct osn_thread thread;
+ local_t int_counter;
struct_group(zero,
bool sampling;
pid_t pid;
- struct osn_nmi nmi;
- struct osn_irq irq;
- struct osn_softirq softirq;
- struct osn_thread thread;
- local_t int_counter;
);
};
@@ -317,23 +317,19 @@ static inline struct timerlat_variables *cpu_tmr_var(int cpu)
return per_cpu_ptr(&per_cpu_timerlat_var, cpu);
}
+static inline void tlat_reset_cpu(int cpu)
+{
+ struct timerlat_variables *tlat = cpu_tmr_var(cpu);
+
+ WARN_ON_ONCE(tlat->thread);
+ memset(&tlat->zero, 0, sizeof(tlat->zero));
+}
+
/*
- * tlat_var_reset - Reset the values of the given timerlat_variables
+ * tlat_var_reset - Reset non-per-cpu state
*/
static inline void tlat_var_reset(void)
{
- struct timerlat_variables *tlat_var;
- int cpu;
-
- /*
- * So far, all the values are initialized as 0, so
- * zeroing the structure is perfect.
- */
- for_each_online_cpu(cpu) {
- tlat_var = cpu_tmr_var(cpu);
- WARN_ON_ONCE(tlat_var->thread);
- memset(&tlat_var->zero, 0, sizeof(tlat_var->zero));
- }
/*
* Reset also align_next, to be filled by a new offset by the first timerlat
* thread that wakes up, if TIMERLAT_ALIGN is set.
@@ -341,38 +337,12 @@ static inline void tlat_var_reset(void)
atomic64_set(&align_next, 0);
}
#else /* CONFIG_TIMERLAT_TRACER */
-#define tlat_var_reset() do {} while (0)
-#endif /* CONFIG_TIMERLAT_TRACER */
-
-/*
- * osn_var_reset - Reset the values of the given osnoise_variables
- */
-static inline void osn_var_reset(void)
+static inline void tlat_reset_cpu(int cpu)
{
- struct osnoise_variables *osn_var;
- int cpu;
-
- /*
- * So far, all the values are initialized as 0, so
- * zeroing the structure is perfect.
- */
- for_each_online_cpu(cpu) {
- osn_var = cpu_osn_var(cpu);
-
- WARN_ON(osn_var->kthread);
- WARN_ON(osn_var->fdd);
- memset(&osn_var->zero, 0, sizeof(osn_var->zero));
- }
}
-/*
- * osn_var_reset_all - Reset the value of all per-cpu osnoise_variables
- */
-static inline void osn_var_reset_all(void)
-{
- osn_var_reset();
- tlat_var_reset();
-}
+#define tlat_var_reset() do {} while (0)
+#endif /* CONFIG_TIMERLAT_TRACER */
/*
* Tells NMIs to call back to the osnoise tracer to record timestamps.
@@ -407,6 +377,36 @@ static struct osnoise_data {
#endif
};
+static inline void osn_reset_cpu(int cpu)
+{
+ struct osnoise_variables *osn = cpu_osn_var(cpu);
+
+ WARN_ON(osn->kthread);
+ WARN_ON(osn->fdd);
+ memset(&osn->zero, 0, sizeof(osn->zero));
+ tlat_reset_cpu(cpu);
+}
+
+/*
+ * osn_var_reset - Reset non-per-cpu state, and check for stale data
+ */
+static inline void osn_var_reset(void)
+{
+ struct osnoise_variables *osn;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ osn = cpu_osn_var(cpu);
+
+ WARN_ON(osn->kthread);
+ WARN_ON(osn->fdd);
+ WARN_ON(osn->sampling);
+ }
+
+ tlat_var_reset();
+ osnoise_data.tainted = false;
+}
+
#ifdef CONFIG_TIMERLAT_TRACER
static inline bool timerlat_enabled(void)
{
@@ -2023,7 +2023,7 @@ static void stop_kthread(unsigned int cpu)
osn_var->kthread = NULL;
}
- osn_var->sampling = false;
+ osn_reset_cpu(cpu);
mutex_unlock(&osn_var->lock);
}
@@ -2451,25 +2451,22 @@ static void timerlat_fd_detach(struct fd_data *fdd)
if (WARN_ON(fdd != osn->fdd))
return;
- WARN_ON(osn->kthread);
WARN_ON(fdd->thread != tlat->thread);
tlat->detach = true;
wake_up_process(tlat->thread);
mutex_lock(&tlat->detach_lock);
- osn->sampling = 0;
- osn->pid = 0;
-
WARN_ON_ONCE(hrtimer_active(&tlat->timer));
hrtimer_cancel(&tlat->timer);
put_task_struct(fdd->thread);
fdd->thread = NULL;
+ tlat->thread = NULL;
osn->fdd = NULL;
- memset(&tlat->zero, 0, sizeof(tlat->zero));
mutex_unlock(&tlat->detach_lock);
+
}
static int timerlat_fd_open(struct inode *inode, struct file *file)
@@ -2530,8 +2527,6 @@ static int timerlat_fd_open(struct inode *inode, struct file *file)
fdd->cpu = cpu;
file->private_data = fdd;
- tlat->tracing_thread = false;
- tlat->thread = current;
get_task_struct(current);
osn_var->pid = current->pid;
@@ -2544,7 +2539,11 @@ static int timerlat_fd_open(struct inode *inode, struct file *file)
mutex_unlock(&interface_lock);
tlat = this_cpu_tmr_var();
- tlat->count = 0;
+ WARN_ON(tlat->thread);
+ WARN_ON(tlat->count != 0);
+ WARN_ON(tlat->tracing_thread);
+ WARN_ON(osn_var->sampling);
+ tlat->thread = current;
hrtimer_setup(&tlat->timer, timerlat_irq, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD);
@@ -2698,13 +2697,13 @@ timerlat_fd_read(struct file *file, char __user *ubuf, size_t count,
static int timerlat_fd_release(struct inode *inode, struct file *file)
{
struct fd_data *fdd = file->private_data;
- struct osnoise_variables *osn_var;
-
- osn_var = cpu_osn_var(fdd->cpu);
+ struct osnoise_variables *osn_var = cpu_osn_var(fdd->cpu);
mutex_lock(&osn_var->lock);
- if (fdd == osn_var->fdd)
+ if (fdd == osn_var->fdd) {
timerlat_fd_detach(fdd);
+ osn_reset_cpu(fdd->cpu);
+ }
mutex_unlock(&osn_var->lock);
kfree(fdd);
@@ -3018,7 +3017,7 @@ static int osnoise_workload_start(void)
if (osnoise_has_registered_instances())
return 0;
- osn_var_reset_all();
+ osn_var_reset();
retval = osnoise_hook_events();
if (retval)
--
2.54.0
next prev parent reply other threads:[~2026-10-28 22:01 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-28 22:01 [PATCH v6 0/10] tracing/osnoise: Synchronization fixes Crystal Wood
2026-10-28 22:01 ` [PATCH v6 01/10] tracing/osnoise: Variable cleanup Crystal Wood
2026-10-28 22:01 ` [PATCH v6 02/10] tracing/osnoise: start_kthread: Always check OSN_WORKLOAD Crystal Wood
2026-10-28 22:06 ` sashiko-bot
2026-10-28 22:01 ` [PATCH v6 03/10] tracing/osnoise: Start all eligible cpus from hotplug workfn Crystal Wood
2026-10-28 22:01 ` [PATCH v6 04/10] tracing/osnoise: Hold a ref on osn->kthread Crystal Wood
2026-10-28 22:01 ` [PATCH v6 05/10] tracing/osnoise: Per-cpu mutexes and fd detachment Crystal Wood
2026-10-28 22:20 ` sashiko-bot
2026-10-28 22:01 ` Crystal Wood [this message]
2026-10-28 22:24 ` [PATCH v6 06/10] tracing/osnoise: Split out per-cpu variable resets sashiko-bot
2026-10-28 22:01 ` [PATCH v6 07/10] tracing/osnoise: kthreads: Verify CPU after migrate_disable() Crystal Wood
2026-10-28 22:01 ` [PATCH v6 08/10] tracing/osnoise: Take trace_types_lock in timerlat_fd_open Crystal Wood
2026-10-28 22:01 ` [PATCH v6 09/10] tracing/osnoise: Print taint message for timerlat Crystal Wood
2026-10-28 22:01 ` [PATCH v6 10/10] tracing/osnoise: Refuse timerlat fd open if tracer inactive Crystal Wood
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261028220120.4005187-7-crwood@redhat.com \
--to=crwood@redhat.com \
--cc=jkacur@redhat.com \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=tglozar@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox