• Steven Rostedt (VMware)'s avatar
    ring-buffer: Bring back context level recursive checks · a0e3a18f
    Steven Rostedt (VMware) authored
    Commit 1a149d7d ("ring-buffer: Rewrite trace_recursive_(un)lock() to be
    simpler") replaced the context level recursion checks with a simple counter.
    This would prevent the ring buffer code from recursively calling itself more
    than the max number of contexts that exist (Normal, softirq, irq, nmi). But
    this change caused a lockup in a specific case, which was during suspend and
    resume using a global clock. Adding a stack dump to see where this occurred,
    the issue was in the trace global clock itself:
    
      trace_buffer_lock_reserve+0x1c/0x50
      __trace_graph_entry+0x2d/0x90
      trace_graph_entry+0xe8/0x200
      prepare_ftrace_return+0x69/0xc0
      ftrace_graph_caller+0x78/0xa8
      queued_spin_lock_slowpath+0x5/0x1d0
      trace_clock_global+0xb0/0xc0
      ring_buffer_lock_reserve+0xf9/0x390
    
    The function graph tracer traced queued_spin_lock_slowpath that was called
    by trace_clock_global. This pointed out that the trace_clock_global() is not
    reentrant, as it takes a spin lock. It depended on the ring buffer recursive
    lock from letting that happen.
    
    By removing the context detection and adding just a max number of allowable
    recursions, it allowed the trace_clock_global() to be entered again and try
    to retake the spinlock it already held, causing a deadlock.
    
    Fixes: 1a149d7d ("ring-buffer: Rewrite trace_recursive_(un)lock() to be simpler")
    Reported-by: default avatarDavid Weinehall <david.weinehall@gmail.com>
    Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
    a0e3a18f
ring_buffer.c 131 KB