[for-next][PATCH 10/18] ftrace: Add selftest to check if RCU unsafe functions are filteredproperly

From: Steven Rostedt
Date: Wed Sep 04 2013 - 10:42:59 EST


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

Add a boot time start up test that has a RCU safe ftrace_ops as well
as an unsafe one. Make sure the RCU safe ops can trace RCU unsafe
functions while the unsafe ftrace_ops can not.

Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
Acked-by: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx>
---
kernel/trace/trace.h | 2 +
kernel/trace/trace_selftest.c | 94 +++++++++++++++++++++++++++++++++
kernel/trace/trace_selftest_dynamic.c | 7 +++
3 files changed, 103 insertions(+)

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 502fed7..3578be6 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -648,6 +648,8 @@ extern unsigned long ftrace_update_tot_cnt;
extern int DYN_FTRACE_TEST_NAME(void);
#define DYN_FTRACE_TEST_NAME2 trace_selftest_dynamic_test_func2
extern int DYN_FTRACE_TEST_NAME2(void);
+#define DYN_FTRACE_TEST_RCU_UNSAFE trace_selftest_dynamic_test_rcu_unsafe
+extern int DYN_FTRACE_TEST_RCU_UNSAFE(void);

extern bool ring_buffer_expanded;
extern bool tracing_selftest_disabled;
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index a7329b7..eeacb47 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -185,6 +185,97 @@ static void reset_counts(void)
trace_selftest_test_dyn_cnt = 0;
}

+static struct ftrace_ops ftrace_rcu_safe_ops = {
+ .func = trace_selftest_test_probe1_func,
+ .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_RCU_SAFE,
+};
+
+static struct ftrace_ops ftrace_rcu_unsafe_ops = {
+ .func = trace_selftest_test_probe2_func,
+ .flags = FTRACE_OPS_FL_RECURSION_SAFE,
+};
+
+static int test_rcu_safe_unsafe(void)
+{
+ int save_ftrace_enabled = ftrace_enabled;
+ char *func_name;
+ int len;
+ int ret = 0;
+
+ printk(KERN_CONT "PASSED\n");
+ pr_info("Testing ftrace rcu safe unsafe: ");
+
+ ftrace_enabled = 1;
+
+ trace_selftest_test_probe1_cnt = 0;
+ trace_selftest_test_probe2_cnt = 0;
+
+ func_name = "*" __stringify(DYN_FTRACE_TEST_RCU_UNSAFE);
+ len = strlen(func_name);
+
+ ftrace_set_filter(&ftrace_rcu_safe_ops, func_name, len, 1);
+ ftrace_set_filter(&ftrace_rcu_unsafe_ops, func_name, len, 1);
+
+ /* Do single registrations first */
+ register_ftrace_function(&ftrace_rcu_safe_ops);
+
+ DYN_FTRACE_TEST_RCU_UNSAFE();
+
+ unregister_ftrace_function(&ftrace_rcu_safe_ops);
+
+ if (trace_selftest_test_probe1_cnt != 1) {
+ printk(KERN_CONT "rcu_safe expected 1 call but had %d ",
+ trace_selftest_test_probe1_cnt);
+ goto out;
+ }
+
+ register_ftrace_function(&ftrace_rcu_unsafe_ops);
+
+ DYN_FTRACE_TEST_RCU_UNSAFE();
+
+ unregister_ftrace_function(&ftrace_rcu_unsafe_ops);
+
+ if (trace_selftest_test_probe2_cnt != 0) {
+ printk(KERN_CONT "rcu_safe expected 0 calls but had %d ",
+ trace_selftest_test_probe2_cnt);
+ goto out;
+ }
+
+ /* Run both together, which uses the list op */
+
+ trace_selftest_test_probe1_cnt = 0;
+ trace_selftest_test_probe2_cnt = 0;
+
+ register_ftrace_function(&ftrace_rcu_safe_ops);
+ register_ftrace_function(&ftrace_rcu_unsafe_ops);
+
+ DYN_FTRACE_TEST_RCU_UNSAFE();
+ DYN_FTRACE_TEST_RCU_UNSAFE();
+ DYN_FTRACE_TEST_RCU_UNSAFE();
+
+ unregister_ftrace_function(&ftrace_rcu_unsafe_ops);
+ unregister_ftrace_function(&ftrace_rcu_safe_ops);
+
+
+ if (trace_selftest_test_probe1_cnt != 3) {
+ printk(KERN_CONT "rcu_safe expected 3 calls but had %d ",
+ trace_selftest_test_probe1_cnt);
+ goto out;
+ }
+
+ if (trace_selftest_test_probe2_cnt != 0) {
+ printk(KERN_CONT "rcu_safe expected 0 calls but had %d ",
+ trace_selftest_test_probe2_cnt);
+ goto out;
+ }
+
+ ret = 0;
+ out:
+ ftrace_enabled = save_ftrace_enabled;
+
+ return ret;
+}
+
static int trace_selftest_ops(int cnt)
{
int save_ftrace_enabled = ftrace_enabled;
@@ -401,6 +492,9 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
if (!ret)
ret = trace_selftest_ops(2);

+ if (!ret)
+ ret = test_rcu_safe_unsafe();
+
return ret;
}

diff --git a/kernel/trace/trace_selftest_dynamic.c b/kernel/trace/trace_selftest_dynamic.c
index b4c475a..5eefa56 100644
--- a/kernel/trace/trace_selftest_dynamic.c
+++ b/kernel/trace/trace_selftest_dynamic.c
@@ -11,3 +11,10 @@ int DYN_FTRACE_TEST_NAME2(void)
/* used to call mcount */
return 0;
}
+
+int trace_selftest_dynamic_test_rcu_unsafe(void)
+{
+ /* used to call mcount */
+ return 0;
+}
+FTRACE_UNSAFE_RCU(trace_selftest_dynamic_test_rcu_unsafe);
--
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/