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

    commit 0878355b51f5f26632e652c848a8e174bb02d22d upstream.

    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    kernel/trace/trace_osnoise.c | 20 ++++++++++++++++----
    1 file changed, 16 insertions(+), 4 deletions(-)

    --- a/kernel/trace/trace_osnoise.c
    +++ b/kernel/trace/trace_osnoise.c
    @@ -2123,6 +2123,13 @@ out_unhook_irq:
    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
    */
    @@ -2155,7 +2162,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;
    }

    @@ -2186,9 +2200,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)

    \
     
     \ /
      Last update: 2022-01-25 04:09    [W:2.097 / U:1.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site