ring-buffer: Add recording of ring buffer recursion into recursed_functions
authorSteven Rostedt (VMware) <rostedt@goodmis.org>
Mon, 2 Nov 2020 19:43:10 +0000 (14:43 -0500)
committerSteven Rostedt (VMware) <rostedt@goodmis.org>
Wed, 11 Nov 2020 01:39:40 +0000 (20:39 -0500)
Add a new config RING_BUFFER_RECORD_RECURSION that will place functions that
recurse from the ring buffer into the ftrace recused_functions file.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
kernel/trace/Kconfig
kernel/trace/ring_buffer.c

index 9b11c09..6aa36ec 100644 (file)
@@ -752,6 +752,20 @@ config FTRACE_RECORD_RECURSION_SIZE
          This file can be reset, but the limit can not change in
          size at runtime.
 
+config RING_BUFFER_RECORD_RECURSION
+       bool "Record functions that recurse in the ring buffer"
+       depends on FTRACE_RECORD_RECURSION
+       # default y, because it is coupled with FTRACE_RECORD_RECURSION
+       default y
+       help
+         The ring buffer has its own internal recursion. Although when
+         recursion happens it wont cause harm because of the protection,
+         but it does cause an unwanted overhead. Enabling this option will
+         place where recursion was detected into the ftrace "recursed_functions"
+         file.
+
+         This will add more overhead to cases that have recursion.
+
 config GCOV_PROFILE_FTRACE
        bool "Enable GCOV profiling on ftrace subsystem"
        depends on GCOV_KERNEL
index dc83b3f..ab68f28 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com>
  */
+#include <linux/trace_recursion.h>
 #include <linux/trace_events.h>
 #include <linux/ring_buffer.h>
 #include <linux/trace_clock.h>
@@ -3006,6 +3007,13 @@ rb_wakeups(struct trace_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
        irq_work_queue(&cpu_buffer->irq_work.work);
 }
 
+#ifdef CONFIG_RING_BUFFER_RECORD_RECURSION
+# define do_ring_buffer_record_recursion()     \
+       do_ftrace_record_recursion(_THIS_IP_, _RET_IP_)
+#else
+# define do_ring_buffer_record_recursion() do { } while (0)
+#endif
+
 /*
  * The lock and unlock are done within a preempt disable section.
  * The current_context per_cpu variable can only be modified
@@ -3088,8 +3096,10 @@ trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer)
                 * been updated yet. In this case, use the TRANSITION bit.
                 */
                bit = RB_CTX_TRANSITION;
-               if (val & (1 << (bit + cpu_buffer->nest)))
+               if (val & (1 << (bit + cpu_buffer->nest))) {
+                       do_ring_buffer_record_recursion();
                        return 1;
+               }
        }
 
        val |= (1 << (bit + cpu_buffer->nest));