aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2014-08-18 13:21:08 -0400
committerSteven Rostedt <rostedt@goodmis.org>2014-08-22 13:21:14 -0400
commit84261912ebee41269004e8a9f3614ba38ef6b206 (patch)
tree26a01f98f3c14d299570012d5aa5655794d3a9e6 /kernel
parent33b7f99cf003ca6c1d31c42b50e1100ad71aaec0 (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')
-rw-r--r--kernel/trace/ftrace.c43
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
1294static void 1294static void
1295ftrace_hash_rec_disable(struct ftrace_ops *ops, int filter_hash); 1295ftrace_hash_rec_disable_modify(struct ftrace_ops *ops, int filter_hash);
1296static void 1296static void
1297ftrace_hash_rec_enable(struct ftrace_ops *ops, int filter_hash); 1297ftrace_hash_rec_enable_modify(struct ftrace_ops *ops, int filter_hash);
1298 1298
1299static int 1299static int
1300ftrace_hash_move(struct ftrace_ops *ops, int enable, 1300ftrace_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
1689static 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
1712static 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
1718static 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
1689static void print_ip_ins(const char *fmt, unsigned char *p) 1724static void print_ip_ins(const char *fmt, unsigned char *p)
1690{ 1725{
1691 int i; 1726 int i;