X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Flttng-events.c;h=4cb0f037e174e8aea12dfca0d2cb6a47368d2a1e;hb=e978f27486ddac0b9cbea5577fc413c67bc61141;hp=3000e856f56e9634cf985e84afe9db2c2fb7a1d1;hpb=a67ba386d82d85c6b6ca56c249a13ab5a1f34b08;p=lttng-modules.git diff --git a/src/lttng-events.c b/src/lttng-events.c index 3000e856..4cb0f037 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -69,8 +69,7 @@ static void lttng_event_enabler_destroy(struct lttng_event_enabler *event_enable static void lttng_event_notifier_enabler_destroy(struct lttng_event_notifier_enabler *event_notifier_enabler); static void lttng_event_notifier_group_sync_enablers(struct lttng_event_notifier_group *event_notifier_group); -static void _lttng_event_destroy(struct lttng_kernel_event_recorder *event); -static void _lttng_event_notifier_destroy(struct lttng_kernel_event_notifier *event_notifier); +static void _lttng_event_destroy(struct lttng_kernel_event_common *event); static void _lttng_channel_destroy(struct lttng_channel *chan); static int _lttng_event_unregister(struct lttng_kernel_event_recorder *event); static int _lttng_event_notifier_unregister(struct lttng_kernel_event_notifier *event_notifier); @@ -90,7 +89,7 @@ int _lttng_type_statedump(struct lttng_session *session, static int _lttng_field_statedump(struct lttng_session *session, const struct lttng_kernel_event_field *field, - size_t nesting); + size_t nesting, const char **prev_field_name_p); void synchronize_trace(void) { @@ -357,7 +356,7 @@ void lttng_session_destroy(struct lttng_session *session) &session->enablers_head, node) lttng_event_enabler_destroy(event_enabler); list_for_each_entry_safe(event_recorder_priv, tmpevent_recorder_priv, &session->events, node) - _lttng_event_destroy(event_recorder_priv->pub); + _lttng_event_destroy(&event_recorder_priv->pub->parent); list_for_each_entry_safe(chan, tmpchan, &session->chan, list) { BUG_ON(chan->channel_type == METADATA_CHANNEL); _lttng_channel_destroy(chan); @@ -412,7 +411,7 @@ void lttng_event_notifier_group_destroy( list_for_each_entry_safe(event_notifier_priv, tmpevent_notifier_priv, &event_notifier_group->event_notifiers_head, node) - _lttng_event_notifier_destroy(event_notifier_priv->pub); + _lttng_event_destroy(&event_notifier_priv->pub->parent); if (event_notifier_group->error_counter) { struct lttng_counter *error_counter = event_notifier_group->error_counter; @@ -604,57 +603,37 @@ end: return ret; } -int lttng_event_enable(struct lttng_kernel_event_recorder *event_recorder) +int lttng_event_enable(struct lttng_kernel_event_common *event) { - struct lttng_kernel_event_common *event = &event_recorder->parent; int ret = 0; mutex_lock(&sessions_mutex); - if (event_recorder->chan->channel_type == METADATA_CHANNEL) { - ret = -EPERM; - goto end; - } - if (event->enabled) { - ret = -EEXIST; - goto end; - } - switch (event->priv->instrumentation) { - case LTTNG_KERNEL_ABI_TRACEPOINT: /* Fall-through */ - case LTTNG_KERNEL_ABI_SYSCALL: - ret = -EINVAL; - break; + switch (event->type) { + case LTTNG_KERNEL_EVENT_TYPE_RECORDER: + { + struct lttng_kernel_event_recorder *event_recorder = + container_of(event, struct lttng_kernel_event_recorder, parent); - case LTTNG_KERNEL_ABI_KPROBE: /* Fall-through */ - case LTTNG_KERNEL_ABI_UPROBE: - WRITE_ONCE(event->enabled, 1); + if (event_recorder->chan->channel_type == METADATA_CHANNEL) { + ret = -EPERM; + goto end; + } break; - - case LTTNG_KERNEL_ABI_KRETPROBE: - ret = lttng_kretprobes_event_enable_state(event_recorder, 1); + } + case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: + switch (event->priv->instrumentation) { + case LTTNG_KERNEL_ABI_KRETPROBE: + ret = -EINVAL; + goto end; + default: + break; + } break; - - case LTTNG_KERNEL_ABI_FUNCTION: /* Fall-through */ - case LTTNG_KERNEL_ABI_NOOP: /* Fall-through */ default: - WARN_ON_ONCE(1); - ret = -EINVAL; + break; } -end: - mutex_unlock(&sessions_mutex); - return ret; -} - -int lttng_event_disable(struct lttng_kernel_event_recorder *event_recorder) -{ - struct lttng_kernel_event_common *event = &event_recorder->parent; - int ret = 0; - mutex_lock(&sessions_mutex); - if (event_recorder->chan->channel_type == METADATA_CHANNEL) { - ret = -EPERM; - goto end; - } - if (!event->enabled) { + if (event->enabled) { ret = -EEXIST; goto end; } @@ -666,12 +645,11 @@ int lttng_event_disable(struct lttng_kernel_event_recorder *event_recorder) case LTTNG_KERNEL_ABI_KPROBE: /* Fall-through */ case LTTNG_KERNEL_ABI_UPROBE: - WRITE_ONCE(event->enabled, 0); + WRITE_ONCE(event->enabled, 1); break; case LTTNG_KERNEL_ABI_KRETPROBE: - - ret = lttng_kretprobes_event_enable_state(event_recorder, 0); + ret = lttng_kretprobes_event_enable_state(event, 1); break; case LTTNG_KERNEL_ABI_FUNCTION: /* Fall-through */ @@ -685,45 +663,36 @@ end: return ret; } -int lttng_event_notifier_enable(struct lttng_kernel_event_notifier *event_notifier) +int lttng_event_disable(struct lttng_kernel_event_common *event) { - struct lttng_kernel_event_common *event = &event_notifier->parent; int ret = 0; mutex_lock(&sessions_mutex); - if (event->enabled) { - ret = -EEXIST; - goto end; - } - switch (event->priv->instrumentation) { - case LTTNG_KERNEL_ABI_TRACEPOINT: /* Fall-through */ - case LTTNG_KERNEL_ABI_SYSCALL: - ret = -EINVAL; - break; + switch (event->type) { + case LTTNG_KERNEL_EVENT_TYPE_RECORDER: + { + struct lttng_kernel_event_recorder *event_recorder = + container_of(event, struct lttng_kernel_event_recorder, parent); - case LTTNG_KERNEL_ABI_KPROBE: /* Fall-through */ - case LTTNG_KERNEL_ABI_UPROBE: - WRITE_ONCE(event->enabled, 1); + if (event_recorder->chan->channel_type == METADATA_CHANNEL) { + ret = -EPERM; + goto end; + } + break; + } + case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: + switch (event->priv->instrumentation) { + case LTTNG_KERNEL_ABI_KRETPROBE: + ret = -EINVAL; + goto end; + default: + break; + } break; - - case LTTNG_KERNEL_ABI_FUNCTION: /* Fall-through */ - case LTTNG_KERNEL_ABI_KRETPROBE: /* Fall-through */ - case LTTNG_KERNEL_ABI_NOOP: /* Fall-through */ default: - WARN_ON_ONCE(1); - ret = -EINVAL; + break; } -end: - mutex_unlock(&sessions_mutex); - return ret; -} -int lttng_event_notifier_disable(struct lttng_kernel_event_notifier *event_notifier) -{ - struct lttng_kernel_event_common *event = &event_notifier->parent; - int ret = 0; - - mutex_lock(&sessions_mutex); if (!event->enabled) { ret = -EEXIST; goto end; @@ -739,8 +708,11 @@ int lttng_event_notifier_disable(struct lttng_kernel_event_notifier *event_notif WRITE_ONCE(event->enabled, 0); break; + case LTTNG_KERNEL_ABI_KRETPROBE: + ret = lttng_kretprobes_event_enable_state(event, 0); + break; + case LTTNG_KERNEL_ABI_FUNCTION: /* Fall-through */ - case LTTNG_KERNEL_ABI_KRETPROBE: /* Fall-through */ case LTTNG_KERNEL_ABI_NOOP: /* Fall-through */ default: WARN_ON_ONCE(1); @@ -913,6 +885,7 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l event_recorder->parent.priv = &event_recorder_priv->parent; event_recorder->parent.type = LTTNG_KERNEL_EVENT_TYPE_RECORDER; + event_recorder->parent.run_filter = lttng_kernel_interpret_event_filter; event_recorder->chan = chan; event_recorder->priv->id = chan->free_event_id++; event_recorder->priv->parent.instrumentation = itype; @@ -988,6 +961,7 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l event_recorder_return->parent.priv = &event_recorder_return_priv->parent; event_recorder_return->parent.type = LTTNG_KERNEL_EVENT_TYPE_RECORDER; + event_recorder_return->parent.run_filter = lttng_kernel_interpret_event_filter; event_recorder_return->chan = chan; event_recorder_return->priv->id = chan->free_event_id++; event_recorder_return->priv->parent.instrumentation = itype; @@ -1189,6 +1163,7 @@ struct lttng_kernel_event_notifier *_lttng_event_notifier_create( INIT_LIST_HEAD(&event_notifier->priv->parent.filter_bytecode_runtime_head); INIT_LIST_HEAD(&event_notifier->priv->parent.enablers_ref_head); INIT_LIST_HEAD(&event_notifier->priv->capture_bytecode_runtime_head); + event_notifier->parent.run_filter = lttng_kernel_interpret_event_filter; switch (itype) { case LTTNG_KERNEL_ABI_TRACEPOINT: @@ -1498,7 +1473,7 @@ void register_event_notifier(struct lttng_kernel_event_notifier *event_notifier) switch (event_notifier->priv->parent.instrumentation) { case LTTNG_KERNEL_ABI_TRACEPOINT: ret = lttng_wrapper_tracepoint_probe_register(desc->event_kname, - desc->event_notifier_callback, + desc->probe_callback, event_notifier); break; @@ -1535,7 +1510,7 @@ int _lttng_event_notifier_unregister( switch (event_notifier->priv->parent.instrumentation) { case LTTNG_KERNEL_ABI_TRACEPOINT: ret = lttng_wrapper_tracepoint_probe_unregister(event_notifier->priv->parent.desc->event_kname, - event_notifier->priv->parent.desc->event_notifier_callback, + event_notifier->priv->parent.desc->probe_callback, event_notifier); break; @@ -1568,89 +1543,93 @@ int _lttng_event_notifier_unregister( * Only used internally at session destruction. */ static -void _lttng_event_destroy(struct lttng_kernel_event_recorder *event_recorder) +void _lttng_event_destroy(struct lttng_kernel_event_common *event) { - struct lttng_kernel_event_common_private *event_priv = &event_recorder->priv->parent; + struct lttng_kernel_event_common_private *event_priv = event->priv; struct lttng_enabler_ref *enabler_ref, *tmp_enabler_ref; - switch (event_priv->instrumentation) { - case LTTNG_KERNEL_ABI_TRACEPOINT: - lttng_event_desc_put(event_priv->desc); - break; + lttng_free_event_filter_runtime(event); + /* Free event enabler refs */ + list_for_each_entry_safe(enabler_ref, tmp_enabler_ref, + &event_priv->enablers_ref_head, node) + kfree(enabler_ref); - case LTTNG_KERNEL_ABI_KPROBE: - module_put(event_priv->desc->owner); - lttng_kprobes_destroy_event_private(event_recorder); - break; + switch (event->type) { + case LTTNG_KERNEL_EVENT_TYPE_RECORDER: + { + struct lttng_kernel_event_recorder *event_recorder = + container_of(event, struct lttng_kernel_event_recorder, parent); - case LTTNG_KERNEL_ABI_KRETPROBE: - module_put(event_priv->desc->owner); - lttng_kretprobes_destroy_private(event_recorder); - break; + switch (event_priv->instrumentation) { + case LTTNG_KERNEL_ABI_TRACEPOINT: + lttng_event_desc_put(event_priv->desc); + break; - case LTTNG_KERNEL_ABI_SYSCALL: - break; + case LTTNG_KERNEL_ABI_KPROBE: + module_put(event_priv->desc->owner); + lttng_kprobes_destroy_event_private(event_recorder); + break; - case LTTNG_KERNEL_ABI_UPROBE: - module_put(event_priv->desc->owner); - lttng_uprobes_destroy_event_private(event_recorder); - break; + case LTTNG_KERNEL_ABI_KRETPROBE: + module_put(event_priv->desc->owner); + lttng_kretprobes_destroy_private(event_recorder); + break; - case LTTNG_KERNEL_ABI_FUNCTION: /* Fall-through */ - case LTTNG_KERNEL_ABI_NOOP: /* Fall-through */ - default: - WARN_ON_ONCE(1); - } - list_del(&event_recorder->priv->node); - lttng_free_event_filter_runtime(event_recorder); - /* Free event enabler refs */ - list_for_each_entry_safe(enabler_ref, tmp_enabler_ref, - &event_priv->enablers_ref_head, node) - kfree(enabler_ref); - kmem_cache_free(event_recorder_private_cache, event_recorder->priv); - kmem_cache_free(event_recorder_cache, event_recorder); -} + case LTTNG_KERNEL_ABI_SYSCALL: + break; -/* - * Only used internally at session destruction. - */ -static -void _lttng_event_notifier_destroy(struct lttng_kernel_event_notifier *event_notifier) -{ - struct lttng_enabler_ref *enabler_ref, *tmp_enabler_ref; + case LTTNG_KERNEL_ABI_UPROBE: + module_put(event_priv->desc->owner); + lttng_uprobes_destroy_event_private(event_recorder); + break; - switch (event_notifier->priv->parent.instrumentation) { - case LTTNG_KERNEL_ABI_TRACEPOINT: - lttng_event_desc_put(event_notifier->priv->parent.desc); + case LTTNG_KERNEL_ABI_FUNCTION: /* Fall-through */ + case LTTNG_KERNEL_ABI_NOOP: /* Fall-through */ + default: + WARN_ON_ONCE(1); + } + list_del(&event_recorder->priv->node); + kmem_cache_free(event_recorder_private_cache, event_recorder->priv); + kmem_cache_free(event_recorder_cache, event_recorder); break; + } + case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: + { + struct lttng_kernel_event_notifier *event_notifier = + container_of(event, struct lttng_kernel_event_notifier, parent); - case LTTNG_KERNEL_ABI_KPROBE: - module_put(event_notifier->priv->parent.desc->owner); - lttng_kprobes_destroy_event_notifier_private(event_notifier); - break; + switch (event_notifier->priv->parent.instrumentation) { + case LTTNG_KERNEL_ABI_TRACEPOINT: + lttng_event_desc_put(event_notifier->priv->parent.desc); + break; - case LTTNG_KERNEL_ABI_SYSCALL: - break; + case LTTNG_KERNEL_ABI_KPROBE: + module_put(event_notifier->priv->parent.desc->owner); + lttng_kprobes_destroy_event_notifier_private(event_notifier); + break; - case LTTNG_KERNEL_ABI_UPROBE: - module_put(event_notifier->priv->parent.desc->owner); - lttng_uprobes_destroy_event_notifier_private(event_notifier); - break; + case LTTNG_KERNEL_ABI_SYSCALL: + break; - case LTTNG_KERNEL_ABI_KRETPROBE: /* Fall-through */ - case LTTNG_KERNEL_ABI_FUNCTION: /* Fall-through */ - case LTTNG_KERNEL_ABI_NOOP: /* Fall-through */ + case LTTNG_KERNEL_ABI_UPROBE: + module_put(event_notifier->priv->parent.desc->owner); + lttng_uprobes_destroy_event_notifier_private(event_notifier); + break; + + case LTTNG_KERNEL_ABI_KRETPROBE: /* Fall-through */ + case LTTNG_KERNEL_ABI_FUNCTION: /* Fall-through */ + case LTTNG_KERNEL_ABI_NOOP: /* Fall-through */ + default: + WARN_ON_ONCE(1); + } + list_del(&event_notifier->priv->node); + kmem_cache_free(event_notifier_private_cache, event_notifier->priv); + kmem_cache_free(event_notifier_cache, event_notifier); + break; + } default: WARN_ON_ONCE(1); } - list_del(&event_notifier->priv->node); - lttng_free_event_notifier_filter_runtime(event_notifier); - /* Free event enabler refs */ - list_for_each_entry_safe(enabler_ref, tmp_enabler_ref, - &event_notifier->priv->parent.enablers_ref_head, node) - kfree(enabler_ref); - kmem_cache_free(event_notifier_private_cache, event_notifier->priv); - kmem_cache_free(event_notifier_cache, event_notifier); } struct lttng_id_tracker *get_tracker(struct lttng_session *session, @@ -2470,7 +2449,7 @@ static int lttng_enabler_attach_filter_bytecode(struct lttng_enabler *enabler, struct lttng_kernel_abi_filter_bytecode __user *bytecode) { - struct lttng_bytecode_node *bytecode_node; + struct lttng_kernel_bytecode_node *bytecode_node; uint32_t bytecode_len; int ret; @@ -2486,7 +2465,7 @@ int lttng_enabler_attach_filter_bytecode(struct lttng_enabler *enabler, if (ret) goto error_free; - bytecode_node->type = LTTNG_BYTECODE_NODE_TYPE_FILTER; + bytecode_node->type = LTTNG_KERNEL_BYTECODE_TYPE_FILTER; bytecode_node->enabler = enabler; /* Enforce length based on allocated size */ bytecode_node->bc.len = bytecode_len; @@ -2515,13 +2494,13 @@ error: return ret; } -int lttng_event_add_callsite(struct lttng_kernel_event_recorder *event_recorder, +int lttng_event_add_callsite(struct lttng_kernel_event_common *event, struct lttng_kernel_abi_event_callsite __user *callsite) { - switch (event_recorder->priv->parent.instrumentation) { + switch (event->priv->instrumentation) { case LTTNG_KERNEL_ABI_UPROBE: - return lttng_uprobes_event_add_callsite(event_recorder, callsite); + return lttng_uprobes_event_add_callsite(event, callsite); default: return -EINVAL; } @@ -2530,7 +2509,7 @@ int lttng_event_add_callsite(struct lttng_kernel_event_recorder *event_recorder, static void lttng_enabler_destroy(struct lttng_enabler *enabler) { - struct lttng_bytecode_node *filter_node, *tmp_filter_node; + struct lttng_kernel_bytecode_node *filter_node, *tmp_filter_node; /* Destroy filter bytecode */ list_for_each_entry_safe(filter_node, tmp_filter_node, @@ -2625,7 +2604,7 @@ int lttng_event_notifier_enabler_attach_capture_bytecode( struct lttng_event_notifier_enabler *event_notifier_enabler, struct lttng_kernel_abi_capture_bytecode __user *bytecode) { - struct lttng_bytecode_node *bytecode_node; + struct lttng_kernel_bytecode_node *bytecode_node; struct lttng_enabler *enabler = lttng_event_notifier_enabler_as_enabler(event_notifier_enabler); uint32_t bytecode_len; @@ -2645,7 +2624,7 @@ int lttng_event_notifier_enabler_attach_capture_bytecode( if (ret) goto error_free; - bytecode_node->type = LTTNG_BYTECODE_NODE_TYPE_CAPTURE; + bytecode_node->type = LTTNG_KERNEL_BYTECODE_TYPE_CAPTURE; bytecode_node->enabler = enabler; /* Enforce length based on allocated size */ @@ -2663,19 +2642,6 @@ end: return ret; } -int lttng_event_notifier_add_callsite(struct lttng_kernel_event_notifier *event_notifier, - struct lttng_kernel_abi_event_callsite __user *callsite) -{ - - switch (event_notifier->priv->parent.instrumentation) { - case LTTNG_KERNEL_ABI_UPROBE: - return lttng_uprobes_event_notifier_add_callsite(event_notifier, - callsite); - default: - return -EINVAL; - } -} - static void lttng_event_notifier_enabler_destroy( struct lttng_event_notifier_enabler *event_notifier_enabler) @@ -2711,8 +2677,9 @@ void lttng_session_sync_event_enablers(struct lttng_session *session) list_for_each_entry(event_recorder_priv, &session->events, node) { struct lttng_kernel_event_recorder *event_recorder = event_recorder_priv->pub; struct lttng_enabler_ref *enabler_ref; - struct lttng_bytecode_runtime *runtime; - int enabled = 0, has_enablers_without_bytecode = 0; + struct lttng_kernel_bytecode_runtime *runtime; + int enabled = 0, has_enablers_without_filter_bytecode = 0; + int nr_filters = 0; switch (event_recorder_priv->parent.instrumentation) { case LTTNG_KERNEL_ABI_TRACEPOINT: /* Fall-through */ @@ -2754,17 +2721,21 @@ void lttng_session_sync_event_enablers(struct lttng_session *session) &event_recorder_priv->parent.enablers_ref_head, node) { if (enabler_ref->ref->enabled && list_empty(&enabler_ref->ref->filter_bytecode_head)) { - has_enablers_without_bytecode = 1; + has_enablers_without_filter_bytecode = 1; break; } } event_recorder_priv->parent.has_enablers_without_filter_bytecode = - has_enablers_without_bytecode; + has_enablers_without_filter_bytecode; /* Enable filters */ list_for_each_entry(runtime, - &event_recorder_priv->parent.filter_bytecode_runtime_head, node) - lttng_bytecode_filter_sync_state(runtime); + &event_recorder_priv->parent.filter_bytecode_runtime_head, node) { + lttng_bytecode_sync_state(runtime); + nr_filters++; + } + WRITE_ONCE(event_recorder_priv->parent.pub->eval_filter, + !(has_enablers_without_filter_bytecode || !nr_filters)); } } @@ -2800,8 +2771,9 @@ void lttng_event_notifier_group_sync_enablers(struct lttng_event_notifier_group list_for_each_entry(event_notifier_priv, &event_notifier_group->event_notifiers_head, node) { struct lttng_kernel_event_notifier *event_notifier = event_notifier_priv->pub; struct lttng_enabler_ref *enabler_ref; - struct lttng_bytecode_runtime *runtime; - int enabled = 0, has_enablers_without_bytecode = 0; + struct lttng_kernel_bytecode_runtime *runtime; + int enabled = 0, has_enablers_without_filter_bytecode = 0; + int nr_filters = 0, nr_captures = 0; switch (event_notifier_priv->parent.instrumentation) { case LTTNG_KERNEL_ABI_TRACEPOINT: /* Fall-through */ @@ -2839,24 +2811,29 @@ void lttng_event_notifier_group_sync_enablers(struct lttng_event_notifier_group &event_notifier_priv->parent.enablers_ref_head, node) { if (enabler_ref->ref->enabled && list_empty(&enabler_ref->ref->filter_bytecode_head)) { - has_enablers_without_bytecode = 1; + has_enablers_without_filter_bytecode = 1; break; } } event_notifier_priv->parent.has_enablers_without_filter_bytecode = - has_enablers_without_bytecode; + has_enablers_without_filter_bytecode; /* Enable filters */ list_for_each_entry(runtime, - &event_notifier_priv->parent.filter_bytecode_runtime_head, node) - lttng_bytecode_filter_sync_state(runtime); + &event_notifier_priv->parent.filter_bytecode_runtime_head, node) { + lttng_bytecode_sync_state(runtime); + nr_filters++; + } + WRITE_ONCE(event_notifier_priv->parent.pub->eval_filter, + !(has_enablers_without_filter_bytecode || !nr_filters)); /* Enable captures */ list_for_each_entry(runtime, - &event_notifier_priv->capture_bytecode_runtime_head, node) - lttng_bytecode_capture_sync_state(runtime); - - WRITE_ONCE(event_notifier->eval_capture, !!event_notifier_priv->num_captures); + &event_notifier_priv->capture_bytecode_runtime_head, node) { + lttng_bytecode_sync_state(runtime); + nr_captures++; + } + WRITE_ONCE(event_notifier->eval_capture, !!nr_captures); } } @@ -2904,12 +2881,12 @@ int lttng_metadata_output_channel(struct lttng_metadata_stream *stream, reserve_len = min_t(size_t, stream->transport->ops.packet_avail_size(chan), len); - lib_ring_buffer_ctx_init(&ctx, chan, NULL, reserve_len, - sizeof(char), -1); + lib_ring_buffer_ctx_init(&ctx, chan, reserve_len, + sizeof(char), NULL); /* * If reservation failed, return an error to the caller. */ - ret = stream->transport->ops.event_reserve(&ctx, 0); + ret = stream->transport->ops.event_reserve(&ctx); if (ret != 0) { printk(KERN_WARNING "LTTng: Metadata event reservation failed\n"); stream->coherent = false; @@ -3075,6 +3052,7 @@ int _lttng_struct_type_statedump(struct lttng_session *session, const struct lttng_kernel_type_struct *type, size_t nesting) { + const char *prev_field_name = NULL; int ret; uint32_t i, nr_fields; unsigned int alignment; @@ -3091,7 +3069,7 @@ int _lttng_struct_type_statedump(struct lttng_session *session, const struct lttng_kernel_event_field *iter_field; iter_field = type->fields[i]; - ret = _lttng_field_statedump(session, iter_field, nesting + 1); + ret = _lttng_field_statedump(session, iter_field, nesting + 1, &prev_field_name); if (ret) return ret; } @@ -3133,11 +3111,18 @@ int _lttng_struct_field_statedump(struct lttng_session *session, static int _lttng_variant_type_statedump(struct lttng_session *session, const struct lttng_kernel_type_variant *type, - size_t nesting) + size_t nesting, + const char *prev_field_name) { + const char *tag_name; int ret; uint32_t i, nr_choices; + tag_name = type->tag_name; + if (!tag_name) + tag_name = prev_field_name; + if (!tag_name) + return -EINVAL; /* * CTF 1.8 does not allow expressing nonzero variant alignment in a nestable way. */ @@ -3148,7 +3133,7 @@ int _lttng_variant_type_statedump(struct lttng_session *session, return ret; ret = lttng_metadata_printf(session, "variant <_%s> {\n", - type->tag_name); + tag_name); if (ret) return ret; nr_choices = type->nr_choices; @@ -3156,7 +3141,7 @@ int _lttng_variant_type_statedump(struct lttng_session *session, const struct lttng_kernel_event_field *iter_field; iter_field = type->choices[i]; - ret = _lttng_field_statedump(session, iter_field, nesting + 1); + ret = _lttng_field_statedump(session, iter_field, nesting + 1, NULL); if (ret) return ret; } @@ -3174,12 +3159,14 @@ int _lttng_variant_type_statedump(struct lttng_session *session, static int _lttng_variant_field_statedump(struct lttng_session *session, const struct lttng_kernel_event_field *field, - size_t nesting) + size_t nesting, + const char *prev_field_name) { int ret; ret = _lttng_variant_type_statedump(session, - lttng_kernel_get_type_variant(field->type), nesting); + lttng_kernel_get_type_variant(field->type), nesting, + prev_field_name); if (ret) return ret; return lttng_field_name_statedump(session, field, nesting); @@ -3242,7 +3229,8 @@ int _lttng_array_field_statedump(struct lttng_session *session, static int _lttng_sequence_field_statedump(struct lttng_session *session, const struct lttng_kernel_event_field *field, - size_t nesting) + size_t nesting, + const char *prev_field_name) { int ret; const char *length_name; @@ -3253,6 +3241,10 @@ int _lttng_sequence_field_statedump(struct lttng_session *session, WARN_ON_ONCE(!sequence_type); length_name = sequence_type->length_name; + if (!length_name) + length_name = prev_field_name; + if (!length_name) + return -EINVAL; if (sequence_type->alignment) { ret = print_tabs(session, nesting); @@ -3287,7 +3279,7 @@ int _lttng_sequence_field_statedump(struct lttng_session *session, ret = lttng_metadata_printf(session, " _%s[ _%s ];\n", field->name, - sequence_type->length_name); + length_name); return ret; } @@ -3510,7 +3502,7 @@ int _lttng_type_statedump(struct lttng_session *session, case lttng_kernel_type_variant: ret = _lttng_variant_type_statedump(session, lttng_kernel_get_type_variant(type), - nesting); + nesting, NULL); break; /* Nested arrays and sequences are not supported yet. */ @@ -3529,10 +3521,14 @@ int _lttng_type_statedump(struct lttng_session *session, static int _lttng_field_statedump(struct lttng_session *session, const struct lttng_kernel_event_field *field, - size_t nesting) + size_t nesting, + const char **prev_field_name_p) { + const char *prev_field_name = NULL; int ret = 0; + if (prev_field_name_p) + prev_field_name = *prev_field_name_p; switch (field->type->type) { case lttng_kernel_type_integer: ret = _lttng_integer_field_statedump(session, field, nesting); @@ -3550,16 +3546,18 @@ int _lttng_field_statedump(struct lttng_session *session, ret = _lttng_array_field_statedump(session, field, nesting); break; case lttng_kernel_type_sequence: - ret = _lttng_sequence_field_statedump(session, field, nesting); + ret = _lttng_sequence_field_statedump(session, field, nesting, prev_field_name); break; case lttng_kernel_type_variant: - ret = _lttng_variant_field_statedump(session, field, nesting); + ret = _lttng_variant_field_statedump(session, field, nesting, prev_field_name); break; default: WARN_ON_ONCE(1); return -EINVAL; } + if (prev_field_name_p) + *prev_field_name_p = field->name; return ret; } @@ -3567,6 +3565,7 @@ static int _lttng_context_metadata_statedump(struct lttng_session *session, struct lttng_kernel_ctx *ctx) { + const char *prev_field_name = NULL; int ret = 0; int i; @@ -3575,7 +3574,7 @@ int _lttng_context_metadata_statedump(struct lttng_session *session, for (i = 0; i < ctx->nr_fields; i++) { const struct lttng_kernel_ctx_field *field = &ctx->fields[i]; - ret = _lttng_field_statedump(session, field->event_field, 2); + ret = _lttng_field_statedump(session, field->event_field, 2, &prev_field_name); if (ret) return ret; } @@ -3586,6 +3585,7 @@ static int _lttng_fields_metadata_statedump(struct lttng_session *session, struct lttng_kernel_event_recorder *event_recorder) { + const char *prev_field_name = NULL; const struct lttng_kernel_event_desc *desc = event_recorder->priv->parent.desc; int ret = 0; int i; @@ -3593,7 +3593,7 @@ int _lttng_fields_metadata_statedump(struct lttng_session *session, for (i = 0; i < desc->nr_fields; i++) { const struct lttng_kernel_event_field *field = desc->fields[i]; - ret = _lttng_field_statedump(session, field, 2); + ret = _lttng_field_statedump(session, field, 2, &prev_field_name); if (ret) return ret; }