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);
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;
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 {
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
struct lttng_kernel_syscall_table syscall_table;
- struct lttng_counter *error_counter;
+ struct lttng_kernel_channel_counter *error_counter;
size_t error_counter_len;
};
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 {
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(
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), \
enum lttng_kernel_channel_type {
LTTNG_KERNEL_CHANNEL_TYPE_BUFFER = 0,
+ LTTNG_KERNEL_CHANNEL_TYPE_COUNTER = 1,
};
struct lttng_kernel_channel_common_private;
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;
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;
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;
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;
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:
{
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");
}
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);
.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,
},
};
.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,
},
};
{
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;
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);
}
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) {
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;
&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);
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);
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;
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);
{
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;
}
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);
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. */
}
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;