mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
33b7f99cf0
commit
84261912eb
1 changed files with 39 additions and 4 deletions
|
@ -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 @@ update:
|
||||||
* 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,
|
||||||
__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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue