X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=lttng-events.c;h=4c0b04a09597bef396dba066fd4d64a0733cf206;hb=31f8bf794172102e9758928b481856c4a8800a7f;hp=5a64f5b2e915950233c695b35540344718c3a78f;hpb=ea53823c42a70a80566a340834e2b00e650406b9;p=lttng-modules.git diff --git a/lttng-events.c b/lttng-events.c index 5a64f5b2..4c0b04a0 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -201,6 +201,10 @@ void lttng_session_destroy(struct lttng_session *session) WARN_ON(ret); } synchronize_trace(); /* Wait for in-flight events to complete */ + list_for_each_entry(chan, &session->chan, list) { + ret = lttng_syscalls_destroy(chan); + WARN_ON(ret); + } list_for_each_entry_safe(enabler, tmpenabler, &session->enablers_head, node) lttng_enabler_destroy(enabler); @@ -210,8 +214,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); lttng_id_tracker_destroy(&session->pid_tracker, false); lttng_id_tracker_destroy(&session->vpid_tracker, false); lttng_id_tracker_destroy(&session->uid_tracker, false); @@ -738,6 +744,28 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, event->enabled = 0; event->registered = 0; event->desc = event_desc; + switch (event_param->u.syscall.entryexit) { + case LTTNG_KERNEL_SYSCALL_ENTRYEXIT: + ret = -EINVAL; + goto register_error; + case LTTNG_KERNEL_SYSCALL_ENTRY: + event->u.syscall.entryexit = LTTNG_SYSCALL_ENTRY; + break; + case LTTNG_KERNEL_SYSCALL_EXIT: + event->u.syscall.entryexit = LTTNG_SYSCALL_EXIT; + break; + } + switch (event_param->u.syscall.abi) { + case LTTNG_KERNEL_SYSCALL_ABI_ALL: + ret = -EINVAL; + goto register_error; + case LTTNG_KERNEL_SYSCALL_ABI_NATIVE: + event->u.syscall.abi = LTTNG_SYSCALL_ABI_NATIVE; + break; + case LTTNG_KERNEL_SYSCALL_ABI_COMPAT: + event->u.syscall.abi = LTTNG_SYSCALL_ABI_COMPAT; + break; + } if (!event->desc) { ret = -EINVAL; goto register_error; @@ -824,8 +852,7 @@ void register_event(struct lttng_event *event) event); break; case LTTNG_KERNEL_SYSCALL: - ret = lttng_syscall_filter_enable(event->chan, - desc->name); + ret = lttng_syscall_filter_enable(event->chan, event); break; case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_UPROBE: @@ -868,8 +895,7 @@ int _lttng_event_unregister(struct lttng_event *event) ret = 0; break; case LTTNG_KERNEL_SYSCALL: - ret = lttng_syscall_filter_disable(event->chan, - desc->name); + ret = lttng_syscall_filter_disable(event->chan, event); break; case LTTNG_KERNEL_NOOP: ret = 0; @@ -1201,39 +1227,87 @@ int lttng_desc_match_enabler(const struct lttng_event_desc *desc, struct lttng_enabler *enabler) { const char *desc_name, *enabler_name; + bool compat = false, entry = false; enabler_name = enabler->event_param.name; switch (enabler->event_param.instrumentation) { case LTTNG_KERNEL_TRACEPOINT: desc_name = desc->name; + switch (enabler->type) { + case LTTNG_ENABLER_STAR_GLOB: + return lttng_match_enabler_star_glob(desc_name, enabler_name); + case LTTNG_ENABLER_NAME: + return lttng_match_enabler_name(desc_name, enabler_name); + default: + return -EINVAL; + } break; case LTTNG_KERNEL_SYSCALL: desc_name = desc->name; - if (!strncmp(desc_name, "compat_", strlen("compat_"))) + if (!strncmp(desc_name, "compat_", strlen("compat_"))) { desc_name += strlen("compat_"); + compat = true; + } if (!strncmp(desc_name, "syscall_exit_", strlen("syscall_exit_"))) { desc_name += strlen("syscall_exit_"); } else if (!strncmp(desc_name, "syscall_entry_", strlen("syscall_entry_"))) { desc_name += strlen("syscall_entry_"); + entry = true; } else { WARN_ON_ONCE(1); return -EINVAL; } + switch (enabler->event_param.u.syscall.entryexit) { + case LTTNG_KERNEL_SYSCALL_ENTRYEXIT: + break; + case LTTNG_KERNEL_SYSCALL_ENTRY: + if (!entry) + return 0; + break; + case LTTNG_KERNEL_SYSCALL_EXIT: + if (entry) + return 0; + break; + default: + return -EINVAL; + } + switch (enabler->event_param.u.syscall.abi) { + case LTTNG_KERNEL_SYSCALL_ABI_ALL: + break; + case LTTNG_KERNEL_SYSCALL_ABI_NATIVE: + if (compat) + return 0; + break; + case LTTNG_KERNEL_SYSCALL_ABI_COMPAT: + if (!compat) + return 0; + break; + default: + return -EINVAL; + } + switch (enabler->event_param.u.syscall.match) { + case LTTNG_SYSCALL_MATCH_NAME: + switch (enabler->type) { + case LTTNG_ENABLER_STAR_GLOB: + return lttng_match_enabler_star_glob(desc_name, enabler_name); + case LTTNG_ENABLER_NAME: + return lttng_match_enabler_name(desc_name, enabler_name); + default: + return -EINVAL; + } + break; + case LTTNG_SYSCALL_MATCH_NR: + return -EINVAL; /* Not implemented. */ + default: + return -EINVAL; + } break; default: WARN_ON_ONCE(1); return -EINVAL; } - switch (enabler->type) { - case LTTNG_ENABLER_STAR_GLOB: - return lttng_match_enabler_star_glob(desc_name, enabler_name); - case LTTNG_ENABLER_NAME: - return lttng_match_enabler_name(desc_name, enabler_name); - default: - return -EINVAL; - } } static @@ -1359,9 +1433,21 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler) static int lttng_enabler_ref_events(struct lttng_enabler *enabler) { - struct lttng_session *session = enabler->chan->session; + struct lttng_channel *chan = enabler->chan; + struct lttng_session *session = chan->session; struct lttng_event *event; + if (enabler->event_param.instrumentation == LTTNG_KERNEL_SYSCALL && + enabler->event_param.u.syscall.entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT && + enabler->event_param.u.syscall.abi == LTTNG_KERNEL_SYSCALL_ABI_ALL && + enabler->event_param.u.syscall.match == LTTNG_SYSCALL_MATCH_NAME && + !strcmp(enabler->event_param.name, "*")) { + if (enabler->enabled) + WRITE_ONCE(chan->syscall_all, 1); + else + WRITE_ONCE(chan->syscall_all, 0); + } + /* First ensure that probe events are created for this enabler. */ lttng_create_event_if_missing(enabler); @@ -1622,7 +1708,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; @@ -1661,6 +1747,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, @@ -1668,18 +1755,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, ...) @@ -1687,9 +1802,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); @@ -1698,7 +1812,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; @@ -1724,16 +1838,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; } @@ -2270,6 +2379,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, @@ -2278,11 +2389,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" @@ -2332,12 +2445,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, @@ -2345,12 +2461,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" @@ -2384,6 +2502,7 @@ int _lttng_channel_metadata_statedump(struct lttng_session *session, chan->metadata_dumped = 1; end: + lttng_metadata_end(session); return ret; } @@ -2569,8 +2688,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; @@ -2743,6 +2865,7 @@ skip_session: } session->metadata_dumped = 1; end: + lttng_metadata_end(session); return ret; }