X-Git-Url: http://git.lttng.org/?p=lttng-modules.git;a=blobdiff_plain;f=src%2Flttng-events.c;h=9f683db18f2274badbaeb37288d4843fc7c246e0;hp=012f2245a353f4b7c43c689985b30628d65063d1;hb=99f52fcce5865809584c1e022bca1409702ea292;hpb=a101fa100885861be33fab3966db2c5136815724 diff --git a/src/lttng-events.c b/src/lttng-events.c index 012f2245..9f683db1 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -198,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; @@ -355,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); @@ -760,17 +823,6 @@ void _lttng_metadata_channel_hangup(struct lttng_metadata_stream *stream) wake_up_interruptible(&stream->read_wait); } -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; -} /* * Supports event creation while tracing session is active. @@ -1013,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) { @@ -1061,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; @@ -1177,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: @@ -1187,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, @@ -1204,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) { @@ -1212,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; } @@ -1942,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)) { @@ -2342,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,