X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=ltt-events.c;h=9eb2c2f2ef838998e7eedb3fee14f0dddc7b9aa2;hb=6d2a620c03c40df6fb09429e9895f71c5d9dfa76;hp=7c7cda6525a4250379521ddf40b4a4bcce389dc2;hpb=11b5a3c23711e1119185011f791f599713914d67;p=lttng-modules.git diff --git a/ltt-events.c b/ltt-events.c index 7c7cda65..9eb2c2f2 100644 --- a/ltt-events.c +++ b/ltt-events.c @@ -11,7 +11,7 @@ #include #include #include -#include /* For vmalloc_sync_all */ +#include "wrapper/symbols.h" /* for wrapper_vmalloc_sync_all() */ #include "ltt-events.h" static LIST_HEAD(sessions); @@ -32,10 +32,11 @@ struct ltt_session *ltt_session_create(void) struct ltt_session *session; mutex_lock(&sessions_mutex); - session = kmalloc(sizeof(struct ltt_session), GFP_KERNEL); + session = kzalloc(sizeof(struct ltt_session), GFP_KERNEL); if (!session) return NULL; INIT_LIST_HEAD(&session->chan); + INIT_LIST_HEAD(&session->events); list_add(&session->list, &sessions); mutex_unlock(&sessions_mutex); return session; @@ -45,9 +46,14 @@ void ltt_session_destroy(struct ltt_session *session) { struct ltt_channel *chan, *tmpchan; struct ltt_event *event, *tmpevent; + int ret; mutex_lock(&sessions_mutex); - session->active = 0; + ACCESS_ONCE(session->active) = 0; + list_for_each_entry(event, &session->events, list) { + ret = _ltt_event_unregister(event); + WARN_ON(ret); + } synchronize_trace(); /* Wait for in-flight events to complete */ list_for_each_entry_safe(event, tmpevent, &session->events, list) _ltt_event_destroy(event); @@ -67,7 +73,7 @@ int ltt_session_start(struct ltt_session *session) ret = -EBUSY; goto end; } - session->active = 1; + ACCESS_ONCE(session->active) = 1; synchronize_trace(); /* Wait for in-flight events to complete */ end: mutex_unlock(&sessions_mutex); @@ -83,36 +89,46 @@ int ltt_session_stop(struct ltt_session *session) ret = -EBUSY; goto end; } - session->active = 0; + ACCESS_ONCE(session->active) = 0; synchronize_trace(); /* Wait for in-flight events to complete */ end: mutex_unlock(&sessions_mutex); return ret; } +static struct ltt_transport *ltt_transport_find(const char *name) +{ + struct ltt_transport *transport; + + list_for_each_entry(transport, <t_transport_list, node) { + if (!strcmp(transport->name, name)) + return transport; + } + return NULL; +} + struct ltt_channel *ltt_channel_create(struct ltt_session *session, - int overwrite, void *buf_addr, + const char *transport_name, + void *buf_addr, size_t subbuf_size, size_t num_subbuf, unsigned int switch_timer_interval, unsigned int read_timer_interval) { struct ltt_channel *chan; - struct ltt_transport *transport = NULL, *tran_iter; - char *transport_name; + struct ltt_transport *transport; mutex_lock(&sessions_mutex); - if (session->active) + if (session->active) { + printk(KERN_WARNING "LTTng refusing to add channel to active session\n"); goto active; /* Refuse to add channel to active session */ - transport_name = overwrite ? "relay-overwrite" : "relay-discard"; - list_for_each_entry(tran_iter, <t_transport_list, node) { - if (!strcmp(tran_iter->name, transport_name)) { - transport = tran_iter; - break; - } } - if (!transport) + transport = ltt_transport_find(transport_name); + if (!transport) { + printk(KERN_WARNING "LTTng transport %s not found\n", + transport_name); goto notransport; - chan = kmalloc(sizeof(struct ltt_channel), GFP_KERNEL); + } + chan = kzalloc(sizeof(struct ltt_channel), GFP_KERNEL); if (!chan) goto nomem; chan->session = session; @@ -120,11 +136,15 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session, chan->chan = transport->ops.channel_create("[lttng]", session, buf_addr, subbuf_size, num_subbuf, switch_timer_interval, read_timer_interval); + if (!chan->chan) + goto create_error; chan->ops = &transport->ops; list_add(&chan->list, &session->chan); mutex_unlock(&sessions_mutex); return chan; +create_error: + kfree(chan); nomem: notransport: active: @@ -156,8 +176,8 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, char *name, if (chan->free_event_id == -1UL) goto full; /* - * This is O(n^2) (for each event loop called at event creation). - * Might require a hash if we have lots of events. + * This is O(n^2) (for each event, the loop is called at event + * creation). Might require a hash if we have lots of events. */ list_for_each_entry(event, &chan->session->events, list) if (!strcmp(event->name, name)) @@ -185,6 +205,7 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, char *name, default: WARN_ON_ONCE(1); } + list_add(&event->list, &chan->session->events); mutex_unlock(&sessions_mutex); return event; @@ -202,7 +223,7 @@ full: /* * Only used internally at session destruction. */ -int _ltt_event_destroy(struct ltt_event *event) +int _ltt_event_unregister(struct ltt_event *event) { int ret = -EINVAL; @@ -216,9 +237,17 @@ int _ltt_event_destroy(struct ltt_event *event) default: WARN_ON_ONCE(1); } + return ret; +} + +/* + * Only used internally at session destruction. + */ +void _ltt_event_destroy(struct ltt_event *event) +{ kfree(event->name); + list_del(&event->list); kmem_cache_free(event_cache, event); - return ret; } /** @@ -240,7 +269,7 @@ void ltt_transport_register(struct ltt_transport *transport) * registered. We deal with this here so we don't have to call * vmalloc_sync_all() in each module's init. */ - vmalloc_sync_all(); + wrapper_vmalloc_sync_all(); mutex_lock(&sessions_mutex); list_add_tail(&transport->node, <t_transport_list); @@ -263,10 +292,23 @@ EXPORT_SYMBOL_GPL(ltt_transport_unregister); static int __init ltt_events_init(void) { + int ret; + event_cache = KMEM_CACHE(ltt_event, 0); if (!event_cache) return -ENOMEM; + ret = ltt_probes_init(); + if (ret) + goto error; + ret = ltt_debugfs_abi_init(); + if (ret) + goto error_abi; return 0; +error_abi: + ltt_probes_exit(); +error: + kmem_cache_destroy(event_cache); + return ret; } module_init(ltt_events_init); @@ -275,6 +317,8 @@ static void __exit ltt_events_exit(void) { struct ltt_session *session, *tmpsession; + ltt_debugfs_abi_exit(); + ltt_probes_exit(); list_for_each_entry_safe(session, tmpsession, &sessions, list) ltt_session_destroy(session); kmem_cache_destroy(event_cache);