tracing: Have the reg function allow to fail

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>
This commit is contained in:
Steven Rostedt (Red Hat) 2016-11-28 13:03:21 -05:00 committed by Steven Rostedt
parent 38e11df134
commit 8cf868affd
15 changed files with 34 additions and 20 deletions

View File

@ -54,7 +54,7 @@ DEFINE_EVENT(ppc64_interrupt_class, timer_interrupt_exit,
); );
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_PSERIES
extern void hcall_tracepoint_regfunc(void); extern int hcall_tracepoint_regfunc(void);
extern void hcall_tracepoint_unregfunc(void); extern void hcall_tracepoint_unregfunc(void);
TRACE_EVENT_FN_COND(hcall_entry, TRACE_EVENT_FN_COND(hcall_entry,
@ -104,7 +104,7 @@ TRACE_EVENT_FN_COND(hcall_exit,
#endif #endif
#ifdef CONFIG_PPC_POWERNV #ifdef CONFIG_PPC_POWERNV
extern void opal_tracepoint_regfunc(void); extern int opal_tracepoint_regfunc(void);
extern void opal_tracepoint_unregfunc(void); extern void opal_tracepoint_unregfunc(void);
TRACE_EVENT_FN(opal_entry, TRACE_EVENT_FN(opal_entry,

View File

@ -6,9 +6,10 @@
#ifdef HAVE_JUMP_LABEL #ifdef HAVE_JUMP_LABEL
struct static_key opal_tracepoint_key = STATIC_KEY_INIT; 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); static_key_slow_inc(&opal_tracepoint_key);
return 0;
} }
void opal_tracepoint_unregfunc(void) 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 */ /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
extern long opal_tracepoint_refcount; extern long opal_tracepoint_refcount;
void opal_tracepoint_regfunc(void) int opal_tracepoint_regfunc(void)
{ {
opal_tracepoint_refcount++; opal_tracepoint_refcount++;
return 0;
} }
void opal_tracepoint_unregfunc(void) void opal_tracepoint_unregfunc(void)

View File

@ -661,9 +661,10 @@ EXPORT_SYMBOL(arch_free_page);
#ifdef HAVE_JUMP_LABEL #ifdef HAVE_JUMP_LABEL
struct static_key hcall_tracepoint_key = STATIC_KEY_INIT; 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); static_key_slow_inc(&hcall_tracepoint_key);
return 0;
} }
void hcall_tracepoint_unregfunc(void) 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 */ /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
extern long hcall_tracepoint_refcount; extern long hcall_tracepoint_refcount;
void hcall_tracepoint_regfunc(void) int hcall_tracepoint_regfunc(void)
{ {
hcall_tracepoint_refcount++; hcall_tracepoint_refcount++;
return 0;
} }
void hcall_tracepoint_unregfunc(void) void hcall_tracepoint_unregfunc(void)

View File

@ -6,7 +6,7 @@
#include <linux/tracepoint.h> #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); extern void trace_irq_vector_unregfunc(void);
DECLARE_EVENT_CLASS(x86_exceptions, DECLARE_EVENT_CLASS(x86_exceptions,

View File

@ -6,7 +6,7 @@
#include <linux/tracepoint.h> #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); extern void trace_irq_vector_unregfunc(void);
DECLARE_EVENT_CLASS(x86_irq_vector, DECLARE_EVENT_CLASS(x86_irq_vector,

View File

@ -34,7 +34,7 @@ static void switch_idt(void *arg)
local_irq_restore(flags); local_irq_restore(flags);
} }
void trace_irq_vector_regfunc(void) int trace_irq_vector_regfunc(void)
{ {
mutex_lock(&irq_vector_mutex); mutex_lock(&irq_vector_mutex);
if (!trace_irq_vector_refcount) { if (!trace_irq_vector_refcount) {
@ -44,6 +44,7 @@ void trace_irq_vector_regfunc(void)
} }
trace_irq_vector_refcount++; trace_irq_vector_refcount++;
mutex_unlock(&irq_vector_mutex); mutex_unlock(&irq_vector_mutex);
return 0;
} }
void trace_irq_vector_unregfunc(void) void trace_irq_vector_unregfunc(void)

View 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 struct static_key i2c_trace_msg = STATIC_KEY_INIT_FALSE;
static bool is_registered; static bool is_registered;
void i2c_transfer_trace_reg(void) int i2c_transfer_trace_reg(void)
{ {
static_key_slow_inc(&i2c_trace_msg); static_key_slow_inc(&i2c_trace_msg);
return 0;
} }
void i2c_transfer_trace_unreg(void) void i2c_transfer_trace_unreg(void)

View File

@ -29,7 +29,7 @@ struct tracepoint_func {
struct tracepoint { struct tracepoint {
const char *name; /* Tracepoint name */ const char *name; /* Tracepoint name */
struct static_key key; struct static_key key;
void (*regfunc)(void); int (*regfunc)(void);
void (*unregfunc)(void); void (*unregfunc)(void);
struct tracepoint_func __rcu *funcs; struct tracepoint_func __rcu *funcs;
}; };

View File

@ -81,7 +81,7 @@ static inline void tracepoint_synchronize_unregister(void)
} }
#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
extern void syscall_regfunc(void); extern int syscall_regfunc(void);
extern void syscall_unregfunc(void); extern void syscall_unregfunc(void);
#endif /* CONFIG_HAVE_SYSCALL_TRACEPOINTS */ #endif /* CONFIG_HAVE_SYSCALL_TRACEPOINTS */

View File

@ -20,7 +20,7 @@
/* /*
* drivers/i2c/i2c-core.c * 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); extern void i2c_transfer_trace_unreg(void);
/* /*

View File

@ -164,11 +164,12 @@ static int benchmark_event_kthread(void *arg)
* When the benchmark tracepoint is enabled, it calls this * When the benchmark tracepoint is enabled, it calls this
* function and the thread that calls the tracepoint is created. * 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, bm_event_thread = kthread_run(benchmark_event_kthread,
NULL, "event_benchmark"); NULL, "event_benchmark");
WARN_ON(!bm_event_thread); WARN_ON(!bm_event_thread);
return 0;
} }
/* /*

View File

@ -6,7 +6,7 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
extern void trace_benchmark_reg(void); extern int trace_benchmark_reg(void);
extern void trace_benchmark_unreg(void); extern void trace_benchmark_unreg(void);
#define BENCHMARK_EVENT_STRLEN 128 #define BENCHMARK_EVENT_STRLEN 128

View File

@ -194,9 +194,13 @@ static int tracepoint_add_func(struct tracepoint *tp,
struct tracepoint_func *func, int prio) struct tracepoint_func *func, int prio)
{ {
struct tracepoint_func *old, *tp_funcs; struct tracepoint_func *old, *tp_funcs;
int ret;
if (tp->regfunc && !static_key_enabled(&tp->key)) if (tp->regfunc && !static_key_enabled(&tp->key)) {
tp->regfunc(); ret = tp->regfunc();
if (ret < 0)
return ret;
}
tp_funcs = rcu_dereference_protected(tp->funcs, tp_funcs = rcu_dereference_protected(tp->funcs,
lockdep_is_held(&tracepoints_mutex)); 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 */ /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
static int sys_tracepoint_refcount; static int sys_tracepoint_refcount;
void syscall_regfunc(void) int syscall_regfunc(void)
{ {
struct task_struct *p, *t; struct task_struct *p, *t;
@ -541,6 +545,8 @@ void syscall_regfunc(void)
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
} }
sys_tracepoint_refcount++; sys_tracepoint_refcount++;
return 0;
} }
void syscall_unregfunc(void) void syscall_unregfunc(void)

View File

@ -79,7 +79,7 @@ static int simple_thread_fn(void *arg)
static DEFINE_MUTEX(thread_mutex); static DEFINE_MUTEX(thread_mutex);
void foo_bar_reg(void) int foo_bar_reg(void)
{ {
pr_info("Starting thread for foo_bar_fn\n"); pr_info("Starting thread for foo_bar_fn\n");
/* /*
@ -90,6 +90,7 @@ void foo_bar_reg(void)
mutex_lock(&thread_mutex); mutex_lock(&thread_mutex);
simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn"); simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn");
mutex_unlock(&thread_mutex); mutex_unlock(&thread_mutex);
return 0;
} }
void foo_bar_unreg(void) void foo_bar_unreg(void)

View File

@ -354,7 +354,7 @@ TRACE_EVENT_CONDITION(foo_bar_with_cond,
TP_printk("foo %s %d", __get_str(foo), __entry->bar) 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); void foo_bar_unreg(void);
/* /*