Skip to content

Commit

Permalink
ftrace: Fix en(dis)able graph caller when en(dis)abling record via sy…
Browse files Browse the repository at this point in the history
…sctl

When ftrace is enabled globally through the proc interface, we must check if
ftrace_graph_active is set. If it is set, then we should also pass the
FTRACE_START_FUNC_RET command to ftrace_run_update_code(). Similarly, when
ftrace is disabled globally through the proc interface, we must check if
ftrace_graph_active is set. If it is set, then we should also pass the
FTRACE_STOP_FUNC_RET command to ftrace_run_update_code().

Consider the following situation.

 # echo 0 > /proc/sys/kernel/ftrace_enabled

After this ftrace_enabled = 0.

 # echo function_graph > /sys/kernel/debug/tracing/current_tracer

Since ftrace_enabled = 0, ftrace_enable_ftrace_graph_caller() is never
called.

 # echo 1 > /proc/sys/kernel/ftrace_enabled

Now ftrace_enabled will be set to true, but still
ftrace_enable_ftrace_graph_caller() will not be called, which is not
desired.

Further if we execute the following after this:
  # echo nop > /sys/kernel/debug/tracing/current_tracer

Now since ftrace_enabled is set it will call
ftrace_disable_ftrace_graph_caller(), which causes a kernel warning on
the ARM platform.

On the ARM platform, when ftrace_enable_ftrace_graph_caller() is called,
it checks whether the old instruction is a nop or not. If it's not a nop,
then it returns an error. If it is a nop then it replaces instruction at
that address with a branch to ftrace_graph_caller.
ftrace_disable_ftrace_graph_caller() behaves just the opposite. Therefore,
if generic ftrace code ever calls either ftrace_enable_ftrace_graph_caller()
or ftrace_disable_ftrace_graph_caller() consecutively two times in a row,
then it will return an error, which will cause the generic ftrace code to
raise a warning.

Note, x86 does not have an issue with this because the architecture
specific code for ftrace_enable_ftrace_graph_caller() and
ftrace_disable_ftrace_graph_caller() does not check the previous state,
and calling either of these functions twice in a row has no ill effect.

Link: http://lkml.kernel.org/r/e4fbe64cdac0dd0e86a3bf914b0f83c0b419f146.1425666454.git.panand@redhat.com

Cc: [email protected] # 2.6.31+
Signed-off-by: Pratyush Anand <[email protected]>
[
  removed extra if (ftrace_start_up) and defined ftrace_graph_active as 0
  if CONFIG_FUNCTION_GRAPH_TRACER is not set.
]
Signed-off-by: Steven Rostedt <[email protected]>
  • Loading branch information
Pratyush Anand authored and rostedt committed Mar 9, 2015
1 parent b24d443 commit 1619dc3
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,12 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer)

static struct pid * const ftrace_swapper_pid = &init_struct_pid;

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
static int ftrace_graph_active;
#else
# define ftrace_graph_active 0
#endif

#ifdef CONFIG_DYNAMIC_FTRACE

static struct ftrace_ops *removed_ops;
Expand Down Expand Up @@ -2692,24 +2698,36 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)

static void ftrace_startup_sysctl(void)
{
int command;

if (unlikely(ftrace_disabled))
return;

/* Force update next time */
saved_ftrace_func = NULL;
/* ftrace_start_up is true if we want ftrace running */
if (ftrace_start_up)
ftrace_run_update_code(FTRACE_UPDATE_CALLS);
if (ftrace_start_up) {
command = FTRACE_UPDATE_CALLS;
if (ftrace_graph_active)
command |= FTRACE_START_FUNC_RET;
ftrace_run_update_code(command);
}
}

static void ftrace_shutdown_sysctl(void)
{
int command;

if (unlikely(ftrace_disabled))
return;

/* ftrace_start_up is true if ftrace is running */
if (ftrace_start_up)
ftrace_run_update_code(FTRACE_DISABLE_CALLS);
if (ftrace_start_up) {
command = FTRACE_DISABLE_CALLS;
if (ftrace_graph_active)
command |= FTRACE_STOP_FUNC_RET;
ftrace_run_update_code(command);
}
}

static cycle_t ftrace_update_time;
Expand Down Expand Up @@ -5594,8 +5612,6 @@ static struct ftrace_ops graph_ops = {
ASSIGN_OPS_HASH(graph_ops, &global_ops.local_hash)
};

static int ftrace_graph_active;

int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
{
return 0;
Expand Down

0 comments on commit 1619dc3

Please sign in to comment.