X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttng-events.c;h=b658aaa2f26946fe5bb3badd3a9fb477c61ce785;hb=e1eb6145438ed8c110ebd5a441f2c7bc5a1d5c34;hp=831f0aef80051a2b537e3f7f56aa2c123e4d68a1;hpb=853aee818b0f82ff37a7af159b6fa657ec3bcd29;p=lttng-modules.git diff --git a/lttng-events.c b/lttng-events.c index 831f0aef..b658aaa2 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -27,9 +27,10 @@ #include #include #include +#include #include -#include /* for wrapper_vmalloc_sync_all() */ +#include /* for wrapper_vmalloc_sync_mappings() */ #include #include #include @@ -130,7 +131,7 @@ struct lttng_session *lttng_session_create(void) goto err; INIT_LIST_HEAD(&session->chan); INIT_LIST_HEAD(&session->events); - uuid_le_gen(&session->uuid); + lttng_guid_gen(&session->uuid); metadata_cache = kzalloc(sizeof(struct lttng_metadata_cache), GFP_KERNEL); @@ -198,8 +199,10 @@ void lttng_session_destroy(struct lttng_session *session) BUG_ON(chan->channel_type == METADATA_CHANNEL); _lttng_channel_destroy(chan); } + mutex_lock(&session->metadata_cache->lock); list_for_each_entry(metadata_stream, &session->metadata_cache->metadata_stream, list) _lttng_metadata_channel_hangup(metadata_stream); + mutex_unlock(&session->metadata_cache->lock); if (session->pid_tracker) lttng_pid_tracker_destroy(session->pid_tracker); kref_put(&session->metadata_cache->refcount, metadata_cache_destroy); @@ -1587,7 +1590,7 @@ void lttng_session_lazy_sync_enablers(struct lttng_session *session) * was written and a negative value on error. */ int lttng_metadata_output_channel(struct lttng_metadata_stream *stream, - struct channel *chan) + struct channel *chan, bool *coherent) { struct lib_ring_buffer_ctx ctx; int ret = 0; @@ -1626,6 +1629,7 @@ int lttng_metadata_output_channel(struct lttng_metadata_stream *stream, ret = stream->transport->ops.event_reserve(&ctx, 0); if (ret != 0) { printk(KERN_WARNING "LTTng: Metadata event reservation failed\n"); + stream->coherent = false; goto end; } stream->transport->ops.event_write(&ctx, @@ -1633,18 +1637,46 @@ int lttng_metadata_output_channel(struct lttng_metadata_stream *stream, reserve_len); stream->transport->ops.event_commit(&ctx); stream->metadata_in += reserve_len; + if (reserve_len < len) + stream->coherent = false; + else + stream->coherent = true; ret = reserve_len; end: + if (coherent) + *coherent = stream->coherent; mutex_unlock(&stream->metadata_cache->lock); return ret; } +static +void lttng_metadata_begin(struct lttng_session *session) +{ + if (atomic_inc_return(&session->metadata_cache->producing) == 1) + mutex_lock(&session->metadata_cache->lock); +} + +static +void lttng_metadata_end(struct lttng_session *session) +{ + WARN_ON_ONCE(!atomic_read(&session->metadata_cache->producing)); + if (atomic_dec_return(&session->metadata_cache->producing) == 0) { + struct lttng_metadata_stream *stream; + + list_for_each_entry(stream, &session->metadata_cache->metadata_stream, list) + wake_up_interruptible(&stream->read_wait); + mutex_unlock(&session->metadata_cache->lock); + } +} + /* * Write the metadata to the metadata cache. * Must be called with sessions_mutex held. * The metadata cache lock protects us from concurrent read access from * thread outputting metadata content to ring buffer. + * The content of the printf is printed as a single atomic metadata + * transaction. */ int lttng_metadata_printf(struct lttng_session *session, const char *fmt, ...) @@ -1652,9 +1684,8 @@ int lttng_metadata_printf(struct lttng_session *session, char *str; size_t len; va_list ap; - struct lttng_metadata_stream *stream; - WARN_ON_ONCE(!READ_ONCE(session->active)); + WARN_ON_ONCE(!LTTNG_READ_ONCE(session->active)); va_start(ap, fmt); str = kvasprintf(GFP_KERNEL, fmt, ap); @@ -1663,7 +1694,7 @@ int lttng_metadata_printf(struct lttng_session *session, return -ENOMEM; len = strlen(str); - mutex_lock(&session->metadata_cache->lock); + WARN_ON_ONCE(!atomic_read(&session->metadata_cache->producing)); if (session->metadata_cache->metadata_written + len > session->metadata_cache->cache_alloc) { char *tmp_cache_realloc; @@ -1689,16 +1720,11 @@ int lttng_metadata_printf(struct lttng_session *session, session->metadata_cache->metadata_written, str, len); session->metadata_cache->metadata_written += len; - mutex_unlock(&session->metadata_cache->lock); kfree(str); - list_for_each_entry(stream, &session->metadata_cache->metadata_stream, list) - wake_up_interruptible(&stream->read_wait); - return 0; err: - mutex_unlock(&session->metadata_cache->lock); kfree(str); return -ENOMEM; } @@ -2235,6 +2261,8 @@ int _lttng_fields_metadata_statedump(struct lttng_session *session, /* * Must be called with sessions_mutex held. + * The entire event metadata is printed as a single atomic metadata + * transaction. */ static int _lttng_event_metadata_statedump(struct lttng_session *session, @@ -2243,11 +2271,13 @@ int _lttng_event_metadata_statedump(struct lttng_session *session, { int ret = 0; - if (event->metadata_dumped || !READ_ONCE(session->active)) + if (event->metadata_dumped || !LTTNG_READ_ONCE(session->active)) return 0; if (chan->channel_type == METADATA_CHANNEL) return 0; + lttng_metadata_begin(session); + ret = lttng_metadata_printf(session, "event {\n" " name = \"%s\";\n" @@ -2297,12 +2327,15 @@ int _lttng_event_metadata_statedump(struct lttng_session *session, event->metadata_dumped = 1; end: + lttng_metadata_end(session); return ret; } /* * Must be called with sessions_mutex held. + * The entire channel metadata is printed as a single atomic metadata + * transaction. */ static int _lttng_channel_metadata_statedump(struct lttng_session *session, @@ -2310,12 +2343,14 @@ int _lttng_channel_metadata_statedump(struct lttng_session *session, { int ret = 0; - if (chan->metadata_dumped || !READ_ONCE(session->active)) + if (chan->metadata_dumped || !LTTNG_READ_ONCE(session->active)) return 0; if (chan->channel_type == METADATA_CHANNEL) return 0; + lttng_metadata_begin(session); + WARN_ON_ONCE(!chan->header_type); ret = lttng_metadata_printf(session, "stream {\n" @@ -2349,6 +2384,7 @@ int _lttng_channel_metadata_statedump(struct lttng_session *session, chan->metadata_dumped = 1; end: + lttng_metadata_end(session); return ret; } @@ -2533,8 +2569,11 @@ int _lttng_session_metadata_statedump(struct lttng_session *session) struct lttng_event *event; int ret = 0; - if (!READ_ONCE(session->active)) + if (!LTTNG_READ_ONCE(session->active)) return 0; + + lttng_metadata_begin(session); + if (session->metadata_dumped) goto skip_session; @@ -2696,6 +2735,7 @@ skip_session: } session->metadata_dumped = 1; end: + lttng_metadata_end(session); return ret; } @@ -2706,9 +2746,9 @@ end: * 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 + * vmalloc_sync_mappings() 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 + * vmalloc_sync_mappings. Therefore, only if the module allocates virtual memory * after its registration must it synchronize the TLBs. */ void lttng_transport_register(struct lttng_transport *transport) @@ -2716,9 +2756,9 @@ void lttng_transport_register(struct lttng_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_mappings() in each module's init. */ - wrapper_vmalloc_sync_all(); + wrapper_vmalloc_sync_mappings(); mutex_lock(&sessions_mutex); list_add_tail(&transport->node, <tng_transport_list);