Skip to content
  • Steven Rostedt (Red Hat)'s avatar
    ftrace: Have function graph only trace based on global_ops filters · 23a8e844
    Steven Rostedt (Red Hat) authored
    Doing some different tests, I discovered that function graph tracing, when
    filtered via the set_ftrace_filter and set_ftrace_notrace files, does
    not always keep with them if another function ftrace_ops is registered
    to trace functions.
    
    The reason is that function graph just happens to trace all functions
    that the function tracer enables. When there was only one user of
    function tracing, the function graph tracer did not need to worry about
    being called by functions that it did not want to trace. But now that there
    are other users, this becomes a problem.
    
    For example, one just needs to do the following:
    
     # cd /sys/kernel/debug/tracing
     # echo schedule > set_ftrace_filter
     # echo function_graph > current_tracer
     # cat trace
    [..]
     0)               |  schedule() {
     ------------------------------------------
     0)    <idle>-0    =>   rcu_pre-7
     ------------------------------------------
    
     0) ! 2980.314 us |  }
     0)               |  schedule() {
     ------------------------------------------
     0)   rcu_pre-7    =>    <idle>-0
     ------------------------------------------
    
     0) + 20.701 us   |  }
    
     # echo 1 > /proc/sys/kernel/stack_tracer_enabled
     # cat trace
    [..]
     1) + 20.825 us   |      }
     1) + 21.651 us   |    }
     1) + 30.924 us   |  } /* SyS_ioctl */
     1)               |  do_page_fault() {
     1)               |    __do_page_fault() {
     1)   0.274 us    |      down_read_trylock();
     1)   0.098 us    |      find_vma();
     1)               |      handle_mm_fault() {
     1)               |        _raw_spin_lock() {
     1)   0.102 us    |          preempt_count_add();
     1)   0.097 us    |          do_raw_spin_lock();
     1)   2.173 us    |        }
     1)               |        do_wp_page() {
     1)   0.079 us    |          vm_normal_page();
     1)   0.086 us    |          reuse_swap_page();
     1)   0.076 us    |          page_move_anon_rmap();
     1)               |          unlock_page() {
     1)   0.082 us    |            page_waitqueue();
     1)   0.086 us    |            __wake_up_bit();
     1)   1.801 us    |          }
     1)   0.075 us    |          ptep_set_access_flags();
     1)               |          _raw_spin_unlock() {
     1)   0.098 us    |            do_raw_spin_unlock();
     1)   0.105 us    |            preempt_count_sub();
     1)   1.884 us    |          }
     1)   9.149 us    |        }
     1) + 13.083 us   |      }
     1)   0.146 us    |      up_read();
    
    When the stack tracer was enabled, it enabled all functions to be traced, which
    now the function graph tracer also traces. This is a side effect that should
    not occur.
    
    To fix this a test is added when the function tracing is changed, as well as when
    the graph tracer is enabled, to see if anything other than the ftrace global_ops
    function tracer is enabled. If so, then the graph tracer calls a test trampoline
    that will look at the function that is being traced and compare it with the
    filters defined by the global_ops.
    
    As an optimization, if there's no other function tracers registered, or if
    the only registered function tracers also use the global ops, the function
    graph infrastructure will call the registered function graph callback directly
    and not go through the test trampoline.
    
    Cc: stable@vger.kernel.org # 3.3+
    Fixes: d2d45c7a
    
     "tracing: Have stack_tracer use a separate list of functions"
    Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
    23a8e844