tracing: Have the reg function allow to fail
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>
Mon, 28 Nov 2016 18:03:21 +0000 (13:03 -0500)
committerSteven Rostedt <rostedt@goodmis.org>
Fri, 9 Dec 2016 14:13:30 +0000 (09:13 -0500)
Some tracepoints have a registration function that gets enabled when the
tracepoint is enabled. There may be cases that the registraction function
must fail (for example, can't allocate enough memory). In this case, the
tracepoint should also fail to register, otherwise the user would not know
why the tracepoint is not working.

Cc: David Howells <dhowells@redhat.com>
Cc: Seiji Aguchi <seiji.aguchi@hds.com>
Cc: Anton Blanchard <anton@samba.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
15 files changed:
arch/powerpc/include/asm/trace.h
arch/powerpc/platforms/powernv/opal-tracepoints.c
arch/powerpc/platforms/pseries/lpar.c
arch/x86/include/asm/trace/exceptions.h
arch/x86/include/asm/trace/irq_vectors.h
arch/x86/kernel/tracepoint.c
drivers/i2c/i2c-core.c
include/linux/tracepoint-defs.h
include/linux/tracepoint.h
include/trace/events/i2c.h
kernel/trace/trace_benchmark.c
kernel/trace/trace_benchmark.h
kernel/tracepoint.c
samples/trace_events/trace-events-sample.c
samples/trace_events/trace-events-sample.h

index 32e36b16773fd876a7b246ddb9e23c28193c3570..c05cef6ee06c82c4a68c77ec95c48c55ac2e7010 100644 (file)
@@ -54,7 +54,7 @@ DEFINE_EVENT(ppc64_interrupt_class, timer_interrupt_exit,
 );
 
 #ifdef CONFIG_PPC_PSERIES
-extern void hcall_tracepoint_regfunc(void);
+extern int hcall_tracepoint_regfunc(void);
 extern void hcall_tracepoint_unregfunc(void);
 
 TRACE_EVENT_FN_COND(hcall_entry,
@@ -104,7 +104,7 @@ TRACE_EVENT_FN_COND(hcall_exit,
 #endif
 
 #ifdef CONFIG_PPC_POWERNV
-extern void opal_tracepoint_regfunc(void);
+extern int opal_tracepoint_regfunc(void);
 extern void opal_tracepoint_unregfunc(void);
 
 TRACE_EVENT_FN(opal_entry,
index 1e496b780efdaf16c0daea9b60611d31ba06ab45..3c447002edffdc13ac3548d3c71b155db87d83d2 100644 (file)
@@ -6,9 +6,10 @@
 #ifdef HAVE_JUMP_LABEL
 struct static_key opal_tracepoint_key = STATIC_KEY_INIT;
 
-void opal_tracepoint_regfunc(void)
+int opal_tracepoint_regfunc(void)
 {
        static_key_slow_inc(&opal_tracepoint_key);
+       return 0;
 }
 
 void opal_tracepoint_unregfunc(void)
@@ -25,9 +26,10 @@ void opal_tracepoint_unregfunc(void)
 /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
 extern long opal_tracepoint_refcount;
 
-void opal_tracepoint_regfunc(void)
+int opal_tracepoint_regfunc(void)
 {
        opal_tracepoint_refcount++;
+       return 0;
 }
 
 void opal_tracepoint_unregfunc(void)
index aa35245d8d6d337204806bbb5888e9df4d5455ef..c0423ce3955c8a24b8ff9de646fcf1965e3365b0 100644 (file)
@@ -661,9 +661,10 @@ EXPORT_SYMBOL(arch_free_page);
 #ifdef HAVE_JUMP_LABEL
 struct static_key hcall_tracepoint_key = STATIC_KEY_INIT;
 
-void hcall_tracepoint_regfunc(void)
+int hcall_tracepoint_regfunc(void)
 {
        static_key_slow_inc(&hcall_tracepoint_key);
+       return 0;
 }
 
 void hcall_tracepoint_unregfunc(void)
@@ -680,9 +681,10 @@ void hcall_tracepoint_unregfunc(void)
 /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
 extern long hcall_tracepoint_refcount;
 
-void hcall_tracepoint_regfunc(void)
+int hcall_tracepoint_regfunc(void)
 {
        hcall_tracepoint_refcount++;
+       return 0;
 }
 
 void hcall_tracepoint_unregfunc(void)
index 2fbc66c7885b56d3771c7b143b98252445b9940c..2422b14c50a7f9ce1a6776eda1a0b309be26afbf 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <linux/tracepoint.h>
 
-extern void trace_irq_vector_regfunc(void);
+extern int trace_irq_vector_regfunc(void);
 extern void trace_irq_vector_unregfunc(void);
 
 DECLARE_EVENT_CLASS(x86_exceptions,
index 38a09a13a9bcdab24f0e2f08fd67f10cc25236dd..32dd6a9e343c075307585a8464d53743a46b7206 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <linux/tracepoint.h>
 
-extern void trace_irq_vector_regfunc(void);
+extern int trace_irq_vector_regfunc(void);
 extern void trace_irq_vector_unregfunc(void);
 
 DECLARE_EVENT_CLASS(x86_irq_vector,
index 1c113db9ed573c3d8723fccc177431861df2bd19..15515132bf0d22c458cb723ca7696f07bcf3d784 100644 (file)
@@ -34,7 +34,7 @@ static void switch_idt(void *arg)
        local_irq_restore(flags);
 }
 
-void trace_irq_vector_regfunc(void)
+int trace_irq_vector_regfunc(void)
 {
        mutex_lock(&irq_vector_mutex);
        if (!trace_irq_vector_refcount) {
@@ -44,6 +44,7 @@ void trace_irq_vector_regfunc(void)
        }
        trace_irq_vector_refcount++;
        mutex_unlock(&irq_vector_mutex);
+       return 0;
 }
 
 void trace_irq_vector_unregfunc(void)
index b432b64e307a81740b0ce8a292dc9b80a3921a40..6a2b995d7fc446672c177cd4ddda7c1ad868503a 100644 (file)
@@ -77,9 +77,10 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
 static struct static_key i2c_trace_msg = STATIC_KEY_INIT_FALSE;
 static bool is_registered;
 
-void i2c_transfer_trace_reg(void)
+int i2c_transfer_trace_reg(void)
 {
        static_key_slow_inc(&i2c_trace_msg);
+       return 0;
 }
 
 void i2c_transfer_trace_unreg(void)
index 4ac89acb613687bd0899e7cbddadb79f4325349e..a03192052066813e89b324eb091988569f97c542 100644 (file)
@@ -29,7 +29,7 @@ struct tracepoint_func {
 struct tracepoint {
        const char *name;               /* Tracepoint name */
        struct static_key key;
-       void (*regfunc)(void);
+       int (*regfunc)(void);
        void (*unregfunc)(void);
        struct tracepoint_func __rcu *funcs;
 };
index be586c632a0c04da3887ae6a0cf28357df98ef5c..f72fcfe0e66a80a80ae59a175e21abfba5b5ca42 100644 (file)
@@ -81,7 +81,7 @@ static inline void tracepoint_synchronize_unregister(void)
 }
 
 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
-extern void syscall_regfunc(void);
+extern int syscall_regfunc(void);
 extern void syscall_unregfunc(void);
 #endif /* CONFIG_HAVE_SYSCALL_TRACEPOINTS */
 
index fe17187df65d24c4f45e1c3e8daccd1b49647070..4abb8eab34d31939b0d6b1fdbb910f5f9e7870a9 100644 (file)
@@ -20,7 +20,7 @@
 /*
  * drivers/i2c/i2c-core.c
  */
-extern void i2c_transfer_trace_reg(void);
+extern int i2c_transfer_trace_reg(void);
 extern void i2c_transfer_trace_unreg(void);
 
 /*
index 0f109c4130d300384cc5e1a22d4fbbb98ed1539f..f76d0416dd839a7b0d9f5f0ccb780c5c8cdc0b4e 100644 (file)
@@ -164,11 +164,12 @@ static int benchmark_event_kthread(void *arg)
  * When the benchmark tracepoint is enabled, it calls this
  * function and the thread that calls the tracepoint is created.
  */
-void trace_benchmark_reg(void)
+int trace_benchmark_reg(void)
 {
        bm_event_thread = kthread_run(benchmark_event_kthread,
                                      NULL, "event_benchmark");
        WARN_ON(!bm_event_thread);
+       return 0;
 }
 
 /*
index 3c1df1df4e29cb74dcd361c75aa54e764adba04e..ebdbfc2f2a645a90ec821990911f088790a79d41 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <linux/tracepoint.h>
 
-extern void trace_benchmark_reg(void);
+extern int trace_benchmark_reg(void);
 extern void trace_benchmark_unreg(void);
 
 #define BENCHMARK_EVENT_STRLEN         128
index d0639d9178997035004ee639a6ffbd95eb5396d9..1f9a31f934a4178c416b90f1f5d0a0ad64b6f145 100644 (file)
@@ -194,9 +194,13 @@ static int tracepoint_add_func(struct tracepoint *tp,
                               struct tracepoint_func *func, int prio)
 {
        struct tracepoint_func *old, *tp_funcs;
+       int ret;
 
-       if (tp->regfunc && !static_key_enabled(&tp->key))
-               tp->regfunc();
+       if (tp->regfunc && !static_key_enabled(&tp->key)) {
+               ret = tp->regfunc();
+               if (ret < 0)
+                       return ret;
+       }
 
        tp_funcs = rcu_dereference_protected(tp->funcs,
                        lockdep_is_held(&tracepoints_mutex));
@@ -529,7 +533,7 @@ EXPORT_SYMBOL_GPL(for_each_kernel_tracepoint);
 /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
 static int sys_tracepoint_refcount;
 
-void syscall_regfunc(void)
+int syscall_regfunc(void)
 {
        struct task_struct *p, *t;
 
@@ -541,6 +545,8 @@ void syscall_regfunc(void)
                read_unlock(&tasklist_lock);
        }
        sys_tracepoint_refcount++;
+
+       return 0;
 }
 
 void syscall_unregfunc(void)
index 880a7d1d27d24025c9ceb8703075f81dab80c35d..30e282d33d4dc5aeca7b1a11cd324f32d2cb5e4e 100644 (file)
@@ -79,7 +79,7 @@ static int simple_thread_fn(void *arg)
 
 static DEFINE_MUTEX(thread_mutex);
 
-void foo_bar_reg(void)
+int foo_bar_reg(void)
 {
        pr_info("Starting thread for foo_bar_fn\n");
        /*
@@ -90,6 +90,7 @@ void foo_bar_reg(void)
        mutex_lock(&thread_mutex);
        simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn");
        mutex_unlock(&thread_mutex);
+       return 0;
 }
 
 void foo_bar_unreg(void)
index d6b75bb495b35ad503eb815867df697db3cd914f..76a75ab7a60879f5b3de69eedd29cdc22027550e 100644 (file)
@@ -354,7 +354,7 @@ TRACE_EVENT_CONDITION(foo_bar_with_cond,
        TP_printk("foo %s %d", __get_str(foo), __entry->bar)
 );
 
-void foo_bar_reg(void);
+int foo_bar_reg(void);
 void foo_bar_unreg(void);
 
 /*