diff options
| author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2014-08-18 13:21:08 -0400 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2014-08-22 13:21:14 -0400 |
| commit | 84261912ebee41269004e8a9f3614ba38ef6b206 (patch) | |
| tree | 26a01f98f3c14d299570012d5aa5655794d3a9e6 /kernel/trace | |
| parent | 33b7f99cf003ca6c1d31c42b50e1100ad71aaec0 (diff) | |
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>
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/ftrace.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index c92757adba79..37f9e90d241c 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -1292,9 +1292,9 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash) | |||
| 1292 | } | 1292 | } |
| 1293 | 1293 | ||
| 1294 | static void | 1294 | static void |
| 1295 | ftrace_hash_rec_disable(struct ftrace_ops *ops, int filter_hash); | 1295 | ftrace_hash_rec_disable_modify(struct ftrace_ops *ops, int filter_hash); |
| 1296 | static void | 1296 | static void |
| 1297 | ftrace_hash_rec_enable(struct ftrace_ops *ops, int filter_hash); | 1297 | ftrace_hash_rec_enable_modify(struct ftrace_ops *ops, int filter_hash); |
| 1298 | 1298 | ||
| 1299 | static int | 1299 | static int |
| 1300 | ftrace_hash_move(struct ftrace_ops *ops, int enable, | 1300 | ftrace_hash_move(struct ftrace_ops *ops, int enable, |
| @@ -1346,13 +1346,13 @@ update: | |||
| 1346 | * Remove the current set, update the hash and add | 1346 | * Remove the current set, update the hash and add |
| 1347 | * them back. | 1347 | * them back. |
| 1348 | */ | 1348 | */ |
| 1349 | ftrace_hash_rec_disable(ops, enable); | 1349 | ftrace_hash_rec_disable_modify(ops, enable); |
| 1350 | 1350 | ||
| 1351 | old_hash = *dst; | 1351 | old_hash = *dst; |
| 1352 | rcu_assign_pointer(*dst, new_hash); | 1352 | rcu_assign_pointer(*dst, new_hash); |
| 1353 | free_ftrace_hash_rcu(old_hash); | 1353 | free_ftrace_hash_rcu(old_hash); |
| 1354 | 1354 | ||
| 1355 | ftrace_hash_rec_enable(ops, enable); | 1355 | ftrace_hash_rec_enable_modify(ops, enable); |
| 1356 | 1356 | ||
| 1357 | return 0; | 1357 | return 0; |
| 1358 | } | 1358 | } |
| @@ -1686,6 +1686,41 @@ static void ftrace_hash_rec_enable(struct ftrace_ops *ops, | |||
| 1686 | __ftrace_hash_rec_update(ops, filter_hash, 1); | 1686 | __ftrace_hash_rec_update(ops, filter_hash, 1); |
| 1687 | } | 1687 | } |
| 1688 | 1688 | ||
| 1689 | static void ftrace_hash_rec_update_modify(struct ftrace_ops *ops, | ||
| 1690 | int filter_hash, int inc) | ||
| 1691 | { | ||
| 1692 | struct ftrace_ops *op; | ||
| 1693 | |||
| 1694 | __ftrace_hash_rec_update(ops, filter_hash, inc); | ||
| 1695 | |||
| 1696 | if (ops->func_hash != &global_ops.local_hash) | ||
| 1697 | return; | ||
| 1698 | |||
| 1699 | /* | ||
| 1700 | * If the ops shares the global_ops hash, then we need to update | ||
| 1701 | * all ops that are enabled and use this hash. | ||
| 1702 | */ | ||
| 1703 | do_for_each_ftrace_op(op, ftrace_ops_list) { | ||
| 1704 | /* Already done */ | ||
| 1705 | if (op == ops) | ||
| 1706 | continue; | ||
| 1707 | if (op->func_hash == &global_ops.local_hash) | ||
| 1708 | __ftrace_hash_rec_update(op, filter_hash, inc); | ||
| 1709 | } while_for_each_ftrace_op(op); | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | static void ftrace_hash_rec_disable_modify(struct ftrace_ops *ops, | ||
| 1713 | int filter_hash) | ||
| 1714 | { | ||
| 1715 | ftrace_hash_rec_update_modify(ops, filter_hash, 0); | ||
| 1716 | } | ||
| 1717 | |||
| 1718 | static void ftrace_hash_rec_enable_modify(struct ftrace_ops *ops, | ||
| 1719 | int filter_hash) | ||
| 1720 | { | ||
| 1721 | ftrace_hash_rec_update_modify(ops, filter_hash, 1); | ||
| 1722 | } | ||
| 1723 | |||
| 1689 | static void print_ip_ins(const char *fmt, unsigned char *p) | 1724 | static void print_ip_ins(const char *fmt, unsigned char *p) |
| 1690 | { | 1725 | { |
| 1691 | int i; | 1726 | int i; |
