X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=ltt-events.c;h=d6cb397e6a61d44a83c1e8eaa898e8f18976107f;hb=c0e31d2eb7b6d446c87cab8b18a8b8257b4ba3e8;hp=3060c07e05d2386d8d90d0482b3040d3d0f970b9;hpb=d4e1a740a3db547f3f9eaebae9200042fb89f7d6;p=lttng-modules.git diff --git a/ltt-events.c b/ltt-events.c index 3060c07e..d6cb397e 100644 --- a/ltt-events.c +++ b/ltt-events.c @@ -7,9 +7,13 @@ */ #include +#include +#include +#include #include "ltt-events.h" static LIST_HEAD(sessions); +static LIST_HEAD(ltt_transport_list); static DEFINE_MUTEX(sessions_mutex); static struct kmem_cache *event_cache; @@ -56,6 +60,38 @@ int ltt_session_destroy(struct ltt_session *session) kfree(session); } +int ltt_session_start(struct ltt_session *session) +{ + int ret = 0; + + mutex_lock(&sessions_mutex); + if (session->active) { + ret = -EBUSY; + goto end; + } + session->active = 1; + synchronize_trace(); /* Wait for in-flight events to complete */ +end: + mutex_unlock(&sessions_mutex); + return ret +} + +int ltt_session_stop(struct ltt_session *session) +{ + int ret = 0; + + mutex_lock(&sessions_mutex); + if (!session->active) { + ret = -EBUSY; + goto end; + } + session->active = 0; + synchronize_trace(); /* Wait for in-flight events to complete */ +end: + mutex_unlock(&sessions_mutex); + return ret +} + struct ltt_channel *ltt_channel_create(struct ltt_session *session, int overwrite, void *buf_addr, size_t subbuf_size, size_t num_subbuf, @@ -63,22 +99,35 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session, unsigned int read_timer_interval) { struct ltt_channel *chan; + struct ltt_transport *transport = NULL, *tran_iter; + char *transport_name; mutex_lock(&sessions_mutex); if (session->active) 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) + goto notransport; chan = kmalloc(sizeof(struct ltt_channel), GFP_KERNEL); if (!chan) - return NULL; + goto nomem; chan->session = session; init_waitqueue_head(&chan->notify_wait); - - /* TODO: create rb channel */ + transport->ops.channel_create(session, buf_addr, subbuf_size, + num_subbuf, switch_timer_interval, + read_timer_interval); list_add(&chan->list, &session->chan); mutex_unlock(&sessions_mutex); return chan; -exist: +nomem: +notransport: active: mutex_unlock(&sessions_mutex); return NULL; @@ -89,7 +138,7 @@ active: */ int _ltt_channel_destroy(struct ltt_channel *chan) { - /* TODO: destroy rb channel */ + transport->ops.channel_destroy(chan); list_del(&chan->list); kfree(chan); } @@ -163,6 +212,46 @@ int _ltt_event_destroy(struct ltt_event *event) kmem_cache_free(event); } +/** + * ltt_transport_register - LTT transport registration + * @transport: transport structure + * + * Registers a transport which can be used as output to extract the data out of + * LTTng. The module calling this registration function must ensure that no + * trap-inducing code will be executed by the transport functions. E.g. + * vmalloc_sync_all() must be called between a vmalloc and the moment the memory + * is made visible to the transport function. This registration acts as a + * vmalloc_sync_all. Therefore, only if the module allocates virtual memory + * after its registration must it synchronize the TLBs. + */ +void ltt_transport_register(struct ltt_transport *transport) +{ + /* + * Make sure no page fault can be triggered by the module about to be + * registered. We deal with this here so we don't have to call + * vmalloc_sync_all() in each module's init. + */ + vmalloc_sync_all(); + + mutex_lock(&sessions_mutex); + list_add_tail(&transport->node, <t_transport_list); + mutex_unlock(&sessions_mutex); +} +EXPORT_SYMBOL_GPL(ltt_transport_register); + +/** + * ltt_transport_unregister - LTT transport unregistration + * @transport: transport structure + */ +void ltt_transport_unregister(struct ltt_transport *transport) +{ + mutex_lock(&sessions_mutex); + list_del(&transport->node); + mutex_unlock(&sessions_mutex); +} +EXPORT_SYMBOL_GPL(ltt_transport_unregister); + + static int __init ltt_events_init(void) { int ret; @@ -170,9 +259,6 @@ static int __init ltt_events_init(void) events_cache = KMEM_CACHE(ltt_event, 0); if (!events_cache) return -ENOMEM; - - /* TODO: show ABI to userspace */ - return 0; } @@ -180,8 +266,6 @@ static void __exit ltt_events_exit(void) { struct ltt_session *session, *tmpsession; - /* TODO: hide ABI from userspace, wait for callers to release refs. */ - list_for_each_entry_safe(session, tmpsession, &sessions, list) ltt_session_destroy(session); kmem_cache_destroy(events_cache);