X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=ltt-events.c;h=03dbb2036af923e3c60841783bca3f46ac528c00;hb=edb5c2da83545004c5f556accb79d010a6b1e3a9;hp=42d486c195d73c8cdfd265b6a54a5d2bd20950ec;hpb=c6485006a92b1b86fbb48c2b277732d3405295c9;p=lttng-modules.git diff --git a/ltt-events.c b/ltt-events.c index 42d486c1..03dbb203 100644 --- a/ltt-events.c +++ b/ltt-events.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include "wrapper/uuid.h" #include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ #include "ltt-events.h" #include "ltt-tracer.h" @@ -34,8 +34,6 @@ int _ltt_event_metadata_statedump(struct ltt_session *session, static int _ltt_session_metadata_statedump(struct ltt_session *session); - -static void synchronize_trace(void) { synchronize_sched(); @@ -68,6 +66,10 @@ void ltt_session_destroy(struct ltt_session *session) mutex_lock(&sessions_mutex); ACCESS_ONCE(session->active) = 0; + list_for_each_entry(chan, &session->chan, list) { + ret = lttng_syscalls_unregister(chan); + WARN_ON(ret); + } list_for_each_entry(event, &session->events, list) { ret = _ltt_event_unregister(event); WARN_ON(ret); @@ -108,12 +110,9 @@ int ltt_session_enable(struct ltt_session *session) ACCESS_ONCE(session->active) = 1; ACCESS_ONCE(session->been_active) = 1; - synchronize_trace(); /* Wait for in-flight events to complete */ ret = _ltt_session_metadata_statedump(session); - if (ret) { + if (ret) ACCESS_ONCE(session->active) = 0; - synchronize_trace(); /* Wait for in-flight events to complete */ - } end: mutex_unlock(&sessions_mutex); return ret; @@ -129,7 +128,6 @@ int ltt_session_disable(struct ltt_session *session) goto end; } ACCESS_ONCE(session->active) = 0; - synchronize_trace(); /* Wait for in-flight events to complete */ end: mutex_unlock(&sessions_mutex); return ret; @@ -202,7 +200,7 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session, unsigned int read_timer_interval) { struct ltt_channel *chan; - struct ltt_transport *transport; + struct ltt_transport *transport = NULL; mutex_lock(&sessions_mutex); if (session->been_active) @@ -213,6 +211,10 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session, transport_name); goto notransport; } + if (!try_module_get(transport->owner)) { + printk(KERN_WARNING "LTT : Can't lock transport module.\n"); + goto notransport; + } chan = kzalloc(sizeof(struct ltt_channel), GFP_KERNEL); if (!chan) goto nomem; @@ -230,6 +232,7 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session, goto create_error; chan->enabled = 1; chan->ops = &transport->ops; + chan->transport = transport; list_add(&chan->list, &session->chan); mutex_unlock(&sessions_mutex); return chan; @@ -237,6 +240,8 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session, create_error: kfree(chan); nomem: + if (transport) + module_put(transport->owner); notransport: active: mutex_unlock(&sessions_mutex); @@ -250,6 +255,7 @@ static void _ltt_channel_destroy(struct ltt_channel *chan) { chan->ops->channel_destroy(chan->chan); + module_put(chan->transport->owner); list_del(&chan->list); lttng_destroy_context(chan->ctx); kfree(chan); @@ -260,7 +266,8 @@ void _ltt_channel_destroy(struct ltt_channel *chan) */ struct ltt_event *ltt_event_create(struct ltt_channel *chan, struct lttng_kernel_event *event_param, - void *filter) + void *filter, + const struct lttng_event_desc *internal_desc) { struct ltt_event *event; int ret; @@ -307,6 +314,49 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, ret = try_module_get(event->desc->owner); WARN_ON_ONCE(!ret); break; + case LTTNG_KERNEL_KRETPROBE: + { + struct ltt_event *event_return; + + /* kretprobe defines 2 events */ + event_return = + kmem_cache_zalloc(event_cache, GFP_KERNEL); + if (!event_return) + goto register_error; + event_return->chan = chan; + event_return->filter = filter; + event_return->id = chan->free_event_id++; + event_return->enabled = 1; + event_return->instrumentation = event_param->instrumentation; + /* + * Populate ltt_event structure before kretprobe registration. + */ + smp_wmb(); + ret = lttng_kretprobes_register(event_param->name, + event_param->u.kretprobe.symbol_name, + event_param->u.kretprobe.offset, + event_param->u.kretprobe.addr, + event, event_return); + if (ret) { + kmem_cache_free(event_cache, event_return); + goto register_error; + } + /* Take 2 refs on the module: one per event. */ + ret = try_module_get(event->desc->owner); + WARN_ON_ONCE(!ret); + ret = try_module_get(event->desc->owner); + WARN_ON_ONCE(!ret); + ret = _ltt_event_metadata_statedump(chan->session, chan, + event_return); + if (ret) { + kmem_cache_free(event_cache, event_return); + module_put(event->desc->owner); + module_put(event->desc->owner); + goto statedump_error; + } + list_add(&event_return->list, &chan->session->events); + break; + } case LTTNG_KERNEL_FUNCTION: ret = lttng_ftrace_register(event_param->name, event_param->u.ftrace.symbol_name, @@ -316,6 +366,11 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, ret = try_module_get(event->desc->owner); WARN_ON_ONCE(!ret); break; + case LTTNG_KERNEL_NOOP: + event->desc = internal_desc; + if (!event->desc) + goto register_error; + break; default: WARN_ON_ONCE(1); } @@ -327,10 +382,7 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, return event; statedump_error: - WARN_ON_ONCE(tracepoint_probe_unregister(event_param->name, - event->desc->probe_callback, - event)); - ltt_event_put(event->desc); + /* If a statedump error occurs, events will not be readable. */ register_error: kmem_cache_free(event_cache, event); cache_error: @@ -359,10 +411,17 @@ int _ltt_event_unregister(struct ltt_event *event) lttng_kprobes_unregister(event); ret = 0; break; + case LTTNG_KERNEL_KRETPROBE: + lttng_kretprobes_unregister(event); + ret = 0; + break; case LTTNG_KERNEL_FUNCTION: lttng_ftrace_unregister(event); ret = 0; break; + case LTTNG_KERNEL_NOOP: + ret = 0; + break; default: WARN_ON_ONCE(1); } @@ -383,10 +442,16 @@ void _ltt_event_destroy(struct ltt_event *event) module_put(event->desc->owner); lttng_kprobes_destroy_private(event); break; + case LTTNG_KERNEL_KRETPROBE: + module_put(event->desc->owner); + lttng_kretprobes_destroy_private(event); + break; case LTTNG_KERNEL_FUNCTION: module_put(event->desc->owner); lttng_ftrace_destroy_private(event); break; + case LTTNG_KERNEL_NOOP: + break; default: WARN_ON_ONCE(1); } @@ -434,7 +499,7 @@ int lttng_metadata_printf(struct ltt_session *session, * we need to bail out after timeout or being * interrupted. */ - waitret = wait_event_interruptible_timeout(*chan->ops->get_reader_wait_queue(chan->chan), + waitret = wait_event_interruptible_timeout(*chan->ops->get_writer_buf_wait_queue(chan->chan, -1), ({ ret = chan->ops->event_reserve(&ctx, 0); ret != -ENOBUFS || !ret; @@ -465,7 +530,7 @@ int _ltt_field_statedump(struct ltt_session *session, switch (field->type.atype) { case atype_integer: ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } %s;\n", + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n", field->type.u.basic.integer.size, field->type.u.basic.integer.alignment, field->type.u.basic.integer.signedness, @@ -484,7 +549,7 @@ int _ltt_field_statedump(struct ltt_session *session, break; case atype_enum: ret = lttng_metadata_printf(session, - " %s %s;\n", + " %s _%s;\n", field->type.u.basic.enumeration.name, field->name); break; @@ -494,7 +559,7 @@ int _ltt_field_statedump(struct ltt_session *session, elem_type = &field->type.u.array.elem_type; ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } %s[%u];\n", + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", elem_type->u.basic.integer.size, elem_type->u.basic.integer.alignment, elem_type->u.basic.integer.signedness, @@ -540,7 +605,7 @@ int _ltt_field_statedump(struct ltt_session *session, return ret; ret = lttng_metadata_printf(session, - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } %s[ __%s_length ];\n", + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n", elem_type->u.basic.integer.size, (unsigned int) elem_type->u.basic.integer.alignment, elem_type->u.basic.integer.signedness, @@ -563,7 +628,7 @@ int _ltt_field_statedump(struct ltt_session *session, case atype_string: /* Default encoding is UTF8 */ ret = lttng_metadata_printf(session, - " string%s %s;\n", + " string%s _%s;\n", field->type.u.basic.string.encoding == lttng_encode_ASCII ? " { encoding = ASCII; }" : "", field->name); @@ -916,7 +981,7 @@ static int __init ltt_events_init(void) event_cache = KMEM_CACHE(ltt_event, 0); if (!event_cache) return -ENOMEM; - ret = ltt_debugfs_abi_init(); + ret = lttng_abi_init(); if (ret) goto error_abi; return 0; @@ -931,7 +996,7 @@ static void __exit ltt_events_exit(void) { struct ltt_session *session, *tmpsession; - ltt_debugfs_abi_exit(); + lttng_abi_exit(); list_for_each_entry_safe(session, tmpsession, &sessions, list) ltt_session_destroy(session); kmem_cache_destroy(event_cache);