Pass osn vars as the kthread arg, and make sure it matches where ve're
runnning in case of (e.g.) hotplug issues.

Signed-off-by: Crystal Wood <[email protected]>
---
v2:
 - Do it for osnoise too, not just timerlat
 - I haven't been able to reproduce this in a while, and I'm not seeing the
   hole in the hotplug sync that would allow it, but I also don't see what
   would have allowed it in v1 (maybe it was in some pre-v1 iteration? or
   maybe just a tiny race window).

   So we can maybe drop this patch, though it still feels better to explicitly
   splat if problems happen rather than rely on this_cpu_osn_var() blowing up
   due to the affinity being set to multiple cpus.
---
 kernel/trace/trace_osnoise.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c
index 17cd5ea61e41..51e9b8837d20 100644
--- a/kernel/trace/trace_osnoise.c
+++ b/kernel/trace/trace_osnoise.c
@@ -236,6 +236,7 @@ struct osnoise_variables {
        struct mutex            lock; /* covers kthread and fdd changes */
        struct task_struct      *kthread;
        struct fd_data          *fdd;
+       int                     cpu;
 
        struct_group(zero,
                bool                    sampling;
@@ -1724,6 +1725,7 @@ static inline int osnoise_migration_pending(void)
  */
 static int osnoise_main(void *data)
 {
+       struct osnoise_variables *osn = data;
        unsigned long flags;
 
        /*
@@ -1734,6 +1736,11 @@ static int osnoise_main(void *data)
         * flag.
         */
        migrate_disable();
+       if (WARN_ON_ONCE(osn->cpu != smp_processor_id())) {
+               migrate_enable();
+               return 1;
+       }
+
        raw_spin_lock_irqsave(&current->pi_lock, flags);
        current->flags &= ~(PF_NO_SETAFFINITY);
        raw_spin_unlock_irqrestore(&current->pi_lock, flags);
@@ -1924,8 +1931,8 @@ static int wait_next_period(struct timerlat_variables 
*tlat)
  */
 static int timerlat_main(void *data)
 {
-       struct osnoise_variables *osn_var = this_cpu_osn_var();
-       struct timerlat_variables *tlat = this_cpu_tmr_var();
+       struct osnoise_variables *osn_var = data;
+       struct timerlat_variables *tlat;
        struct timerlat_sample s;
        struct sched_param sp;
        unsigned long flags;
@@ -1945,6 +1952,13 @@ static int timerlat_main(void *data)
         * flag.
         */
        migrate_disable();
+       if (WARN_ON_ONCE(osn_var->cpu != smp_processor_id())) {
+               migrate_enable();
+               return 1;
+       }
+
+       tlat = this_cpu_tmr_var();
+
        raw_spin_lock_irqsave(&current->pi_lock, flags);
        current->flags &= ~(PF_NO_SETAFFINITY);
        raw_spin_unlock_irqrestore(&current->pi_lock, flags);
@@ -2076,7 +2090,7 @@ static int start_kthread(unsigned int cpu)
                snprintf(comm, 24, "osnoise/%d", cpu);
        }
 
-       kthread = kthread_create_on_cpu(main, NULL, cpu, comm);
+       kthread = kthread_create_on_cpu(main, cpu_osn_var(cpu), cpu, comm);
 
        if (IS_ERR(kthread)) {
                pr_err(BANNER "could not start sampling thread\n");
@@ -3253,6 +3267,7 @@ __init static int init_osnoise_tracer(void)
                struct osnoise_variables *osn = cpu_osn_var(cpu);
 
                mutex_init(&osn->lock);
+               osn->cpu = cpu;
        }
 
        cpumask_copy(&osnoise_cpumask, cpu_all_mask);
-- 
2.54.0


Reply via email to