|
@@ -1059,6 +1059,12 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
|
|
|
|
|
|
static struct pid * const ftrace_swapper_pid = &init_struct_pid;
|
|
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
|
|
#ifdef CONFIG_DYNAMIC_FTRACE
|
|
|
|
|
|
static struct ftrace_ops *removed_ops;
|
|
static struct ftrace_ops *removed_ops;
|
|
@@ -2041,8 +2047,12 @@ static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
|
|
if (!ftrace_rec_count(rec))
|
|
if (!ftrace_rec_count(rec))
|
|
rec->flags = 0;
|
|
rec->flags = 0;
|
|
else
|
|
else
|
|
- /* Just disable the record (keep REGS state) */
|
|
|
|
- rec->flags &= ~FTRACE_FL_ENABLED;
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Just disable the record, but keep the ops TRAMP
|
|
|
|
+ * and REGS states. The _EN flags must be disabled though.
|
|
|
|
+ */
|
|
|
|
+ rec->flags &= ~(FTRACE_FL_ENABLED | FTRACE_FL_TRAMP_EN |
|
|
|
|
+ FTRACE_FL_REGS_EN);
|
|
}
|
|
}
|
|
|
|
|
|
return FTRACE_UPDATE_MAKE_NOP;
|
|
return FTRACE_UPDATE_MAKE_NOP;
|
|
@@ -2688,24 +2698,36 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
|
|
|
|
|
|
static void ftrace_startup_sysctl(void)
|
|
static void ftrace_startup_sysctl(void)
|
|
{
|
|
{
|
|
|
|
+ int command;
|
|
|
|
+
|
|
if (unlikely(ftrace_disabled))
|
|
if (unlikely(ftrace_disabled))
|
|
return;
|
|
return;
|
|
|
|
|
|
/* Force update next time */
|
|
/* Force update next time */
|
|
saved_ftrace_func = NULL;
|
|
saved_ftrace_func = NULL;
|
|
/* ftrace_start_up is true if we want ftrace running */
|
|
/* 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_startup_enable(command);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
static void ftrace_shutdown_sysctl(void)
|
|
static void ftrace_shutdown_sysctl(void)
|
|
{
|
|
{
|
|
|
|
+ int command;
|
|
|
|
+
|
|
if (unlikely(ftrace_disabled))
|
|
if (unlikely(ftrace_disabled))
|
|
return;
|
|
return;
|
|
|
|
|
|
/* ftrace_start_up is true if ftrace is running */
|
|
/* 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;
|
|
static cycle_t ftrace_update_time;
|
|
@@ -5558,12 +5580,12 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
|
|
|
|
|
|
if (ftrace_enabled) {
|
|
if (ftrace_enabled) {
|
|
|
|
|
|
- ftrace_startup_sysctl();
|
|
|
|
-
|
|
|
|
/* we are starting ftrace again */
|
|
/* we are starting ftrace again */
|
|
if (ftrace_ops_list != &ftrace_list_end)
|
|
if (ftrace_ops_list != &ftrace_list_end)
|
|
update_ftrace_function();
|
|
update_ftrace_function();
|
|
|
|
|
|
|
|
+ ftrace_startup_sysctl();
|
|
|
|
+
|
|
} else {
|
|
} else {
|
|
/* stopping ftrace calls (just send to ftrace_stub) */
|
|
/* stopping ftrace calls (just send to ftrace_stub) */
|
|
ftrace_trace_function = ftrace_stub;
|
|
ftrace_trace_function = ftrace_stub;
|
|
@@ -5590,8 +5612,6 @@ static struct ftrace_ops graph_ops = {
|
|
ASSIGN_OPS_HASH(graph_ops, &global_ops.local_hash)
|
|
ASSIGN_OPS_HASH(graph_ops, &global_ops.local_hash)
|
|
};
|
|
};
|
|
|
|
|
|
-static int ftrace_graph_active;
|
|
|
|
-
|
|
|
|
int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
|
|
int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
|
|
{
|
|
{
|
|
return 0;
|
|
return 0;
|