X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=src%2Flttng-events.c;h=9f683db18f2274badbaeb37288d4843fc7c246e0;hb=99f52fcce5865809584c1e022bca1409702ea292;hp=75a193045b1d381a3bf531542e763d741b095d8a;hpb=99d223adfae9b68800e91bda470c92acb14efae6;p=lttng-modules.git diff --git a/src/lttng-events.c b/src/lttng-events.c index 75a19304..9f683db1 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -52,6 +52,7 @@ static LIST_HEAD(sessions); static LIST_HEAD(event_notifier_groups); static LIST_HEAD(lttng_transport_list); +static LIST_HEAD(lttng_counter_transport_list); /* * Protect the sessions and metadata caches. */ @@ -197,6 +198,61 @@ err: return NULL; } +static +struct lttng_counter_transport *lttng_counter_transport_find(const char *name) +{ + struct lttng_counter_transport *transport; + + list_for_each_entry(transport, <tng_counter_transport_list, node) { + if (!strcmp(transport->name, name)) + return transport; + } + return NULL; +} + +struct lttng_counter *lttng_kernel_counter_create( + const char *counter_transport_name, + size_t number_dimensions, const size_t *dimensions_sizes) +{ + struct lttng_counter *counter = NULL; + struct lttng_counter_transport *counter_transport = NULL; + + counter_transport = lttng_counter_transport_find(counter_transport_name); + if (!counter_transport) { + printk(KERN_WARNING "LTTng: counter transport %s not found.\n", + counter_transport_name); + goto notransport; + } + if (!try_module_get(counter_transport->owner)) { + printk(KERN_WARNING "LTTng: Can't lock counter transport module.\n"); + goto notransport; + } + + counter = lttng_kvzalloc(sizeof(struct lttng_counter), GFP_KERNEL); + if (!counter) + goto nomem; + + /* Create event notifier error counter. */ + counter->ops = &counter_transport->ops; + counter->transport = counter_transport; + + counter->counter = counter->ops->counter_create( + number_dimensions, dimensions_sizes, 0); + if (!counter->counter) { + goto create_error; + } + + return counter; + +create_error: + lttng_kvfree(counter); +nomem: + if (counter_transport) + module_put(counter_transport->owner); +notransport: + return NULL; +} + struct lttng_event_notifier_group *lttng_event_notifier_group_create(void) { struct lttng_transport *transport = NULL; @@ -354,6 +410,14 @@ void lttng_event_notifier_group_destroy( &event_notifier_group->event_notifiers_head, list) _lttng_event_notifier_destroy(event_notifier); + if (event_notifier_group->error_counter) { + struct lttng_counter *error_counter = event_notifier_group->error_counter; + error_counter->ops->counter_destroy(error_counter->counter); + module_put(error_counter->transport->owner); + lttng_kvfree(error_counter); + event_notifier_group->error_counter = NULL; + } + event_notifier_group->ops->channel_destroy(event_notifier_group->chan); module_put(event_notifier_group->transport->owner); list_del(&event_notifier_group->node); @@ -759,6 +823,7 @@ void _lttng_metadata_channel_hangup(struct lttng_metadata_stream *stream) wake_up_interruptible(&stream->read_wait); } + /* * Supports event creation while tracing session is active. * Needs to be called with sessions mutex held. @@ -1000,7 +1065,8 @@ full: struct lttng_event_notifier *_lttng_event_notifier_create( const struct lttng_event_desc *event_desc, - uint64_t token, struct lttng_event_notifier_group *event_notifier_group, + uint64_t token, uint64_t error_counter_index, + struct lttng_event_notifier_group *event_notifier_group, struct lttng_kernel_event_notifier *event_notifier_param, void *filter, enum lttng_kernel_instrumentation itype) { @@ -1048,6 +1114,7 @@ struct lttng_event_notifier *_lttng_event_notifier_create( event_notifier->group = event_notifier_group; event_notifier->user_token = token; + event_notifier->error_counter_index = error_counter_index; event_notifier->num_captures = 0; event_notifier->filter = filter; event_notifier->instrumentation = itype; @@ -1164,6 +1231,35 @@ struct lttng_event_notifier *_lttng_event_notifier_create( list_add(&event_notifier->list, &event_notifier_group->event_notifiers_head); hlist_add_head(&event_notifier->hlist, head); + + /* + * Clear the error counter bucket. The sessiond keeps track of which + * bucket is currently in use. We trust it. + */ + if (event_notifier_group->error_counter) { + size_t dimension_index[1]; + + /* + * Check that the index is within the boundary of the counter. + */ + if (event_notifier->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->error_counter_index); + ret = -EINVAL; + goto register_error; + } + + dimension_index[0] = event_notifier->error_counter_index; + ret = event_notifier_group->error_counter->ops->counter_clear( + event_notifier_group->error_counter->counter, + dimension_index); + if (ret) { + printk(KERN_INFO "LTTng: event_notifier: Unable to clear error counter bucket %llu\n", + event_notifier->error_counter_index); + goto register_error; + } + } + return event_notifier; register_error: @@ -1174,6 +1270,28 @@ type_error: return ERR_PTR(ret); } +int lttng_kernel_counter_read(struct lttng_counter *counter, + const size_t *dim_indexes, int32_t cpu, + int64_t *val, bool *overflow, bool *underflow) +{ + return counter->ops->counter_read(counter->counter, dim_indexes, + cpu, val, overflow, underflow); +} + +int lttng_kernel_counter_aggregate(struct lttng_counter *counter, + const size_t *dim_indexes, int64_t *val, + bool *overflow, bool *underflow) +{ + return counter->ops->counter_aggregate(counter->counter, dim_indexes, + val, overflow, underflow); +} + +int lttng_kernel_counter_clear(struct lttng_counter *counter, + const size_t *dim_indexes) +{ + return counter->ops->counter_clear(counter->counter, dim_indexes); +} + struct lttng_event *lttng_event_create(struct lttng_channel *chan, struct lttng_kernel_event *event_param, void *filter, @@ -1191,7 +1309,8 @@ struct lttng_event *lttng_event_create(struct lttng_channel *chan, struct lttng_event_notifier *lttng_event_notifier_create( const struct lttng_event_desc *event_desc, - uint64_t id, struct lttng_event_notifier_group *event_notifier_group, + uint64_t id, uint64_t error_counter_index, + struct lttng_event_notifier_group *event_notifier_group, struct lttng_kernel_event_notifier *event_notifier_param, void *filter, enum lttng_kernel_instrumentation itype) { @@ -1199,7 +1318,8 @@ struct lttng_event_notifier *lttng_event_notifier_create( mutex_lock(&sessions_mutex); event_notifier = _lttng_event_notifier_create(event_desc, id, - event_notifier_group, event_notifier_param, filter, itype); + error_counter_index, event_notifier_group, + event_notifier_param, filter, itype); mutex_unlock(&sessions_mutex); return event_notifier; } @@ -1929,6 +2049,7 @@ void lttng_create_tracepoint_event_notifier_if_missing(struct lttng_event_notifi */ event_notifier = _lttng_event_notifier_create(desc, event_notifier_enabler->base.user_token, + event_notifier_enabler->error_counter_index, event_notifier_group, NULL, NULL, LTTNG_KERNEL_TRACEPOINT); if (IS_ERR(event_notifier)) { @@ -2329,6 +2450,7 @@ struct lttng_event_notifier_enabler *lttng_event_notifier_enabler_create( INIT_LIST_HEAD(&event_notifier_enabler->base.filter_bytecode_head); INIT_LIST_HEAD(&event_notifier_enabler->capture_bytecode_head); + event_notifier_enabler->error_counter_index = event_notifier_param->error_counter_index; event_notifier_enabler->num_captures = 0; memcpy(&event_notifier_enabler->base.event_param, &event_notifier_param->event, @@ -3878,6 +4000,29 @@ void lttng_transport_unregister(struct lttng_transport *transport) } EXPORT_SYMBOL_GPL(lttng_transport_unregister); +void lttng_counter_transport_register(struct lttng_counter_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_mappings() in each module's init. + */ + wrapper_vmalloc_sync_mappings(); + + mutex_lock(&sessions_mutex); + list_add_tail(&transport->node, <tng_counter_transport_list); + mutex_unlock(&sessions_mutex); +} +EXPORT_SYMBOL_GPL(lttng_counter_transport_register); + +void lttng_counter_transport_unregister(struct lttng_counter_transport *transport) +{ + mutex_lock(&sessions_mutex); + list_del(&transport->node); + mutex_unlock(&sessions_mutex); +} +EXPORT_SYMBOL_GPL(lttng_counter_transport_unregister); + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) enum cpuhp_state lttng_hp_prepare;