From e64957da15e3652322dcf6a5389beb01901de8e6 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 22 Jun 2011 15:51:06 -0400 Subject: [PATCH] Add enable/disable per event/channel/session (new ABI) Signed-off-by: Mathieu Desnoyers --- ltt-debugfs-abi.c | 35 ++++++++++++++++++++++---------- ltt-debugfs-abi.h | 4 ++++ ltt-events.c | 46 ++++++++++++++++++++++++++++++++++++++++-- ltt-events.h | 11 ++++++++-- probes/lttng-events.h | 6 +++++- probes/lttng-ftrace.c | 7 ++++++- probes/lttng-kprobes.c | 7 ++++++- 7 files changed, 98 insertions(+), 18 deletions(-) diff --git a/ltt-debugfs-abi.c b/ltt-debugfs-abi.c index e3f5b55d..53cc35d6 100644 --- a/ltt-debugfs-abi.c +++ b/ltt-debugfs-abi.c @@ -330,10 +330,10 @@ fd_error: * This ioctl implements lttng commands: * LTTNG_KERNEL_CHANNEL * Returns a LTTng channel file descriptor - * LTTNG_KERNEL_SESSION_START - * Starts tracing session - * LTTNG_KERNEL_SESSION_STOP - * Stops tracing session + * LTTNG_KERNEL_ENABLE + * Enables tracing for a session (weak enable) + * LTTNG_KERNEL_DISABLE + * Disables tracing for a session (strong disable) * LTTNG_KERNEL_METADATA * Returns a LTTng metadata file descriptor * @@ -350,9 +350,11 @@ long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (struct lttng_kernel_channel __user *) arg, PER_CPU_CHANNEL); case LTTNG_KERNEL_SESSION_START: - return ltt_session_start(session); + case LTTNG_KERNEL_ENABLE: + return ltt_session_enable(session); case LTTNG_KERNEL_SESSION_STOP: - return ltt_session_stop(session); + case LTTNG_KERNEL_DISABLE: + return ltt_session_disable(session); case LTTNG_KERNEL_METADATA: return lttng_abi_create_channel(file, (struct lttng_kernel_channel __user *) arg, @@ -506,6 +508,10 @@ fd_error: * Returns an event file descriptor or failure. * LTTNG_KERNEL_CONTEXT * Prepend a context field to each event in the channel + * LTTNG_KERNEL_ENABLE + * Enable recording for events in this channel (weak enable) + * LTTNG_KERNEL_DISABLE + * Disable recording for events in this channel (strong disable) * * Channel and event file descriptors also hold a reference on the session. */ @@ -523,6 +529,10 @@ long lttng_channel_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return lttng_abi_add_context(file, (struct lttng_kernel_context __user *) arg, &channel->ctx, channel->session); + case LTTNG_KERNEL_ENABLE: + return ltt_channel_enable(channel); + case LTTNG_KERNEL_DISABLE: + return ltt_channel_disable(channel); default: return -ENOIOCTLCMD; } @@ -614,13 +624,12 @@ static const struct file_operations lttng_metadata_fops = { * @arg: command arg * * This ioctl implements lttng commands: - * LTTNG_KERNEL_STREAM - * Returns an event stream file descriptor or failure. - * (typically, one event stream records events from one CPU) - * LTTNG_KERNEL_EVENT - * Returns an event file descriptor or failure. * LTTNG_KERNEL_CONTEXT * Prepend a context field to each record of this event + * LTTNG_KERNEL_ENABLE + * Enable recording for this event (weak enable) + * LTTNG_KERNEL_DISABLE + * Disable recording for this event (strong disable) */ static long lttng_event_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -632,6 +641,10 @@ long lttng_event_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return lttng_abi_add_context(file, (struct lttng_kernel_context __user *) arg, &event->ctx, event->chan->session); + case LTTNG_KERNEL_ENABLE: + return ltt_event_enable(event); + case LTTNG_KERNEL_DISABLE: + return ltt_event_disable(event); default: return -ENOIOCTLCMD; } diff --git a/ltt-debugfs-abi.h b/ltt-debugfs-abi.h index 87be71bd..dd38507e 100644 --- a/ltt-debugfs-abi.h +++ b/ltt-debugfs-abi.h @@ -107,4 +107,8 @@ struct lttng_kernel_context { #define LTTNG_KERNEL_CONTEXT \ _IOW(0xF6, 0x70, struct lttng_kernel_context) +/* Event, Channel and Session ioctl */ +#define LTTNG_KERNEL_ENABLE _IO(0xF6, 0x80) +#define LTTNG_KERNEL_DISABLE _IO(0xF6, 0x81) + #endif /* _LTT_DEBUGFS_ABI_H */ diff --git a/ltt-events.c b/ltt-events.c index 40e8e459..a94e8f9a 100644 --- a/ltt-events.c +++ b/ltt-events.c @@ -82,7 +82,7 @@ void ltt_session_destroy(struct ltt_session *session) kfree(session); } -int ltt_session_start(struct ltt_session *session) +int ltt_session_enable(struct ltt_session *session) { int ret = 0; struct ltt_channel *chan; @@ -119,7 +119,7 @@ end: return ret; } -int ltt_session_stop(struct ltt_session *session) +int ltt_session_disable(struct ltt_session *session) { int ret = 0; @@ -135,6 +135,46 @@ end: return ret; } +int ltt_channel_enable(struct ltt_channel *channel) +{ + int old; + + old = xchg(&channel->enabled, 1); + if (old) + return -EEXIST; + return 0; +} + +int ltt_channel_disable(struct ltt_channel *channel) +{ + int old; + + old = xchg(&channel->enabled, 0); + if (!old) + return -EEXIST; + return 0; +} + +int ltt_event_enable(struct ltt_event *event) +{ + int old; + + old = xchg(&event->enabled, 1); + if (old) + return -EEXIST; + return 0; +} + +int ltt_event_disable(struct ltt_event *event) +{ + int old; + + old = xchg(&event->enabled, 0); + if (!old) + return -EEXIST; + return 0; +} + static struct ltt_transport *ltt_transport_find(const char *name) { struct ltt_transport *transport; @@ -180,6 +220,7 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session, read_timer_interval); if (!chan->chan) goto create_error; + chan->enabled = 1; chan->ops = &transport->ops; list_add(&chan->list, &session->chan); mutex_unlock(&sessions_mutex); @@ -232,6 +273,7 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, event->chan = chan; event->filter = filter; event->id = chan->free_event_id++; + event->enabled = 1; event->instrumentation = event_param->instrumentation; /* Populate ltt_event structure before tracepoint registration. */ smp_wmb(); diff --git a/ltt-events.h b/ltt-events.h index 05eff540..787868a9 100644 --- a/ltt-events.h +++ b/ltt-events.h @@ -164,6 +164,7 @@ struct lttng_probe_desc { struct ltt_event { unsigned int id; struct ltt_channel *chan; + int enabled; const struct lttng_event_desc *desc; void *filter; struct lttng_ctx *ctx; @@ -211,6 +212,7 @@ struct ltt_channel_ops { struct ltt_channel { unsigned int id; struct channel *chan; /* Channel buffers */ + int enabled; struct lttng_ctx *ctx; /* Event ID management */ struct ltt_session *session; @@ -243,8 +245,8 @@ struct ltt_transport { }; struct ltt_session *ltt_session_create(void); -int ltt_session_start(struct ltt_session *session); -int ltt_session_stop(struct ltt_session *session); +int ltt_session_enable(struct ltt_session *session); +int ltt_session_disable(struct ltt_session *session); void ltt_session_destroy(struct ltt_session *session); struct ltt_channel *ltt_channel_create(struct ltt_session *session, @@ -263,6 +265,11 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, struct lttng_kernel_event *event_param, void *filter); +int ltt_channel_enable(struct ltt_channel *channel); +int ltt_channel_disable(struct ltt_channel *channel); +int ltt_event_enable(struct ltt_event *event); +int ltt_event_disable(struct ltt_event *event); + void ltt_transport_register(struct ltt_transport *transport); void ltt_transport_unregister(struct ltt_transport *transport); diff --git a/probes/lttng-events.h b/probes/lttng-events.h index 16e26804..f9780485 100644 --- a/probes/lttng-events.h +++ b/probes/lttng-events.h @@ -529,7 +529,11 @@ static void __event_probe__##_name(void *__data, _proto) \ \ if (0) \ (void) __dynamic_len_idx; /* don't warn if unused */ \ - if (!ACCESS_ONCE(__chan->session->active)) \ + if (unlikely(!ACCESS_ONCE(__chan->session->active))) \ + return; \ + if (unlikely(!ACCESS_ONCE(__chan->enabled))) \ + return; \ + if (unlikely(!ACCESS_ONCE(__event->enabled))) \ return; \ __event_len = __event_get_size__##_name(__dynamic_len, _args); \ __event_align = __event_get_align__##_name(_args); \ diff --git a/probes/lttng-ftrace.c b/probes/lttng-ftrace.c index b8bd3447..1aa71831 100644 --- a/probes/lttng-ftrace.c +++ b/probes/lttng-ftrace.c @@ -38,8 +38,13 @@ void lttng_ftrace_handler(unsigned long ip, unsigned long parent_ip, void **data } payload; int ret; - if (!ACCESS_ONCE(chan->session->active)) + if (unlikely(!ACCESS_ONCE(chan->session->active))) return; + if (unlikely(!ACCESS_ONCE(chan->enabled))) + return; + if (unlikely(!ACCESS_ONCE(event->enabled))) + return; + lib_ring_buffer_ctx_init(&ctx, chan->chan, event, sizeof(payload), ltt_alignof(payload), -1); ret = chan->ops->event_reserve(&ctx, event->id); diff --git a/probes/lttng-kprobes.c b/probes/lttng-kprobes.c index 89cfe073..38ee4513 100644 --- a/probes/lttng-kprobes.c +++ b/probes/lttng-kprobes.c @@ -25,8 +25,13 @@ int lttng_kprobes_handler_pre(struct kprobe *p, struct pt_regs *regs) int ret; unsigned long data = (unsigned long) p->addr; - if (!ACCESS_ONCE(chan->session->active)) + if (unlikely(!ACCESS_ONCE(chan->session->active))) return 0; + if (unlikely(!ACCESS_ONCE(chan->enabled))) + return 0; + if (unlikely(!ACCESS_ONCE(event->enabled))) + return 0; + lib_ring_buffer_ctx_init(&ctx, chan->chan, event, sizeof(data), ltt_alignof(data), -1); ret = chan->ops->event_reserve(&ctx, event->id); -- 2.34.1