Commit e1effa01 authored by Steven Rostedt (Red Hat)'s avatar Steven Rostedt (Red Hat) Committed by Steven Rostedt

ftrace: Annotate the ops operation on update

Add three new flags for ftrace_ops:

  FTRACE_OPS_FL_ADDING
  FTRACE_OPS_FL_REMOVING
  FTRACE_OPS_FL_MODIFYING

These will be set for the ftrace_ops when they are first added
to the function tracing, being removed from function tracing
or just having their functions changed from function tracing,
respectively.

This will be needed to remove the tramp_hash, which can grow quite
big. The tramp_hash is used to note what functions a ftrace_ops
is using a trampoline for. Denoting which ftrace_ops is being
modified, will allow us to use the ftrace_ops hashes themselves,
which are much smaller as they have a global flag to denote if
a ftrace_ops is tracing all functions, as well as a notrace hash
if the ftrace_ops is tracing all but a few. The tramp_hash just
creates a hash item for every function, which can go into the 10s
of thousands if all functions are using the ftrace_ops trampoline.
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 5fecaa04
...@@ -91,6 +91,9 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops); ...@@ -91,6 +91,9 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);
* INITIALIZED - The ftrace_ops has already been initialized (first use time * INITIALIZED - The ftrace_ops has already been initialized (first use time
* register_ftrace_function() is called, it will initialized the ops) * register_ftrace_function() is called, it will initialized the ops)
* DELETED - The ops are being deleted, do not let them be registered again. * DELETED - The ops are being deleted, do not let them be registered again.
* ADDING - The ops is in the process of being added.
* REMOVING - The ops is in the process of being removed.
* MODIFYING - The ops is in the process of changing its filter functions.
*/ */
enum { enum {
FTRACE_OPS_FL_ENABLED = 1 << 0, FTRACE_OPS_FL_ENABLED = 1 << 0,
...@@ -102,6 +105,9 @@ enum { ...@@ -102,6 +105,9 @@ enum {
FTRACE_OPS_FL_STUB = 1 << 6, FTRACE_OPS_FL_STUB = 1 << 6,
FTRACE_OPS_FL_INITIALIZED = 1 << 7, FTRACE_OPS_FL_INITIALIZED = 1 << 7,
FTRACE_OPS_FL_DELETED = 1 << 8, FTRACE_OPS_FL_DELETED = 1 << 8,
FTRACE_OPS_FL_ADDING = 1 << 9,
FTRACE_OPS_FL_REMOVING = 1 << 10,
FTRACE_OPS_FL_MODIFYING = 1 << 11,
}; };
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
......
...@@ -1057,6 +1057,12 @@ static struct pid * const ftrace_swapper_pid = &init_struct_pid; ...@@ -1057,6 +1057,12 @@ static struct pid * const ftrace_swapper_pid = &init_struct_pid;
static struct ftrace_ops *removed_ops; static struct ftrace_ops *removed_ops;
/*
* Set when doing a global update, like enabling all recs or disabling them.
* It is not set when just updating a single ftrace_ops.
*/
static bool update_all_ops;
#ifndef CONFIG_FTRACE_MCOUNT_RECORD #ifndef CONFIG_FTRACE_MCOUNT_RECORD
# error Dynamic ftrace depends on MCOUNT_RECORD # error Dynamic ftrace depends on MCOUNT_RECORD
#endif #endif
...@@ -2366,6 +2372,13 @@ static void ftrace_run_update_code(int command) ...@@ -2366,6 +2372,13 @@ static void ftrace_run_update_code(int command)
FTRACE_WARN_ON(ret); FTRACE_WARN_ON(ret);
} }
static void ftrace_run_modify_code(struct ftrace_ops *ops, int command)
{
ops->flags |= FTRACE_OPS_FL_MODIFYING;
ftrace_run_update_code(command);
ops->flags &= ~FTRACE_OPS_FL_MODIFYING;
}
static ftrace_func_t saved_ftrace_func; static ftrace_func_t saved_ftrace_func;
static int ftrace_start_up; static int ftrace_start_up;
...@@ -2387,6 +2400,13 @@ static void ftrace_startup_enable(int command) ...@@ -2387,6 +2400,13 @@ static void ftrace_startup_enable(int command)
ftrace_run_update_code(command); ftrace_run_update_code(command);
} }
static void ftrace_startup_all(int command)
{
update_all_ops = true;
ftrace_startup_enable(command);
update_all_ops = false;
}
static int ftrace_startup(struct ftrace_ops *ops, int command) static int ftrace_startup(struct ftrace_ops *ops, int command)
{ {
int ret; int ret;
...@@ -2401,12 +2421,22 @@ static int ftrace_startup(struct ftrace_ops *ops, int command) ...@@ -2401,12 +2421,22 @@ static int ftrace_startup(struct ftrace_ops *ops, int command)
ftrace_start_up++; ftrace_start_up++;
command |= FTRACE_UPDATE_CALLS; command |= FTRACE_UPDATE_CALLS;
ops->flags |= FTRACE_OPS_FL_ENABLED; /*
* Note that ftrace probes uses this to start up
* and modify functions it will probe. But we still
* set the ADDING flag for modification, as probes
* do not have trampolines. If they add them in the
* future, then the probes will need to distinguish
* between adding and updating probes.
*/
ops->flags |= FTRACE_OPS_FL_ENABLED | FTRACE_OPS_FL_ADDING;
ftrace_hash_rec_enable(ops, 1); ftrace_hash_rec_enable(ops, 1);
ftrace_startup_enable(command); ftrace_startup_enable(command);
ops->flags &= ~FTRACE_OPS_FL_ADDING;
return 0; return 0;
} }
...@@ -2456,11 +2486,12 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command) ...@@ -2456,11 +2486,12 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
* If the ops uses a trampoline, then it needs to be * If the ops uses a trampoline, then it needs to be
* tested first on update. * tested first on update.
*/ */
ops->flags |= FTRACE_OPS_FL_REMOVING;
removed_ops = ops; removed_ops = ops;
ftrace_run_update_code(command); ftrace_run_update_code(command);
removed_ops = NULL; ops->flags &= ~FTRACE_OPS_FL_REMOVING;
/* /*
* Dynamic ops may be freed, we must make sure that all * Dynamic ops may be freed, we must make sure that all
...@@ -3373,7 +3404,7 @@ static void __enable_ftrace_function_probe(void) ...@@ -3373,7 +3404,7 @@ static void __enable_ftrace_function_probe(void)
if (ftrace_probe_registered) { if (ftrace_probe_registered) {
/* still need to update the function call sites */ /* still need to update the function call sites */
if (ftrace_enabled) if (ftrace_enabled)
ftrace_run_update_code(FTRACE_UPDATE_CALLS); ftrace_run_modify_code(&trace_probe_ops, FTRACE_UPDATE_CALLS);
return; return;
} }
...@@ -3792,7 +3823,7 @@ ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove) ...@@ -3792,7 +3823,7 @@ ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
static void ftrace_ops_update_code(struct ftrace_ops *ops) static void ftrace_ops_update_code(struct ftrace_ops *ops)
{ {
if (ops->flags & FTRACE_OPS_FL_ENABLED && ftrace_enabled) if (ops->flags & FTRACE_OPS_FL_ENABLED && ftrace_enabled)
ftrace_run_update_code(FTRACE_UPDATE_CALLS); ftrace_run_modify_code(ops, FTRACE_UPDATE_CALLS);
} }
static int static int
...@@ -4717,6 +4748,7 @@ core_initcall(ftrace_nodyn_init); ...@@ -4717,6 +4748,7 @@ core_initcall(ftrace_nodyn_init);
static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; } static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
static inline void ftrace_startup_enable(int command) { } static inline void ftrace_startup_enable(int command) { }
static inline void ftrace_startup_all(int command) { }
/* Keep as macros so we do not need to define the commands */ /* Keep as macros so we do not need to define the commands */
# define ftrace_startup(ops, command) \ # define ftrace_startup(ops, command) \
({ \ ({ \
...@@ -5016,7 +5048,8 @@ static int ftrace_pid_add(int p) ...@@ -5016,7 +5048,8 @@ static int ftrace_pid_add(int p)
set_ftrace_pid_task(pid); set_ftrace_pid_task(pid);
ftrace_update_pid_func(); ftrace_update_pid_func();
ftrace_startup_enable(0);
ftrace_startup_all(0);
mutex_unlock(&ftrace_lock); mutex_unlock(&ftrace_lock);
return 0; return 0;
...@@ -5045,7 +5078,7 @@ static void ftrace_pid_reset(void) ...@@ -5045,7 +5078,7 @@ static void ftrace_pid_reset(void)
} }
ftrace_update_pid_func(); ftrace_update_pid_func();
ftrace_startup_enable(0); ftrace_startup_all(0);
mutex_unlock(&ftrace_lock); mutex_unlock(&ftrace_lock);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment