From: Mathieu Desnoyers Date: Thu, 10 Feb 2022 17:52:54 +0000 (-0500) Subject: Refactor notification error counters X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=76ba9cee90d2091c960ef9768eff5ec90dee26f4;p=lttng-modules.git Refactor notification error counters Signed-off-by: Mathieu Desnoyers Change-Id: I106b6fe85f899297582e131252c591ac5ba7d538 --- diff --git a/include/lttng/events-internal.h b/include/lttng/events-internal.h index 80d81f3a..9a28b197 100644 --- a/include/lttng/events-internal.h +++ b/include/lttng/events-internal.h @@ -233,9 +233,17 @@ struct lttng_kernel_channel_counter_ops_private { void (*counter_destroy)(struct lttng_kernel_channel_counter *counter); int (*counter_add)(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int64_t v); + /* + * counter_read reads a specific cpu's counter if @cpu >= 0, or + * the global aggregation counter if @cpu == -1. + */ int (*counter_read)(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int cpu, int64_t *value, bool *overflow, bool *underflow); + /* + * counter_aggregate returns the total sum of all per-cpu counters and + * the global aggregation counter. + */ int (*counter_aggregate)(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int64_t *value, bool *overflow, bool *underflow); @@ -250,6 +258,11 @@ struct lttng_kernel_channel_counter_private { struct lib_counter *counter; struct lttng_kernel_channel_counter_ops *ops; + /* Owned either by session or event notifier group. */ + + /* Session or event notifier group file owner. */ + struct file *owner; + /* Event notifier group owner. */ struct lttng_event_notifier_group *event_notifier_group; @@ -257,6 +270,7 @@ struct lttng_kernel_channel_counter_private { struct lttng_session *session; struct list_head node; /* Counter list (in session) */ size_t free_index; /* Next index to allocate */ + struct lttng_counter_transport *transport; }; enum lttng_kernel_bytecode_interpreter_ret { @@ -474,34 +488,17 @@ struct lttng_kernel_channel_buffer_ops_private { uint64_t *id); }; -struct lttng_counter_ops { - struct lib_counter *(*counter_create)(size_t nr_dimensions, - const size_t *max_nr_elem, /* for each dimension */ - int64_t global_sum_step); - void (*counter_destroy)(struct lib_counter *counter); - int (*counter_add)(struct lib_counter *counter, const size_t *dimension_indexes, - int64_t v); - /* - * counter_read reads a specific cpu's counter if @cpu >= 0, or - * the global aggregation counter if @cpu == -1. - */ - int (*counter_read)(struct lib_counter *counter, const size_t *dimension_indexes, int cpu, - int64_t *value, bool *overflow, bool *underflow); - /* - * counter_aggregate returns the total sum of all per-cpu counters and - * the global aggregation counter. - */ - int (*counter_aggregate)(struct lib_counter *counter, const size_t *dimension_indexes, - int64_t *value, bool *overflow, bool *underflow); - int (*counter_clear)(struct lib_counter *counter, const size_t *dimension_indexes); +struct lttng_counter_map_descriptor { + uint64_t user_token; + size_t array_index; + char key[LTTNG_KERNEL_ABI_COUNTER_KEY_LEN]; }; -struct lttng_counter { - struct file *file; /* File associated to counter. */ - struct file *owner; - struct lttng_counter_transport *transport; - struct lib_counter *counter; - struct lttng_counter_ops *ops; +struct lttng_counter_map { + struct lttng_counter_map_descriptor *descriptors; + size_t nr_descriptors; + size_t alloc_len; + struct mutex lock; /* counter map lock */ }; #define LTTNG_EVENT_HT_BITS 12 @@ -527,7 +524,7 @@ struct lttng_event_notifier_group { struct lttng_kernel_syscall_table syscall_table; - struct lttng_counter *error_counter; + struct lttng_kernel_channel_counter *error_counter; size_t error_counter_len; }; @@ -542,7 +539,7 @@ struct lttng_counter_transport { char *name; struct module *owner; struct list_head node; - struct lttng_counter_ops ops; + struct lttng_kernel_channel_counter_ops ops; }; struct lttng_kernel_session_private { @@ -1124,16 +1121,19 @@ int lttng_session_metadata_regenerate(struct lttng_kernel_session *session); int lttng_session_statedump(struct lttng_kernel_session *session); void metadata_cache_destroy(struct kref *kref); -struct lttng_counter *lttng_kernel_counter_create( - const char *counter_transport_name, size_t number_dimensions, - const size_t *dimensions_sizes); -int lttng_kernel_counter_read(struct lttng_counter *counter, +struct lttng_kernel_channel_counter *lttng_kernel_counter_create( + const char *counter_transport_name, + size_t number_dimensions, + const struct lttng_counter_dimension *dimensions, + int64_t global_sum_step, + bool coalesce_hits); +int lttng_kernel_counter_read(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int32_t cpu, int64_t *val, bool *overflow, bool *underflow); -int lttng_kernel_counter_aggregate(struct lttng_counter *counter, +int lttng_kernel_counter_aggregate(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int64_t *val, bool *overflow, bool *underflow); -int lttng_kernel_counter_clear(struct lttng_counter *counter, +int lttng_kernel_counter_clear(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes); struct lttng_event_notifier_group *lttng_event_notifier_group_create(void); int lttng_event_notifier_group_create_error_counter( @@ -1221,6 +1221,10 @@ int lttng_calibrate(struct lttng_kernel_abi_calibrate *calibrate); extern const struct file_operations lttng_tracepoint_list_fops; extern const struct file_operations lttng_syscall_list_fops; +struct lttng_kernel_channel_buffer *lttng_kernel_alloc_channel_buffer(void); +struct lttng_kernel_channel_counter *lttng_kernel_alloc_channel_counter(void); +void lttng_kernel_free_channel_common(struct lttng_kernel_channel_common *chan); + #define lttng_kernel_static_ctx_field(_event_field, _get_size, _record, _get_value, _destroy, _priv) \ __LTTNG_COMPOUND_LITERAL(const struct lttng_kernel_ctx_field, { \ .event_field = (_event_field), \ diff --git a/include/lttng/events.h b/include/lttng/events.h index e6bfb412..ba30c2b7 100644 --- a/include/lttng/events.h +++ b/include/lttng/events.h @@ -426,6 +426,7 @@ struct lttng_kernel_channel_buffer_ops { enum lttng_kernel_channel_type { LTTNG_KERNEL_CHANNEL_TYPE_BUFFER = 0, + LTTNG_KERNEL_CHANNEL_TYPE_COUNTER = 1, }; struct lttng_kernel_channel_common_private; diff --git a/src/lttng-abi.c b/src/lttng-abi.c index 36dbddde..93df4a63 100644 --- a/src/lttng-abi.c +++ b/src/lttng-abi.c @@ -613,14 +613,14 @@ int lttng_abi_session_set_creation_time(struct lttng_kernel_session *session, static int lttng_counter_release(struct inode *inode, struct file *file) { - struct lttng_counter *counter = file->private_data; + struct lttng_kernel_channel_counter *counter = file->private_data; if (counter) { /* * Do not destroy the counter itself. Wait of the owner * (event_notifier group) to be destroyed. */ - fput(counter->owner); + fput(counter->priv->owner); } return 0; @@ -629,7 +629,7 @@ int lttng_counter_release(struct inode *inode, struct file *file) static long lttng_counter_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct lttng_counter *counter = file->private_data; + struct lttng_kernel_channel_counter *counter = file->private_data; size_t indexes[LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX] = { 0 }; int i; @@ -652,14 +652,12 @@ long lttng_counter_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EINVAL; if (local_counter_read.index.number_dimensions > LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX) return -EINVAL; - /* Cast all indexes into size_t. */ for (i = 0; i < local_counter_read.index.number_dimensions; i++) - indexes[i] = (size_t) local_counter_read.index.dimension_indexes[i]; + indexes[i] = local_counter_read.index.dimension_indexes[i]; cpu = local_counter_read.cpu; - ret = lttng_kernel_counter_read(counter, indexes, cpu, &value, - &overflow, &underflow); + ret = lttng_kernel_counter_read(counter, indexes, cpu, &value, &overflow, &underflow); if (ret) return ret; local_counter_read.value.value = value; @@ -689,13 +687,11 @@ long lttng_counter_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EINVAL; if (local_counter_aggregate.index.number_dimensions > LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX) return -EINVAL; - /* Cast all indexes into size_t. */ for (i = 0; i < local_counter_aggregate.index.number_dimensions; i++) - indexes[i] = (size_t) local_counter_aggregate.index.dimension_indexes[i]; + indexes[i] = local_counter_aggregate.index.dimension_indexes[i]; - ret = lttng_kernel_counter_aggregate(counter, indexes, &value, - &overflow, &underflow); + ret = lttng_kernel_counter_aggregate(counter, indexes, &value, &overflow, &underflow); if (ret) return ret; local_counter_aggregate.value.value = value; @@ -722,11 +718,9 @@ long lttng_counter_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EINVAL; if (local_counter_clear.index.number_dimensions > LTTNG_KERNEL_ABI_COUNTER_DIMENSION_MAX) return -EINVAL; - /* Cast all indexes into size_t. */ for (i = 0; i < local_counter_clear.index.number_dimensions; i++) - indexes[i] = (size_t) local_counter_clear.index.dimension_indexes[i]; - + indexes[i] = local_counter_clear.index.dimension_indexes[i]; return lttng_kernel_counter_clear(counter, indexes); } default: @@ -2209,11 +2203,12 @@ long lttng_abi_event_notifier_group_create_error_counter( { int counter_fd, ret; char *counter_transport_name; - size_t counter_len; - struct lttng_counter *counter = NULL; + struct lttng_kernel_channel_counter *chan_counter = NULL; struct file *counter_file; struct lttng_event_notifier_group *event_notifier_group = (struct lttng_event_notifier_group *) event_notifier_group_file->private_data; + struct lttng_counter_dimension dimensions[1]; + size_t counter_len; if (error_counter_conf->arithmetic != LTTNG_KERNEL_ABI_COUNTER_ARITHMETIC_MODULAR) { printk(KERN_ERR "LTTng: event_notifier: Error counter of the wrong arithmetic type.\n"); @@ -2264,39 +2259,41 @@ long lttng_abi_event_notifier_group_create_error_counter( } counter_len = error_counter_conf->dimensions[0].size; + dimensions[0].size = counter_len; + dimensions[0].underflow_index = 0; + dimensions[0].overflow_index = 0; + dimensions[0].has_underflow = 0; + dimensions[0].has_overflow = 0; if (!atomic_long_add_unless(&event_notifier_group_file->f_count, 1, LONG_MAX)) { ret = -EOVERFLOW; goto refcount_error; } - counter = lttng_kernel_counter_create(counter_transport_name, - 1, &counter_len); - if (!counter) { + chan_counter = lttng_kernel_counter_create(counter_transport_name, 1, dimensions, 0, false); + if (!chan_counter) { ret = -EINVAL; - goto counter_error; + goto create_error; } + chan_counter->priv->parent.file = counter_file; + chan_counter->priv->owner = event_notifier_group->file; + counter_file->private_data = chan_counter; event_notifier_group->error_counter_len = counter_len; /* * store-release to publish error counter matches load-acquire * in record_error. Ensures the counter is created and the * error_counter_len is set before they are used. */ - smp_store_release(&event_notifier_group->error_counter, counter); - - counter->file = counter_file; - counter->owner = event_notifier_group->file; - counter_file->private_data = counter; - /* Ownership transferred. */ - counter = NULL; + smp_store_release(&event_notifier_group->error_counter, + chan_counter); fd_install(counter_fd, counter_file); lttng_unlock_sessions(); return counter_fd; -counter_error: +create_error: atomic_long_dec(&event_notifier_group_file->f_count); refcount_error: fput(counter_file); diff --git a/src/lttng-counter-client-percpu-32-modular.c b/src/lttng-counter-client-percpu-32-modular.c index 35a8b54f..421b04ae 100644 --- a/src/lttng-counter-client-percpu-32-modular.c +++ b/src/lttng-counter-client-percpu-32-modular.c @@ -22,53 +22,89 @@ static const struct lib_counter_config client_config = { .counter_size = COUNTER_SIZE_32_BIT, }; -static struct lib_counter *counter_create(size_t nr_dimensions, - const size_t *max_nr_elem, +static struct lttng_kernel_channel_counter *counter_create(size_t nr_dimensions, + const struct lttng_counter_dimension *dimensions, int64_t global_sum_step) { - return lttng_counter_create(&client_config, nr_dimensions, max_nr_elem, + size_t max_nr_elem[LTTNG_COUNTER_DIMENSION_MAX], i; + struct lttng_kernel_channel_counter *lttng_chan_counter; + struct lib_counter *counter; + + if (nr_dimensions > LTTNG_COUNTER_DIMENSION_MAX) + return NULL; + for (i = 0; i < nr_dimensions; i++) { + if (dimensions[i].has_underflow || dimensions[i].has_overflow) + return NULL; + max_nr_elem[i] = dimensions[i].size; + } + lttng_chan_counter = lttng_kernel_alloc_channel_counter(); + if (!lttng_chan_counter) + return NULL; + counter = lttng_counter_create(&client_config, nr_dimensions, max_nr_elem, global_sum_step); + if (!counter) + goto error; + lttng_chan_counter->priv->counter = counter; + return lttng_chan_counter; + +error: + lttng_kernel_free_channel_common(<tng_chan_counter->parent); + return NULL; +} + +static void counter_destroy(struct lttng_kernel_channel_counter *counter) +{ + lttng_counter_destroy(counter->priv->counter); + lttng_kernel_free_channel_common(&counter->parent); } -static void counter_destroy(struct lib_counter *counter) +static int counter_add(struct lttng_kernel_channel_counter *counter, + const size_t *dimension_indexes, int64_t v) { - return lttng_counter_destroy(counter); + return lttng_counter_add(&client_config, counter->priv->counter, dimension_indexes, v); } -static int counter_add(struct lib_counter *counter, const size_t *dimension_indexes, int64_t v) +static int event_counter_add(struct lttng_kernel_event_counter *event_counter, int64_t v) { - return lttng_counter_add(&client_config, counter, dimension_indexes, v); + struct lttng_kernel_channel_counter *counter = event_counter->chan; + size_t index = event_counter->priv->parent.id; + + return counter_add(counter, &index, v); } -static int counter_read(struct lib_counter *counter, const size_t *dimension_indexes, int cpu, +static int counter_read(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int cpu, int64_t *value, bool *overflow, bool *underflow) { - return lttng_counter_read(&client_config, counter, dimension_indexes, cpu, value, + return lttng_counter_read(&client_config, counter->priv->counter, dimension_indexes, cpu, value, overflow, underflow); } -static int counter_aggregate(struct lib_counter *counter, const size_t *dimension_indexes, +static int counter_aggregate(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int64_t *value, bool *overflow, bool *underflow) { - return lttng_counter_aggregate(&client_config, counter, dimension_indexes, value, + return lttng_counter_aggregate(&client_config, counter->priv->counter, dimension_indexes, value, overflow, underflow); } -static int counter_clear(struct lib_counter *counter, const size_t *dimension_indexes) +static int counter_clear(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes) { - return lttng_counter_clear(&client_config, counter, dimension_indexes); + return lttng_counter_clear(&client_config, counter->priv->counter, dimension_indexes); } static struct lttng_counter_transport lttng_counter_transport = { .name = "counter-per-cpu-32-modular", .owner = THIS_MODULE, .ops = { - .counter_create = counter_create, - .counter_destroy = counter_destroy, - .counter_add = counter_add, - .counter_read = counter_read, - .counter_aggregate = counter_aggregate, - .counter_clear = counter_clear, + .priv = __LTTNG_COMPOUND_LITERAL(struct lttng_kernel_channel_counter_ops_private, { + .pub = <tng_counter_transport.ops, + .counter_create = counter_create, + .counter_destroy = counter_destroy, + .counter_add = counter_add, + .counter_read = counter_read, + .counter_aggregate = counter_aggregate, + .counter_clear = counter_clear, + }), + .event_counter_add = event_counter_add, }, }; diff --git a/src/lttng-counter-client-percpu-64-modular.c b/src/lttng-counter-client-percpu-64-modular.c index 771bed3e..6050ebc9 100644 --- a/src/lttng-counter-client-percpu-64-modular.c +++ b/src/lttng-counter-client-percpu-64-modular.c @@ -22,53 +22,89 @@ static const struct lib_counter_config client_config = { .counter_size = COUNTER_SIZE_64_BIT, }; -static struct lib_counter *counter_create(size_t nr_dimensions, - const size_t *max_nr_elem, +static struct lttng_kernel_channel_counter *counter_create(size_t nr_dimensions, + const struct lttng_counter_dimension *dimensions, int64_t global_sum_step) { - return lttng_counter_create(&client_config, nr_dimensions, max_nr_elem, + size_t max_nr_elem[LTTNG_COUNTER_DIMENSION_MAX], i; + struct lttng_kernel_channel_counter *lttng_chan_counter; + struct lib_counter *counter; + + if (nr_dimensions > LTTNG_COUNTER_DIMENSION_MAX) + return NULL; + for (i = 0; i < nr_dimensions; i++) { + if (dimensions[i].has_underflow || dimensions[i].has_overflow) + return NULL; + max_nr_elem[i] = dimensions[i].size; + } + lttng_chan_counter = lttng_kernel_alloc_channel_counter(); + if (!lttng_chan_counter) + return NULL; + counter = lttng_counter_create(&client_config, nr_dimensions, max_nr_elem, global_sum_step); + if (!counter) + goto error; + lttng_chan_counter->priv->counter = counter; + return lttng_chan_counter; + +error: + lttng_kernel_free_channel_common(<tng_chan_counter->parent); + return NULL; +} + +static void counter_destroy(struct lttng_kernel_channel_counter *counter) +{ + lttng_counter_destroy(counter->priv->counter); + lttng_kernel_free_channel_common(&counter->parent); } -static void counter_destroy(struct lib_counter *counter) +static int counter_add(struct lttng_kernel_channel_counter *counter, + const size_t *dimension_indexes, int64_t v) { - return lttng_counter_destroy(counter); + return lttng_counter_add(&client_config, counter->priv->counter, dimension_indexes, v); } -static int counter_add(struct lib_counter *counter, const size_t *dimension_indexes, int64_t v) +static int event_counter_add(struct lttng_kernel_event_counter *event_counter, int64_t v) { - return lttng_counter_add(&client_config, counter, dimension_indexes, v); + struct lttng_kernel_channel_counter *counter = event_counter->chan; + size_t index = event_counter->priv->parent.id; + + return counter_add(counter, &index, v); } -static int counter_read(struct lib_counter *counter, const size_t *dimension_indexes, int cpu, +static int counter_read(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int cpu, int64_t *value, bool *overflow, bool *underflow) { - return lttng_counter_read(&client_config, counter, dimension_indexes, cpu, value, + return lttng_counter_read(&client_config, counter->priv->counter, dimension_indexes, cpu, value, overflow, underflow); } -static int counter_aggregate(struct lib_counter *counter, const size_t *dimension_indexes, +static int counter_aggregate(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int64_t *value, bool *overflow, bool *underflow) { - return lttng_counter_aggregate(&client_config, counter, dimension_indexes, value, + return lttng_counter_aggregate(&client_config, counter->priv->counter, dimension_indexes, value, overflow, underflow); } -static int counter_clear(struct lib_counter *counter, const size_t *dimension_indexes) +static int counter_clear(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes) { - return lttng_counter_clear(&client_config, counter, dimension_indexes); + return lttng_counter_clear(&client_config, counter->priv->counter, dimension_indexes); } static struct lttng_counter_transport lttng_counter_transport = { .name = "counter-per-cpu-64-modular", .owner = THIS_MODULE, .ops = { - .counter_create = counter_create, - .counter_destroy = counter_destroy, - .counter_add = counter_add, - .counter_read = counter_read, - .counter_aggregate = counter_aggregate, - .counter_clear = counter_clear, + .priv = __LTTNG_COMPOUND_LITERAL(struct lttng_kernel_channel_counter_ops_private, { + .pub = <tng_counter_transport.ops, + .counter_create = counter_create, + .counter_destroy = counter_destroy, + .counter_add = counter_add, + .counter_read = counter_read, + .counter_aggregate = counter_aggregate, + .counter_clear = counter_clear, + }), + .event_counter_add = event_counter_add, }, }; diff --git a/src/lttng-event-notifier-notification.c b/src/lttng-event-notifier-notification.c index 29d2d156..290e57e3 100644 --- a/src/lttng-event-notifier-notification.c +++ b/src/lttng-event-notifier-notification.c @@ -394,7 +394,7 @@ void record_error(struct lttng_kernel_event_notifier *event_notifier) { struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group; - struct lttng_counter *error_counter; + struct lttng_kernel_channel_counter *error_counter; size_t dimension_index[1]; int ret; @@ -410,8 +410,7 @@ void record_error(struct lttng_kernel_event_notifier *event_notifier) dimension_index[0] = event_notifier->priv->error_counter_index; - ret = error_counter->ops->counter_add(error_counter->counter, - dimension_index, 1); + ret = error_counter->ops->priv->counter_add(error_counter, dimension_index, 1); if (ret) WARN_ON_ONCE(1); } diff --git a/src/lttng-events.c b/src/lttng-events.c index 3f15965c..2458b279 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -232,12 +232,15 @@ struct lttng_counter_transport *lttng_counter_transport_find(const char *name) return NULL; } -struct lttng_counter *lttng_kernel_counter_create( +struct lttng_kernel_channel_counter *lttng_kernel_counter_create( const char *counter_transport_name, - size_t number_dimensions, const size_t *dimensions_sizes) + size_t number_dimensions, + const struct lttng_counter_dimension *dimensions, + int64_t global_sum_step, + bool coalesce_hits) { - struct lttng_counter *counter = NULL; struct lttng_counter_transport *counter_transport = NULL; + struct lttng_kernel_channel_counter *counter = NULL; counter_transport = lttng_counter_transport_find(counter_transport_name); if (!counter_transport) { @@ -250,31 +253,34 @@ struct lttng_counter *lttng_kernel_counter_create( goto notransport; } - counter = lttng_kvzalloc(sizeof(struct lttng_counter), GFP_KERNEL); + counter = counter_transport->ops.priv->counter_create(number_dimensions, dimensions, + global_sum_step); if (!counter) - goto nomem; + goto create_error; /* 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; - } + counter->priv->parent.coalesce_hits = coalesce_hits; + counter->priv->transport = counter_transport; return counter; create_error: - lttng_kvfree(counter); -nomem: if (counter_transport) module_put(counter_transport->owner); notransport: return NULL; } +static +void lttng_kernel_counter_destroy(struct lttng_kernel_channel_counter *counter) +{ + struct lttng_counter_transport *counter_transport = counter->priv->transport; + + counter->ops->priv->counter_destroy(counter); + module_put(counter_transport->owner); +} + struct lttng_event_notifier_group *lttng_event_notifier_group_create(void) { struct lttng_transport *transport = NULL; @@ -429,14 +435,8 @@ void lttng_event_notifier_group_destroy( &event_notifier_group->event_notifiers_head, parent.node) _lttng_event_destroy(&event_notifier_priv->pub->parent); - 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; - } + if (event_notifier_group->error_counter) + lttng_kernel_counter_destroy(event_notifier_group->error_counter); event_notifier_group->ops->priv->channel_destroy(event_notifier_group->chan); module_put(event_notifier_group->transport->owner); @@ -769,7 +769,6 @@ struct lttng_kernel_channel_buffer *lttng_channel_buffer_create(struct lttng_ker enum channel_type channel_type) { struct lttng_kernel_channel_buffer *chan; - struct lttng_kernel_channel_buffer_private *chan_priv; struct lttng_transport *transport = NULL; mutex_lock(&sessions_mutex); @@ -785,15 +784,9 @@ struct lttng_kernel_channel_buffer *lttng_channel_buffer_create(struct lttng_ker printk(KERN_WARNING "LTTng: Can't lock transport module.\n"); goto notransport; } - chan = kzalloc(sizeof(struct lttng_kernel_channel_buffer), GFP_KERNEL); + chan = lttng_kernel_alloc_channel_buffer(); if (!chan) goto nomem; - chan_priv = kzalloc(sizeof(struct lttng_kernel_channel_buffer_private), GFP_KERNEL); - if (!chan_priv) - goto nomem_priv; - chan->priv = chan_priv; - chan_priv->pub = chan; - chan->parent.type = LTTNG_KERNEL_CHANNEL_TYPE_BUFFER; chan->parent.session = session; chan->priv->id = session->priv->free_chan_id++; chan->ops = &transport->ops; @@ -816,9 +809,7 @@ struct lttng_kernel_channel_buffer *lttng_channel_buffer_create(struct lttng_ker return chan; create_error: - kfree(chan_priv); -nomem_priv: - kfree(chan); + lttng_kernel_free_channel_common(&chan->parent); nomem: if (transport) module_put(transport->owner); @@ -1060,12 +1051,15 @@ int lttng_kernel_event_notifier_clear_error_counter(struct lttng_kernel_event_co { switch (event->type) { case LTTNG_KERNEL_EVENT_TYPE_RECORDER: + lttng_fallthrough; + case LTTNG_KERNEL_EVENT_TYPE_COUNTER: 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_kernel_channel_counter *error_counter; struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group; size_t dimension_index[1]; int ret; @@ -1089,7 +1083,7 @@ int lttng_kernel_event_notifier_clear_error_counter(struct lttng_kernel_event_co } dimension_index[0] = event_notifier->priv->error_counter_index; - ret = error_counter->ops->counter_clear(error_counter->counter, dimension_index); + ret = error_counter->ops->priv->counter_clear(error_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); @@ -1356,26 +1350,26 @@ struct lttng_kernel_event_common *lttng_kernel_event_create(struct lttng_event_e return event; } -int lttng_kernel_counter_read(struct lttng_counter *counter, +int lttng_kernel_counter_read(struct lttng_kernel_channel_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, + return counter->ops->priv->counter_read(counter, dim_indexes, cpu, val, overflow, underflow); } -int lttng_kernel_counter_aggregate(struct lttng_counter *counter, +int lttng_kernel_counter_aggregate(struct lttng_kernel_channel_counter *counter, const size_t *dim_indexes, int64_t *val, bool *overflow, bool *underflow) { - return counter->ops->counter_aggregate(counter->counter, dim_indexes, + return counter->ops->priv->counter_aggregate(counter, dim_indexes, val, overflow, underflow); } -int lttng_kernel_counter_clear(struct lttng_counter *counter, +int lttng_kernel_counter_clear(struct lttng_kernel_channel_counter *counter, const size_t *dim_indexes) { - return counter->ops->counter_clear(counter->counter, dim_indexes); + return counter->ops->priv->counter_clear(counter, dim_indexes); } /* Only used for tracepoints and system calls for now. */ @@ -4053,6 +4047,87 @@ void lttng_counter_transport_unregister(struct lttng_counter_transport *transpor } EXPORT_SYMBOL_GPL(lttng_counter_transport_unregister); +struct lttng_kernel_channel_buffer *lttng_kernel_alloc_channel_buffer(void) +{ + struct lttng_kernel_channel_buffer *lttng_chan_buf; + struct lttng_kernel_channel_common *lttng_chan_common; + struct lttng_kernel_channel_buffer_private *lttng_chan_buf_priv; + + lttng_chan_buf = kzalloc(sizeof(struct lttng_kernel_channel_buffer), GFP_KERNEL); + if (!lttng_chan_buf) + goto nomem; + lttng_chan_buf_priv = kzalloc(sizeof(struct lttng_kernel_channel_buffer_private), GFP_KERNEL); + if (!lttng_chan_buf_priv) + goto nomem_priv; + lttng_chan_common = <tng_chan_buf->parent; + lttng_chan_common->type = LTTNG_KERNEL_CHANNEL_TYPE_BUFFER; + lttng_chan_buf->priv = lttng_chan_buf_priv; + lttng_chan_common->priv = <tng_chan_buf_priv->parent; + lttng_chan_buf_priv->pub = lttng_chan_buf; + lttng_chan_buf_priv->parent.pub = lttng_chan_common; + return lttng_chan_buf; + +nomem_priv: + kfree(lttng_chan_buf); +nomem: + return NULL; +} +EXPORT_SYMBOL_GPL(lttng_kernel_alloc_channel_buffer); + +struct lttng_kernel_channel_counter *lttng_kernel_alloc_channel_counter(void) +{ + struct lttng_kernel_channel_counter *lttng_chan_counter; + struct lttng_kernel_channel_common *lttng_chan_common; + struct lttng_kernel_channel_counter_private *lttng_chan_counter_priv; + + lttng_chan_counter = kzalloc(sizeof(struct lttng_kernel_channel_counter), GFP_KERNEL); + if (!lttng_chan_counter) + goto nomem; + lttng_chan_counter_priv = kzalloc(sizeof(struct lttng_kernel_channel_counter_private), GFP_KERNEL); + if (!lttng_chan_counter_priv) + goto nomem_priv; + lttng_chan_common = <tng_chan_counter->parent; + lttng_chan_common->type = LTTNG_KERNEL_CHANNEL_TYPE_COUNTER; + lttng_chan_counter->priv = lttng_chan_counter_priv; + lttng_chan_common->priv = <tng_chan_counter_priv->parent; + lttng_chan_counter_priv->pub = lttng_chan_counter; + lttng_chan_counter_priv->parent.pub = lttng_chan_common; + return lttng_chan_counter; + +nomem_priv: + kfree(lttng_chan_counter); +nomem: + return NULL; +} +EXPORT_SYMBOL_GPL(lttng_kernel_alloc_channel_counter); + +void lttng_kernel_free_channel_common(struct lttng_kernel_channel_common *chan) +{ + switch (chan->type) { + case LTTNG_KERNEL_CHANNEL_TYPE_BUFFER: + { + struct lttng_kernel_channel_buffer *chan_buf = container_of(chan, + struct lttng_kernel_channel_buffer, parent); + + kfree(chan_buf->priv); + kfree(chan_buf); + break; + } + case LTTNG_KERNEL_CHANNEL_TYPE_COUNTER: + { + struct lttng_kernel_channel_counter *chan_counter = container_of(chan, + struct lttng_kernel_channel_counter, parent); + + kfree(chan_counter->priv); + kfree(chan_counter); + break; + } + default: + WARN_ON_ONCE(1); + } +} +EXPORT_SYMBOL_GPL(lttng_kernel_free_channel_common); + #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) enum cpuhp_state lttng_hp_prepare;