lkml.org 
[lkml]   [2022]   [Jan]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[for-next][PATCH 31/31] tracing/osnoise: Properly unhook events if start_per_cpu_kthreads() fails
    From: Nikita Yushchenko <nikita.yushchenko@virtuozzo.com>

    If start_per_cpu_kthreads() called from osnoise_workload_start() returns
    error, event hooks are left in broken state: unhook_irq_events() called
    but unhook_thread_events() and unhook_softirq_events() not called, and
    trace_osnoise_callback_enabled flag not cleared.

    On the next tracer enable, hooks get not installed due to
    trace_osnoise_callback_enabled flag.

    And on the further tracer disable an attempt to remove non-installed
    hooks happened, hitting a WARN_ON_ONCE() in tracepoint_remove_func().

    Fix the error path by adding the missing part of cleanup.
    While at this, introduce osnoise_unhook_events() to avoid code
    duplication between this error path and normal tracer disable.

    Link: https://lkml.kernel.org/r/20220109153459.3701773-1-nikita.yushchenko@virtuozzo.com

    Cc: stable@vger.kernel.org
    Fixes: bce29ac9ce0b ("trace: Add osnoise tracer")
    Acked-by: Daniel Bristot de Oliveira <bristot@kernel.org>
    Signed-off-by: Nikita Yushchenko <nikita.yushchenko@virtuozzo.com>
    Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
    ---
    kernel/trace/trace_osnoise.c | 20 ++++++++++++++++----
    1 file changed, 16 insertions(+), 4 deletions(-)

    diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c
    index 4719a848bf17..36d9d5be08b4 100644
    --- a/kernel/trace/trace_osnoise.c
    +++ b/kernel/trace/trace_osnoise.c
    @@ -2122,6 +2122,13 @@ static int osnoise_hook_events(void)
    return -EINVAL;
    }

    +static void osnoise_unhook_events(void)
    +{
    + unhook_thread_events();
    + unhook_softirq_events();
    + unhook_irq_events();
    +}
    +
    /*
    * osnoise_workload_start - start the workload and hook to events
    */
    @@ -2154,7 +2161,14 @@ static int osnoise_workload_start(void)

    retval = start_per_cpu_kthreads();
    if (retval) {
    - unhook_irq_events();
    + trace_osnoise_callback_enabled = false;
    + /*
    + * Make sure that ftrace_nmi_enter/exit() see
    + * trace_osnoise_callback_enabled as false before continuing.
    + */
    + barrier();
    +
    + osnoise_unhook_events();
    return retval;
    }

    @@ -2185,9 +2199,7 @@ static void osnoise_workload_stop(void)

    stop_per_cpu_kthreads();

    - unhook_irq_events();
    - unhook_softirq_events();
    - unhook_thread_events();
    + osnoise_unhook_events();
    }

    static void osnoise_tracer_start(struct trace_array *tr)
    --
    2.33.0
    \
     
     \ /
      Last update: 2022-01-11 18:33    [W:2.568 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site