[for-next][PATCH 05/18] ftrace: Do not set ftrace records for unsafe RCU when not allowed

From: Steven Rostedt
Date: Wed Sep 04 2013 - 10:37:27 EST


From: "Steven Rostedt (Red Hat)" <rostedt@xxxxxxxxxxx>

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 should not call callbacks that do not specify
that they do not use RCU, do not update those records for ops that
do not specify they are RCU safe.

Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
Acked-by: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx>
---
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 cc63a35..3327aff 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.
@@ -4306,8 +4323,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@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/