#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
-#include <linux/uuid.h>
+#include "wrapper/uuid.h"
#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */
#include "ltt-events.h"
#include "ltt-tracer.h"
static
int _ltt_session_metadata_statedump(struct ltt_session *session);
-
-static
void synchronize_trace(void)
{
synchronize_sched();
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;
goto end;
}
ACCESS_ONCE(session->active) = 0;
- synchronize_trace(); /* Wait for in-flight events to complete */
end:
mutex_unlock(&sessions_mutex);
return ret;
{
int old;
+ if (channel == channel->session->metadata)
+ return -EPERM;
old = xchg(&channel->enabled, 1);
if (old)
return -EEXIST;
{
int old;
+ if (channel == channel->session->metadata)
+ return -EPERM;
old = xchg(&channel->enabled, 0);
if (!old)
return -EEXIST;
{
int old;
+ if (event->chan == event->chan->session->metadata)
+ return -EPERM;
old = xchg(&event->enabled, 1);
if (old)
return -EEXIST;
{
int old;
+ if (event->chan == event->chan->session->metadata)
+ return -EPERM;
old = xchg(&event->enabled, 0);
if (!old)
return -EEXIST;
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)
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;
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;
create_error:
kfree(chan);
nomem:
+ if (transport)
+ module_put(transport->owner);
notransport:
active:
mutex_unlock(&sessions_mutex);
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);
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,
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;
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);