X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Flttng-events.c;h=981ee30c326cb65be35ff7b6d107d600e09633a4;hb=c4e310594ea3bd6d5110bcda972c0920e95a6eaf;hp=ad5faa98cfc0add560fdf10eab4dc54473e9b91f;hpb=0d223dc61b7f4ffcbe4ca49a000029f09f0afd08;p=lttng-modules.git diff --git a/src/lttng-events.c b/src/lttng-events.c index ad5faa98..981ee30c 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -73,9 +73,7 @@ static void _lttng_event_destroy(struct lttng_kernel_event_common *event); static void _lttng_channel_destroy(struct lttng_kernel_channel_buffer *chan); static int _lttng_event_unregister(struct lttng_kernel_event_common *event); static -int _lttng_event_metadata_statedump(struct lttng_kernel_session *session, - struct lttng_kernel_channel_buffer *chan, - struct lttng_kernel_event_recorder *event); +int _lttng_event_recorder_metadata_statedump(struct lttng_kernel_event_common *event); static int _lttng_session_metadata_statedump(struct lttng_kernel_session *session); static @@ -866,6 +864,48 @@ void _lttng_metadata_channel_hangup(struct lttng_metadata_stream *stream) wake_up_interruptible(&stream->read_wait); } +static +bool lttng_kernel_event_id_available(struct lttng_event_enabler_common *event_enabler) +{ + struct lttng_kernel_abi_event *event_param = &event_enabler->event_param; + enum lttng_kernel_abi_instrumentation itype = event_param->instrumentation; + + switch (event_enabler->enabler_type) { + case LTTNG_EVENT_ENABLER_TYPE_RECORDER: + { + struct lttng_event_recorder_enabler *event_recorder_enabler = + container_of(event_enabler, struct lttng_event_recorder_enabler, parent); + struct lttng_kernel_channel_buffer *chan = event_recorder_enabler->chan; + + switch (itype) { + case LTTNG_KERNEL_ABI_TRACEPOINT: + lttng_fallthrough; + case LTTNG_KERNEL_ABI_KPROBE: + lttng_fallthrough; + case LTTNG_KERNEL_ABI_SYSCALL: + lttng_fallthrough; + case LTTNG_KERNEL_ABI_UPROBE: + if (chan->priv->free_event_id == -1U) + return false; + return true; + case LTTNG_KERNEL_ABI_KRETPROBE: + /* kretprobes require 2 event IDs. */ + if (chan->priv->free_event_id >= -2U) + return false; + return true; + default: + WARN_ON_ONCE(1); + return false; + } + } + case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER: + return true; + default: + WARN_ON_ONCE(1); + return false; + } +} + static struct lttng_kernel_event_common *lttng_kernel_event_alloc(struct lttng_event_enabler_common *event_enabler) { @@ -970,6 +1010,53 @@ void lttng_kernel_event_free(struct lttng_kernel_event_common *event) } } +static +int lttng_kernel_event_notifier_clear_error_counter(struct lttng_kernel_event_common *event) +{ + switch (event->type) { + case LTTNG_KERNEL_EVENT_TYPE_RECORDER: + return 0; + case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: + { + struct lttng_kernel_event_notifier *event_notifier = + container_of(event, struct lttng_kernel_event_notifier, parent); + struct lttng_counter *error_counter; + struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group; + size_t dimension_index[1]; + int ret; + + /* + * Clear the error counter bucket. The sessiond keeps track of which + * bucket is currently in use. We trust it. The session lock + * synchronizes against concurrent creation of the error + * counter. + */ + error_counter = event_notifier_group->error_counter; + if (!error_counter) + return 0; + /* + * Check that the index is within the boundary of the counter. + */ + if (event_notifier->priv->error_counter_index >= event_notifier_group->error_counter_len) { + printk(KERN_INFO "LTTng: event_notifier: Error counter index out-of-bound: counter-len=%zu, index=%llu\n", + event_notifier_group->error_counter_len, event_notifier->priv->error_counter_index); + return -EINVAL; + } + + dimension_index[0] = event_notifier->priv->error_counter_index; + ret = error_counter->ops->counter_clear(error_counter->counter, dimension_index); + if (ret) { + printk(KERN_INFO "LTTng: event_notifier: Unable to clear error counter bucket %llu\n", + event_notifier->priv->error_counter_index); + return -EINVAL; + } + return 0; + } + default: + return -EINVAL; + } +} + /* * Supports event creation while tracing session is active. * Needs to be called with sessions mutex held. @@ -979,7 +1066,7 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l const struct lttng_kernel_event_desc *event_desc) { struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(&event_enabler->parent); - struct lttng_kernel_channel_buffer *chan = event_enabler->chan; + struct list_head *event_list_head = lttng_get_event_list_head_from_enabler(&event_enabler->parent); struct lttng_kernel_abi_event *event_param = &event_enabler->parent.event_param; enum lttng_kernel_abi_instrumentation itype = event_param->instrumentation; struct lttng_kernel_event_common_private *event_priv; @@ -989,7 +1076,7 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l struct hlist_head *head; int ret; - if (chan->priv->free_event_id == -1U) { + if (!lttng_kernel_event_id_available(&event_enabler->parent)) { ret = -EMFILE; goto full; } @@ -1076,7 +1163,6 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l case LTTNG_KERNEL_ABI_KRETPROBE: { struct lttng_kernel_event_common *event_return; - struct lttng_kernel_event_recorder *event_recorder_return; /* kretprobe defines 2 events */ /* @@ -1091,7 +1177,6 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l ret = -ENOMEM; goto alloc_error; } - event_recorder_return = container_of(event_return, struct lttng_kernel_event_recorder, parent); event_return->enabled = 0; event_return->priv->registered = 1; @@ -1115,7 +1200,7 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l WARN_ON_ONCE(!ret); ret = try_module_get(event_return->priv->desc->owner); WARN_ON_ONCE(!ret); - ret = _lttng_event_metadata_statedump(chan->parent.session, chan, event_recorder_return); + ret = _lttng_event_recorder_metadata_statedump(event_return); WARN_ON_ONCE(ret > 0); if (ret) { lttng_kernel_event_free(event_return); @@ -1123,7 +1208,7 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l module_put(event->priv->desc->owner); goto statedump_error; } - list_add(&event_return->priv->node, &chan->parent.session->priv->events); + list_add(&event_return->priv->node, event_list_head); break; } @@ -1195,13 +1280,13 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l ret = -EINVAL; goto register_error; } - ret = _lttng_event_metadata_statedump(chan->parent.session, chan, event_recorder); + ret = _lttng_event_recorder_metadata_statedump(event); WARN_ON_ONCE(ret > 0); if (ret) { goto statedump_error; } hlist_add_head(&event->priv->hlist_node, head); - list_add(&event->priv->node, &chan->parent.session->priv->events); + list_add(&event->priv->node, event_list_head); return event_recorder; statedump_error: @@ -1220,13 +1305,12 @@ struct lttng_kernel_event_notifier *_lttng_kernel_event_notifier_create(struct l const struct lttng_kernel_event_desc *event_desc) { struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(&event_enabler->parent); - struct lttng_event_notifier_group *event_notifier_group = event_enabler->group; + struct list_head *event_list_head = lttng_get_event_list_head_from_enabler(&event_enabler->parent); struct lttng_kernel_abi_event *event_param = &event_enabler->parent.event_param; enum lttng_kernel_abi_instrumentation itype = event_param->instrumentation; struct lttng_kernel_event_common_private *event_priv; struct lttng_kernel_event_common *event; struct lttng_kernel_event_notifier *event_notifier; - struct lttng_counter *error_counter; const char *event_name; struct hlist_head *head; int ret; @@ -1382,37 +1466,12 @@ struct lttng_kernel_event_notifier *_lttng_kernel_event_notifier_create(struct l goto register_error; } - list_add(&event->priv->node, &event_notifier_group->event_notifiers_head); - hlist_add_head(&event->priv->hlist_node, head); - - /* - * Clear the error counter bucket. The sessiond keeps track of which - * bucket is currently in use. We trust it. The session lock - * synchronizes against concurrent creation of the error - * counter. - */ - error_counter = event_notifier_group->error_counter; - if (error_counter) { - size_t dimension_index[1]; - - /* - * Check that the index is within the boundary of the counter. - */ - if (event_notifier->priv->error_counter_index >= event_notifier_group->error_counter_len) { - printk(KERN_INFO "LTTng: event_notifier: Error counter index out-of-bound: counter-len=%zu, index=%llu\n", - event_notifier_group->error_counter_len, event_notifier->priv->error_counter_index); - ret = -EINVAL; - goto register_error; - } + ret = lttng_kernel_event_notifier_clear_error_counter(event); + if (ret) + goto register_error; - dimension_index[0] = event_notifier->priv->error_counter_index; - ret = error_counter->ops->counter_clear(error_counter->counter, dimension_index); - if (ret) { - printk(KERN_INFO "LTTng: event_notifier: Unable to clear error counter bucket %llu\n", - event_notifier->priv->error_counter_index); - goto register_error; - } - } + list_add(&event->priv->node, event_list_head); + hlist_add_head(&event->priv->hlist_node, head); return event_notifier; @@ -3643,12 +3702,19 @@ int _lttng_fields_metadata_statedump(struct lttng_kernel_session *session, * transaction. */ static -int _lttng_event_metadata_statedump(struct lttng_kernel_session *session, - struct lttng_kernel_channel_buffer *chan, - struct lttng_kernel_event_recorder *event_recorder) +int _lttng_event_recorder_metadata_statedump(struct lttng_kernel_event_common *event) { + struct lttng_kernel_event_recorder *event_recorder; + struct lttng_kernel_channel_buffer *chan; + struct lttng_kernel_session *session; int ret = 0; + if (event->type != LTTNG_KERNEL_EVENT_TYPE_RECORDER) + return 0; + event_recorder = container_of(event, struct lttng_kernel_event_recorder, parent); + chan = event_recorder->chan; + session = chan->parent.session; + if (event_recorder->priv->metadata_dumped || !LTTNG_READ_ONCE(session->active)) return 0; if (chan->priv->channel_type == METADATA_CHANNEL) @@ -4103,8 +4169,7 @@ skip_session: } list_for_each_entry(event_recorder_priv, &session->priv->events, parent.node) { - ret = _lttng_event_metadata_statedump(session, event_recorder_priv->pub->chan, - event_recorder_priv->pub); + ret = _lttng_event_recorder_metadata_statedump(&event_recorder_priv->pub->parent); if (ret) goto end; }