From: "Steven Rostedt (Red Hat)" For the ftrace_ops that use RCU read locks, and can not be called by unsafe RCU functions (those outside of RCU tracking), have them not update the RCU unsafe function records when they are being registered or unregistered. The ftrace function records store a counter of all the ftrace_ops callbacks that are hooked to the function the record represents. As unsafe RCU functions do not call callbacks that do not specify that they do not use RCU, do not update those records. Cc: Jiri Olsa Cc: Paul E. McKenney Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 3750360..d61f431 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1168,6 +1168,12 @@ static struct ftrace_page *ftrace_new_pgs; static struct ftrace_page *ftrace_pages_start; static struct ftrace_page *ftrace_pages; +/* + * Hash of functions that are not safe to be called by + * callbacks that use RCU read locks. + */ +static struct ftrace_hash *ftrace_unsafe_rcu; + static bool ftrace_hash_empty(struct ftrace_hash *hash) { return !hash || !hash->count; @@ -1638,6 +1644,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops, { struct ftrace_hash *hash; struct ftrace_hash *other_hash; + struct ftrace_hash *rcu_hash; struct ftrace_page *pg; struct dyn_ftrace *rec; int count = 0; @@ -1647,6 +1654,12 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops, if (!(ops->flags & FTRACE_OPS_FL_ENABLED)) return; + /* Ignore rcu unsafe functions unless ops handles them */ + if (ops->flags & FTRACE_OPS_FL_RCU_SAFE) + rcu_hash = NULL; + else + rcu_hash = ftrace_unsafe_rcu; + /* * In the filter_hash case: * If the count is zero, we update all records. @@ -1680,6 +1693,10 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops, int in_hash = 0; int match = 0; + /* Ignore all in the rcu unsafe hash */ + if (ftrace_lookup_ip(rcu_hash, rec->ip)) + continue; + if (all) { /* * Only the filter_hash affects all records. @@ -4291,8 +4308,6 @@ struct notifier_block ftrace_module_exit_nb = { extern struct ftrace_func_finder *__start_ftrace_unsafe_rcu[]; extern struct ftrace_func_finder *__stop_ftrace_unsafe_rcu[]; -static struct ftrace_hash *ftrace_unsafe_rcu; - static void __init create_unsafe_rcu_hash(void) { struct ftrace_func_finder *finder; -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/