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

ftrace: Update all ftrace_ops for a ftrace_hash_ops update

When updating what an ftrace_ops traces, if it is registered (that is,
actively tracing), and that ftrace_ops uses the shared global_ops
local_hash, then we need to update all tracers that are active and
also share the global_ops' ftrace_hash_ops.

Cc: stable@vger.kernel.org # 3.16 (apply after 3.17-rc4 is out)
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 33b7f99c
...@@ -1292,9 +1292,9 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash) ...@@ -1292,9 +1292,9 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
} }
static void static void
ftrace_hash_rec_disable(struct ftrace_ops *ops, int filter_hash); ftrace_hash_rec_disable_modify(struct ftrace_ops *ops, int filter_hash);
static void static void
ftrace_hash_rec_enable(struct ftrace_ops *ops, int filter_hash); ftrace_hash_rec_enable_modify(struct ftrace_ops *ops, int filter_hash);
static int static int
ftrace_hash_move(struct ftrace_ops *ops, int enable, ftrace_hash_move(struct ftrace_ops *ops, int enable,
...@@ -1346,13 +1346,13 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable, ...@@ -1346,13 +1346,13 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
* Remove the current set, update the hash and add * Remove the current set, update the hash and add
* them back. * them back.
*/ */
ftrace_hash_rec_disable(ops, enable); ftrace_hash_rec_disable_modify(ops, enable);
old_hash = *dst; old_hash = *dst;
rcu_assign_pointer(*dst, new_hash); rcu_assign_pointer(*dst, new_hash);
free_ftrace_hash_rcu(old_hash); free_ftrace_hash_rcu(old_hash);
ftrace_hash_rec_enable(ops, enable); ftrace_hash_rec_enable_modify(ops, enable);
return 0; return 0;
} }
...@@ -1686,6 +1686,41 @@ static void ftrace_hash_rec_enable(struct ftrace_ops *ops, ...@@ -1686,6 +1686,41 @@ static void ftrace_hash_rec_enable(struct ftrace_ops *ops,
__ftrace_hash_rec_update(ops, filter_hash, 1); __ftrace_hash_rec_update(ops, filter_hash, 1);
} }
static void ftrace_hash_rec_update_modify(struct ftrace_ops *ops,
int filter_hash, int inc)
{
struct ftrace_ops *op;
__ftrace_hash_rec_update(ops, filter_hash, inc);
if (ops->func_hash != &global_ops.local_hash)
return;
/*
* If the ops shares the global_ops hash, then we need to update
* all ops that are enabled and use this hash.
*/
do_for_each_ftrace_op(op, ftrace_ops_list) {
/* Already done */
if (op == ops)
continue;
if (op->func_hash == &global_ops.local_hash)
__ftrace_hash_rec_update(op, filter_hash, inc);
} while_for_each_ftrace_op(op);
}
static void ftrace_hash_rec_disable_modify(struct ftrace_ops *ops,
int filter_hash)
{
ftrace_hash_rec_update_modify(ops, filter_hash, 0);
}
static void ftrace_hash_rec_enable_modify(struct ftrace_ops *ops,
int filter_hash)
{
ftrace_hash_rec_update_modify(ops, filter_hash, 1);
}
static void print_ip_ins(const char *fmt, unsigned char *p) static void print_ip_ins(const char *fmt, unsigned char *p)
{ {
int i; int i;
......
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