From a0493bef1367458230b0319401f8533b0400cea2 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 1 Sep 2015 22:27:35 -0400 Subject: [PATCH] Fix: non-enabler events should be disabled by default The session daemon expects that all events (enablers and events) are disabled when created, so we can attach a filter before enabling them. Also fix the kretprobe to ensure we can enable/disable both the entry and return probe (--function instrumentation). Fixes: #926 Signed-off-by: Mathieu Desnoyers --- lttng-events.c | 64 +++++++++++++++++++++++++++++++++------ lttng-events.h | 9 ++++++ probes/lttng-kretprobes.c | 20 ++++++++++++ 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/lttng-events.c b/lttng-events.c index c49174dd..bd7b4efe 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -329,8 +329,23 @@ int lttng_event_enable(struct lttng_event *event) ret = -EEXIST; goto end; } - ACCESS_ONCE(event->enabled) = 1; - lttng_session_sync_enablers(event->chan->session); + switch (event->instrumentation) { + case LTTNG_KERNEL_TRACEPOINT: + case LTTNG_KERNEL_SYSCALL: + ret = -EINVAL; + break; + case LTTNG_KERNEL_KPROBE: + case LTTNG_KERNEL_FUNCTION: + case LTTNG_KERNEL_NOOP: + ACCESS_ONCE(event->enabled) = 1; + break; + case LTTNG_KERNEL_KRETPROBE: + ret = lttng_kretprobes_event_enable_state(event, 1); + break; + default: + WARN_ON_ONCE(1); + ret = -EINVAL; + } end: mutex_unlock(&sessions_mutex); return ret; @@ -349,8 +364,23 @@ int lttng_event_disable(struct lttng_event *event) ret = -EEXIST; goto end; } - ACCESS_ONCE(event->enabled) = 0; - lttng_session_sync_enablers(event->chan->session); + switch (event->instrumentation) { + case LTTNG_KERNEL_TRACEPOINT: + case LTTNG_KERNEL_SYSCALL: + ret = -EINVAL; + break; + case LTTNG_KERNEL_KPROBE: + case LTTNG_KERNEL_FUNCTION: + case LTTNG_KERNEL_NOOP: + ACCESS_ONCE(event->enabled) = 0; + break; + case LTTNG_KERNEL_KRETPROBE: + ret = lttng_kretprobes_event_enable_state(event, 0); + break; + default: + WARN_ON_ONCE(1); + ret = -EINVAL; + } end: mutex_unlock(&sessions_mutex); return ret; @@ -538,7 +568,11 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, smp_wmb(); break; case LTTNG_KERNEL_KPROBE: - event->enabled = 1; + /* + * Needs to be explicitly enabled after creation, since + * we may want to apply filters. + */ + event->enabled = 0; event->registered = 1; /* * Populate lttng_event structure before event @@ -562,7 +596,11 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, struct lttng_event *event_return; /* kretprobe defines 2 events */ - event->enabled = 1; + /* + * Needs to be explicitly enabled after creation, since + * we may want to apply filters. + */ + event->enabled = 0; event->registered = 1; event_return = kmem_cache_zalloc(event_cache, GFP_KERNEL); @@ -573,7 +611,7 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, event_return->chan = chan; event_return->filter = filter; event_return->id = chan->free_event_id++; - event_return->enabled = 1; + event_return->enabled = 0; event_return->registered = 1; event_return->instrumentation = itype; /* @@ -608,7 +646,11 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, break; } case LTTNG_KERNEL_FUNCTION: - event->enabled = 1; + /* + * Needs to be explicitly enabled after creation, since + * we may want to apply filters. + */ + event->enabled = 0; event->registered = 1; /* * Populate lttng_event structure before event @@ -626,7 +668,11 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, break; case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_SYSCALL: - event->enabled = 1; + /* + * Needs to be explicitly enabled after creation, since + * we may want to apply filters. + */ + event->enabled = 0; event->registered = 0; event->desc = event_desc; if (!event->desc) { diff --git a/lttng-events.h b/lttng-events.h index b3e94a0c..82b88e85 100644 --- a/lttng-events.h +++ b/lttng-events.h @@ -681,6 +681,8 @@ int lttng_kretprobes_register(const char *name, struct lttng_event *event_exit); void lttng_kretprobes_unregister(struct lttng_event *event); void lttng_kretprobes_destroy_private(struct lttng_event *event); +int lttng_kretprobes_event_enable_state(struct lttng_event *event, + int enable); #else static inline int lttng_kretprobes_register(const char *name, @@ -702,6 +704,13 @@ static inline void lttng_kretprobes_destroy_private(struct lttng_event *event) { } + +static inline +int lttng_kretprobes_event_enable_state(struct lttng_event *event, + int enable) +{ + return -ENOSYS; +} #endif #ifdef CONFIG_DYNAMIC_FTRACE diff --git a/probes/lttng-kretprobes.c b/probes/lttng-kretprobes.c index d71090a2..52b3f781 100644 --- a/probes/lttng-kretprobes.c +++ b/probes/lttng-kretprobes.c @@ -285,6 +285,26 @@ void lttng_kretprobes_destroy_private(struct lttng_event *event) } EXPORT_SYMBOL_GPL(lttng_kretprobes_destroy_private); +int lttng_kretprobes_event_enable_state(struct lttng_event *event, + int enable) +{ + struct lttng_event *event_return; + struct lttng_krp *lttng_krp; + + if (event->instrumentation != LTTNG_KERNEL_KRETPROBE) { + return -EINVAL; + } + if (event->enabled == enable) { + return -EBUSY; + } + lttng_krp = event->u.kretprobe.lttng_krp; + event_return = lttng_krp->event[EVENT_RETURN]; + ACCESS_ONCE(event->enabled) = enable; + ACCESS_ONCE(event_return->enabled) = enable; + return 0; +} +EXPORT_SYMBOL_GPL(lttng_kretprobes_event_enable_state); + MODULE_LICENSE("GPL and additional rights"); MODULE_AUTHOR("Mathieu Desnoyers"); MODULE_DESCRIPTION("Linux Trace Toolkit Kretprobes Support"); -- 2.34.1