From: Mathieu Desnoyers Date: Tue, 23 Jul 2024 19:20:51 +0000 (-0400) Subject: Introduce extension points for trace hit counters X-Git-Url: http://git.lttng.org./?a=commitdiff_plain;h=d9a337ba12e599152c5fccedd177e943049697e1;p=lttng-modules.git Introduce extension points for trace hit counters Introduce two extension points for trace hit counters: 1) Future "actions" to perform other than "increment", 2) Future dimension indexing schemes (keys) other than tokens. Change the layout of struct lttng_kernel_abi_counter_key_dimension by adding a "key_type" field. A new struct lttng_kernel_abi_counter_key_dimension_tokens inherits from struct lttng_kernel_abi_counter_key_dimension, and contains the uint32_t nr_key_tokens field. The only currently supported key_type is LTTNG_KERNEL_ABI_KEY_TYPE_TOKENS = 0. Change the layout of struct lttng_kernel_abi_counter_event by adding an "action" field. The only currently supported action is LTTNG_KERNEL_ABI_COUNTER_ACTION_INCREMENT = 0. Change the struct lttng_kernel_abi_key_token_string so it inherits from struct lttng_kernel_abi_key_token. The "len" field of struct lttng_kernel_abi_key_token now includes the length of the entire child structure. Remove struct lttng_kernel_abi_counter_key: it was previously expecting all key dimensions to have the same size. But because each dimension can be of a different type, each may have its own distinct size. Change the newly introduced API between probe providers to change the "event_counter_add" callback into a "counter_hit" callback, which takes one less argument (no integer value), but takes additional stack_data, probe_ctx, and event_counter_ctx arguments for future use. Change-Id: I4de86a9fac75ce759f58b545dffa2f99c59f5688 Signed-off-by: Mathieu Desnoyers --- diff --git a/include/lttng/abi.h b/include/lttng/abi.h index 7b26dafc..8f0a1472 100644 --- a/include/lttng/abi.h +++ b/include/lttng/abi.h @@ -209,47 +209,105 @@ enum lttng_kernel_abi_counter_bitness { LTTNG_KERNEL_ABI_COUNTER_BITNESS_64 = 1, }; -struct lttng_kernel_abi_counter_key_string { - uint32_t string_len; /* string length allocated by user-space (input) (includes \0) */ - char str[]; /* Null-terminated string. */ +struct lttng_kernel_abi_key_token { + uint32_t len; /* length of child structure. */ + uint32_t type; /* enum lttng_kernel_abi_key_token_type */ + /* + * The size of this structure is fixed because it is embedded into + * children structures. + */ } __attribute__((packed)); -struct lttng_kernel_abi_counter_map_descriptor { - uint32_t len; /* length of this structure */ - - uint64_t descriptor_index; /* input. [ 0 .. nr_descriptors - 1 ] */ +/* Length of this structure excludes the following string. */ +struct lttng_kernel_abi_key_token_string { + struct lttng_kernel_abi_key_token parent; + uint32_t string_len; /* string length (includes \0) */ - uint32_t dimension; /* outputs */ - uint64_t array_index; - uint64_t user_token; - uint64_t key_ptr; /* pointer to struct lttng_kernel_abi_counter_key_string */ - uint32_t key_string_len; /* key string length (includes \0) */ + /* Null-terminated string of length @string_len follows this structure. */ } __attribute__((packed)); -struct lttng_kernel_abi_key_token { - uint32_t type; /* enum lttng_kernel_abi_key_token_type */ - union { - uint64_t string_ptr; - } arg; +/* + * token types event_name and provider_name don't have specific fields, + * so they do not need to derive their own specific child structure. + */ + +struct lttng_kernel_abi_counter_map_descriptor { + uint32_t len; /* length of this structure. */ + + uint64_t descriptor_index; /* Descriptor index (input: [ 0 .. nr_descriptors - 1 ]) */ + + uint32_t dimension; /* Dimension indexed (output) */ + uint64_t user_token; /* User-provided 64-bit token (output) */ + uint64_t key_string; /* + * Pointer (input) to key string associated with this index + * (output). If key_string_len is smaller than the required + * space, the ioctl fails with -ENOSPC, storing the required + * string space into @key_string_len. + */ + uint32_t key_string_len; /* Key string length (input/output, includes \0) */ + uint64_t array_indexes; /* + * Pointer (input) to array of indexes within each dimension + * (output). There are @dimension values populated. Each + * element is of type uint64_t. If arrays_indexes_len is + * smaller than @dimension, the ioctl fails with -ENOSPC, + * storing the required array index length into + * @array_index_len. + */ + uint32_t array_indexes_len; /* Array indexes length (input/output). */ } __attribute__((packed)); +/* + * Dimension indexing: All events should use the same key type to index + * a given map dimension. + */ +enum lttng_kernel_abi_key_type { + LTTNG_KERNEL_ABI_KEY_TYPE_TOKENS = 0, /* Dimension key is a set of tokens. */ + LTTNG_KERNEL_ABI_KEY_TYPE_INTEGER = 1, /* Dimension key is an integer value. */ +}; + struct lttng_kernel_abi_counter_key_dimension { - uint32_t nr_key_tokens; - uint32_t elem_len; /* array stride (size of struct lttng_kernel_abi_key_token) */ - uint64_t ptr; /* pointer to array of struct lttng_kernel_abi_key_token */ + uint32_t len; /* length of child structure */ + uint32_t key_type; /* enum lttng_kernel_abi_key_type */ + /* + * The size of this structure is fixed because it is embedded + * into children structures. + */ } __attribute__((packed)); -struct lttng_kernel_abi_counter_key { - uint32_t number_dimensions; - uint32_t elem_len; /* array stride (size of struct lttng_kernel_abi_counter_key_dimension) */ - uint64_t ptr; /* pointer to array of struct lttng_kernel_abi_counter_key_dimension */ +struct lttng_kernel_abi_counter_key_dimension_tokens { + struct lttng_kernel_abi_counter_key_dimension parent; + uint32_t nr_key_tokens; + + /* Followed by an array of nr_key_tokens struct lttng_kernel_abi_key_token elements. */ } __attribute__((packed)); +/* + * The "integer" key type is not implemented yet, but when it will be + * introduced in the future, its specific key dimension will allow + * defining the function to apply over input argument, bytecode to run + * and so on. + */ + +enum lttng_kernel_abi_counter_action { + LTTNG_KERNEL_ABI_COUNTER_ACTION_INCREMENT = 0, + + /* + * Can be extended with additional actions, such as decrement, + * set value, run bytecode, and so on. + */ +}; + struct lttng_kernel_abi_counter_event { uint32_t len; /* length of this structure */ + uint32_t action; /* enum lttng_kernel_abi_counter_action */ struct lttng_kernel_abi_event event; - struct lttng_kernel_abi_counter_key key; + uint32_t number_key_dimensions; /* array of dimensions is an array of var. len. elements. */ + + /* + * Followed by additional data specific to the action, and by a + * variable-length array of key dimensions. + */ } __attribute__((packed)); enum lttng_kernel_abi_counter_dimension_flags { @@ -258,6 +316,7 @@ enum lttng_kernel_abi_counter_dimension_flags { }; struct lttng_kernel_abi_counter_dimension { + uint32_t key_type; /* enum lttng_kernel_abi_key_type */ uint32_t flags; /* enum lttng_kernel_abi_counter_dimension_flags */ uint64_t size; /* dimension size */ uint64_t underflow_index; diff --git a/include/lttng/events-internal.h b/include/lttng/events-internal.h index 55d34c44..224bfec1 100644 --- a/include/lttng/events-internal.h +++ b/include/lttng/events-internal.h @@ -134,11 +134,16 @@ struct lttng_kernel_event_recorder_private { #define LTTNG_KERNEL_COUNTER_KEY_LEN 256 +enum lttng_event_counter_action { + LTTNG_EVENT_COUNTER_ACTION_INCREMENT = 0, +}; + struct lttng_kernel_event_counter_private { struct lttng_kernel_event_session_common_private parent; struct lttng_kernel_event_counter *pub; /* Public event interface */ struct hlist_node hlist_key_node; /* node in events key hash table */ + enum lttng_event_counter_action action; char key[LTTNG_KERNEL_COUNTER_KEY_LEN]; }; @@ -352,6 +357,8 @@ struct lttng_event_counter_enabler { struct lttng_event_enabler_session_common parent; struct lttng_kernel_channel_counter *chan; struct lttng_kernel_counter_key *key; + + enum lttng_event_counter_action action; }; struct lttng_event_notifier_enabler { diff --git a/include/lttng/events.h b/include/lttng/events.h index ba30c2b7..8c04ec28 100644 --- a/include/lttng/events.h +++ b/include/lttng/events.h @@ -376,6 +376,10 @@ struct lttng_kernel_event_recorder { struct lttng_kernel_channel_buffer *chan; }; +struct lttng_kernel_event_counter_ctx { + int args_available; +}; + struct lttng_kernel_event_counter_private; struct lttng_kernel_event_counter { @@ -383,6 +387,8 @@ struct lttng_kernel_event_counter { struct lttng_kernel_event_counter_private *priv; /* Private event counter interface */ struct lttng_kernel_channel_counter *chan; + + int use_args; /* Use input arguments. */ }; struct lttng_kernel_notification_ctx { @@ -456,7 +462,10 @@ struct lttng_kernel_channel_counter_ops_private; struct lttng_kernel_channel_counter_ops { struct lttng_kernel_channel_counter_ops_private *priv; /* Private channel counter ops interface */ - int (*event_counter_add)(struct lttng_kernel_event_counter *event_counter, int64_t v); + int (*counter_hit)(struct lttng_kernel_event_counter *event_counter, + const char *stack_data, + struct lttng_kernel_probe_ctx *probe_ctx, + struct lttng_kernel_event_counter_ctx *event_counter_ctx); }; struct lttng_kernel_channel_counter { diff --git a/include/lttng/tracepoint-event-impl.h b/include/lttng/tracepoint-event-impl.h index e047950a..a0053044 100644 --- a/include/lttng/tracepoint-event-impl.h +++ b/include/lttng/tracepoint-event-impl.h @@ -1175,8 +1175,18 @@ static void __event_probe__##_name(_data_proto) \ { \ struct lttng_kernel_event_counter *__event_counter = \ container_of(__event, struct lttng_kernel_event_counter, parent); \ + struct lttng_kernel_event_counter_ctx __event_counter_ctx; \ \ - (void) __event_counter->chan->ops->event_counter_add(__event_counter, 1); \ + __event_counter_ctx.args_available = LTTNG_READ_ONCE(__event_counter->use_args); \ + if (unlikely(!__interpreter_stack_prepared && __event_counter_ctx.args_available)) \ + __event_prepare_interpreter_stack__##_name( \ + __stackvar.__interpreter_stack_data, \ + _locvar_args); \ + \ + (void) __event_counter->chan->ops->counter_hit(__event_counter, \ + __stackvar.__interpreter_stack_data, \ + &__lttng_probe_ctx, \ + &__event_counter_ctx); \ break; \ } \ default: \ diff --git a/src/lttng-abi.c b/src/lttng-abi.c index 97fbfe95..5a3b616f 100644 --- a/src/lttng-abi.c +++ b/src/lttng-abi.c @@ -687,103 +687,124 @@ end: } static -int create_counter_key_from_abi_key(struct lttng_kernel_counter_key **_counter_key, - struct lttng_kernel_abi_counter_key *abi_key) +int create_counter_key_from_abi_dimensions(struct lttng_kernel_counter_key **_counter_key, + uint32_t nr_dimensions, void __user *ptr) { - struct lttng_kernel_counter_key *counter_key; - uint32_t i, dimension_len, nr_dimensions; struct lttng_kernel_abi_counter_key_dimension __user *udimension; struct lttng_kernel_abi_counter_key_dimension kdimension = {}; - struct lttng_kernel_abi_key_token __user *utoken; - struct lttng_key_token *token_array; - uint32_t token_len, nr_tokens; + struct lttng_kernel_counter_key *counter_key = NULL; + struct lttng_key_token *token_array = NULL; + uint32_t i; int ret = 0; - nr_dimensions = abi_key->number_dimensions; if (!nr_dimensions || nr_dimensions > LTTNG_KERNEL_COUNTER_MAX_DIMENSIONS) return -EINVAL; counter_key = kzalloc(sizeof(*counter_key), GFP_KERNEL); if (!counter_key) return -ENOMEM; counter_key->nr_dimensions = nr_dimensions; - dimension_len = abi_key->elem_len; - if (dimension_len > PAGE_SIZE) { - ret = -E2BIG; - goto error; - } - if (dimension_len < offsetofend(struct lttng_kernel_abi_counter_key_dimension, ptr)) { + /* Only a single dimension is supported. */ + if (WARN_ON_ONCE(nr_dimensions != 1)) { ret = -EINVAL; goto error; } - /* Only a single dimension is supported. */ - WARN_ON_ONCE(nr_dimensions != 1); - udimension = (struct lttng_kernel_abi_counter_key_dimension __user *)(unsigned long)abi_key->ptr; - ret = lttng_copy_struct_from_user(&kdimension, sizeof(kdimension), udimension, dimension_len); + udimension = (struct lttng_kernel_abi_counter_key_dimension __user *)ptr; + ret = lttng_copy_struct_from_user(&kdimension, sizeof(kdimension), udimension, sizeof(*udimension)); if (ret) goto error; - nr_tokens = kdimension.nr_key_tokens; - if (nr_tokens > LTTNG_KERNEL_COUNTER_MAX_TOKENS) { - ret = -EINVAL; - goto error; - } - token_len = kdimension.elem_len; - if (token_len > PAGE_SIZE) { + if (kdimension.len > PAGE_SIZE) { ret = -E2BIG; goto error; } - token_array = kzalloc(nr_tokens * sizeof(*token_array), GFP_KERNEL); - if (!token_array) { - ret = -ENOMEM; - goto error; - } - counter_key->dimension_array[0].token_array = token_array; - counter_key->dimension_array[0].nr_key_tokens = nr_tokens; - utoken = (struct lttng_kernel_abi_key_token __user *)(unsigned long)kdimension.ptr; - for (i = 0; i < nr_tokens; i++) { - struct lttng_kernel_abi_key_token ktoken = {}; - struct lttng_key_token *key_token = &token_array[i]; - - ret = lttng_copy_struct_from_user(&ktoken, sizeof(ktoken), utoken, token_len); + switch (kdimension.key_type) { + case LTTNG_KERNEL_ABI_KEY_TYPE_TOKENS: + { + struct lttng_kernel_abi_counter_key_dimension_tokens kdimension_tokens = {}; + struct lttng_kernel_abi_counter_key_dimension_tokens __user *udimension_tokens; + struct lttng_kernel_abi_key_token __user *utoken; + uint32_t nr_tokens; + + udimension_tokens = (struct lttng_kernel_abi_counter_key_dimension_tokens __user *)ptr; + ret = lttng_copy_struct_from_user(&kdimension_tokens, sizeof(kdimension_tokens), + udimension_tokens, kdimension.len); if (ret) goto error; - switch (ktoken.type) { - case LTTNG_KERNEL_ABI_KEY_TOKEN_STRING: - { - char __user *string_ptr = (char __user *)(unsigned long)ktoken.arg.string_ptr; - size_t string_len; - - key_token->type = LTTNG_KEY_TOKEN_STRING; - - string_len = strnlen_user(string_ptr, PAGE_SIZE); - if (!string_len || string_len > PAGE_SIZE) { - ret = -EINVAL; - goto error; - } - key_token->str = kzalloc(string_len, GFP_KERNEL); - if (!key_token->str) { - ret = -ENOMEM; - goto error; - } - ret = copy_from_user(key_token->str, string_ptr, string_len); + nr_tokens = kdimension_tokens.nr_key_tokens; + if (nr_tokens > LTTNG_KERNEL_COUNTER_MAX_TOKENS) { + ret = -EINVAL; + goto error; + } + token_array = kzalloc(nr_tokens * sizeof(*token_array), GFP_KERNEL); + if (!token_array) { + ret = -ENOMEM; + goto error; + } + counter_key->dimension_array[0].token_array = token_array; + counter_key->dimension_array[0].nr_key_tokens = nr_tokens; + utoken = (struct lttng_kernel_abi_key_token __user *)((unsigned long)ptr + kdimension.len); + for (i = 0; i < nr_tokens; i++) { + struct lttng_kernel_abi_key_token ktoken = {}; + struct lttng_key_token *key_token = &token_array[i]; + uint32_t token_len = 0; + + ret = lttng_copy_struct_from_user(&ktoken, sizeof(ktoken), utoken, sizeof(*utoken)); if (ret) goto error; - if (key_token->str[string_len - 1] != '\0') { + token_len += ktoken.len; + switch (ktoken.type) { + case LTTNG_KERNEL_ABI_KEY_TOKEN_STRING: + { + struct lttng_kernel_abi_key_token_string __user *utoken_string; + struct lttng_kernel_abi_key_token_string *ktoken_string; + char __user *string_ptr; + size_t string_len; + + utoken_string = (struct lttng_kernel_abi_key_token_string __user *) utoken; + ret = lttng_copy_struct_from_user(&ktoken_string, sizeof(ktoken_string), + utoken_string, ktoken.len); + if (ret) + goto error; + string_ptr = (char __user *) ((unsigned long)utoken_string + ktoken.len); + string_len = ktoken_string->string_len; + key_token->type = LTTNG_KEY_TOKEN_STRING; + if (!string_len || string_len > PAGE_SIZE) { + ret = -EINVAL; + goto error; + } + key_token->str = kzalloc(string_len, GFP_KERNEL); + if (!key_token->str) { + ret = -ENOMEM; + goto error; + } + ret = copy_from_user(key_token->str, string_ptr, string_len); + if (ret) + goto error; + if (key_token->str[string_len - 1] != '\0') { + ret = -EINVAL; + goto error; + } + token_len += string_len; + break; + } + case LTTNG_KERNEL_ABI_KEY_TOKEN_EVENT_NAME: + key_token->type = LTTNG_KEY_TOKEN_EVENT_NAME; + break; + + case LTTNG_KERNEL_ABI_KEY_TOKEN_PROVIDER_NAME: + lttng_fallthrough; + default: ret = -EINVAL; goto error; } - break; + utoken = (struct lttng_kernel_abi_key_token __user *)((unsigned long)utoken + token_len); } - case LTTNG_KERNEL_ABI_KEY_TOKEN_EVENT_NAME: - key_token->type = LTTNG_KEY_TOKEN_EVENT_NAME; - break; - case LTTNG_KERNEL_ABI_KEY_TOKEN_PROVIDER_NAME: - lttng_fallthrough; - default: - ret = -EINVAL; - goto error; - } - utoken = (struct lttng_kernel_abi_key_token __user *)((unsigned long)utoken + token_len); + break; + } + case LTTNG_KERNEL_ABI_KEY_TYPE_INTEGER: + default: + ret = -EINVAL; + goto error; } *_counter_key = counter_key; return 0; @@ -1138,12 +1159,11 @@ long lttng_counter_ioctl_abi_counter_event(struct file *file, return ret; if (len > PAGE_SIZE) return -E2BIG; - if (len < offsetofend(struct lttng_kernel_abi_counter_event, key)) + if (len < offsetofend(struct lttng_kernel_abi_counter_event, number_key_dimensions)) return -EINVAL; counter_event = kzalloc(sizeof(*counter_event), GFP_KERNEL); - if (!counter_event) { + if (!counter_event) return -ENOMEM; - } ret = lttng_copy_struct_from_user(&kcounter_event, sizeof(kcounter_event), ucounter_event, len); if (ret) @@ -1152,7 +1172,17 @@ long lttng_counter_ioctl_abi_counter_event(struct file *file, ret = copy_user_event_param_ext(&counter_event->event_param_ext, &kcounter_event.event); if (ret) goto end_counter_event; - ret = create_counter_key_from_abi_key(&counter_event->counter_key, &kcounter_event.key); + switch (kcounter_event.action) { + case LTTNG_KERNEL_ABI_COUNTER_ACTION_INCREMENT: + /* No specific data for this action. */ + break; + default: + ret = -EINVAL; + goto end_counter_event; + } + ret = create_counter_key_from_abi_dimensions(&counter_event->counter_key, + kcounter_event.number_key_dimensions, + (void __user *) arg + len); if (ret) goto end_counter_event; ret = lttng_abi_create_event_counter_enabler(file, counter_event); @@ -1168,10 +1198,10 @@ long lttng_counter_ioctl_abi_counter_map_descriptor(struct lttng_kernel_channel_ { struct lttng_kernel_abi_counter_map_descriptor __user *udescriptor = (struct lttng_kernel_abi_counter_map_descriptor __user *) arg; - struct lttng_kernel_abi_counter_key_string __user *ukey_ptr; struct lttng_kernel_abi_counter_map_descriptor kdescriptor = {}; struct lttng_counter_map_descriptor *descriptor; char key[LTTNG_KERNEL_COUNTER_KEY_LEN] = {}; + uint64_t array_indexes[1]; size_t key_strlen; uint32_t len; int ret; @@ -1181,41 +1211,38 @@ long lttng_counter_ioctl_abi_counter_map_descriptor(struct lttng_kernel_channel_ return ret; if (len > PAGE_SIZE) return -E2BIG; - if (!len || len < offsetofend(struct lttng_kernel_abi_counter_map_descriptor, key_ptr)) + if (len < offsetofend(struct lttng_kernel_abi_counter_map_descriptor, array_indexes_len)) return -EINVAL; ret = lttng_copy_struct_from_user(&kdescriptor, sizeof(kdescriptor), udescriptor, len); if (ret) return ret; - mutex_lock(&counter->priv->map.lock); if (kdescriptor.descriptor_index >= counter->priv->map.nr_descriptors) { ret = -EOVERFLOW; goto map_descriptor_error_unlock; } + if (kdescriptor.array_indexes_len < 1) { + ret = -EINVAL; + goto map_descriptor_error_unlock; + } + kdescriptor.array_indexes_len = 1; descriptor = &counter->priv->map.descriptors[kdescriptor.descriptor_index]; + kdescriptor.dimension = 0; kdescriptor.user_token = descriptor->user_token; - kdescriptor.array_index = descriptor->array_index; memcpy(&key, descriptor->key, LTTNG_KERNEL_COUNTER_KEY_LEN); + array_indexes[0] = descriptor->array_index; mutex_unlock(&counter->priv->map.lock); key_strlen = strlen(key) + 1; + if (kdescriptor.key_string_len < key_strlen) + return -ENOSPC; kdescriptor.key_string_len = key_strlen; + if (copy_to_user((char __user *)(unsigned long)kdescriptor.key_string, key, key_strlen)) + return -EFAULT; + if (copy_to_user((uint64_t __user *)(unsigned long)kdescriptor.array_indexes, array_indexes, sizeof(uint64_t))) + return -EFAULT; if (copy_to_user(udescriptor, &kdescriptor, min(sizeof(kdescriptor), (size_t)len))) return -EFAULT; - ukey_ptr = (struct lttng_kernel_abi_counter_key_string __user *)(unsigned long)kdescriptor.key_ptr; - if (ukey_ptr) { - uint32_t ukey_string_len; - - ret = get_user(ukey_string_len, &ukey_ptr->string_len); - if (ret) - return ret; - if (ukey_string_len > PAGE_SIZE) - return -E2BIG; - if (key_strlen > ukey_string_len) - return -ENOSPC; - if (copy_to_user(ukey_ptr->str, key, key_strlen)) - return -EFAULT; - } return 0; map_descriptor_error_unlock: diff --git a/src/lttng-counter-client-percpu-32-modular.c b/src/lttng-counter-client-percpu-32-modular.c index b8b79a7e..eb9d74d8 100644 --- a/src/lttng-counter-client-percpu-32-modular.c +++ b/src/lttng-counter-client-percpu-32-modular.c @@ -65,12 +65,22 @@ static int counter_add(struct lttng_kernel_channel_counter *counter, return lttng_counter_add(&client_config, counter->priv->counter, dimension_indexes, v); } -static int event_counter_add(struct lttng_kernel_event_counter *event_counter, int64_t v) +static int counter_hit(struct lttng_kernel_event_counter *event_counter, + const char *stack_data __attribute__((unused)), + struct lttng_kernel_probe_ctx *probe_ctx __attribute__((unused)), + struct lttng_kernel_event_counter_ctx *event_counter_ctx __attribute__((unused))) { struct lttng_kernel_channel_counter *counter = event_counter->chan; - size_t index = event_counter->priv->parent.id; - return counter_add(counter, &index, v); + switch (event_counter->priv->action) { + case LTTNG_EVENT_COUNTER_ACTION_INCREMENT: + { + size_t index = event_counter->priv->parent.id; + return counter_add(counter, &index, 1); + } + default: + return -ENOSYS; + } } static int counter_read(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int cpu, @@ -117,7 +127,7 @@ static struct lttng_counter_transport lttng_counter_transport = { .counter_get_nr_dimensions = counter_get_nr_dimensions, .counter_get_max_nr_elem = counter_get_max_nr_elem, }), - .event_counter_add = event_counter_add, + .counter_hit = counter_hit, }, }; diff --git a/src/lttng-counter-client-percpu-64-modular.c b/src/lttng-counter-client-percpu-64-modular.c index 4ff38a3e..829e6a70 100644 --- a/src/lttng-counter-client-percpu-64-modular.c +++ b/src/lttng-counter-client-percpu-64-modular.c @@ -65,12 +65,22 @@ static int counter_add(struct lttng_kernel_channel_counter *counter, return lttng_counter_add(&client_config, counter->priv->counter, dimension_indexes, v); } -static int event_counter_add(struct lttng_kernel_event_counter *event_counter, int64_t v) +static int counter_hit(struct lttng_kernel_event_counter *event_counter, + const char *stack_data __attribute__((unused)), + struct lttng_kernel_probe_ctx *probe_ctx __attribute__((unused)), + struct lttng_kernel_event_counter_ctx *event_counter_ctx __attribute__((unused))) { struct lttng_kernel_channel_counter *counter = event_counter->chan; - size_t index = event_counter->priv->parent.id; - return counter_add(counter, &index, v); + switch (event_counter->priv->action) { + case LTTNG_EVENT_COUNTER_ACTION_INCREMENT: + { + size_t index = event_counter->priv->parent.id; + return counter_add(counter, &index, 1); + } + default: + return -ENOSYS; + } } static int counter_read(struct lttng_kernel_channel_counter *counter, const size_t *dimension_indexes, int cpu, @@ -117,7 +127,7 @@ static struct lttng_counter_transport lttng_counter_transport = { .counter_get_nr_dimensions = counter_get_nr_dimensions, .counter_get_max_nr_elem = counter_get_max_nr_elem, }), - .event_counter_add = event_counter_add, + .counter_hit = counter_hit, }, }; diff --git a/src/lttng-events.c b/src/lttng-events.c index 8a6c6478..95184984 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -1073,6 +1073,7 @@ struct lttng_kernel_event_common *lttng_kernel_event_alloc(struct lttng_event_en if (!chan->priv->parent.coalesce_hits) event_counter->priv->parent.parent.user_token = event_counter_enabler->parent.parent.user_token; strcpy(event_counter_priv->key, key_string); + event_counter_priv->action = event_counter_enabler->action; if (key_head) { struct lttng_kernel_event_counter_private *event_counter_priv_iter; diff --git a/src/lttng-kprobes.c b/src/lttng-kprobes.c index 5fa2a11a..75eb4141 100644 --- a/src/lttng-kprobes.c +++ b/src/lttng-kprobes.c @@ -95,8 +95,11 @@ int lttng_kprobes_event_handler_pre(struct kprobe *p, struct pt_regs *regs) { struct lttng_kernel_event_counter *event_counter = container_of(event, struct lttng_kernel_event_counter, parent); + struct lttng_kernel_event_counter_ctx event_counter_ctx; - (void) event_counter->chan->ops->event_counter_add(event_counter, 1); + event_counter_ctx.args_available = false; + (void) event_counter->chan->ops->counter_hit(event_counter, + NULL, NULL, &event_counter_ctx); break; } default: diff --git a/src/lttng-kretprobes.c b/src/lttng-kretprobes.c index 29a50e37..7bc38499 100644 --- a/src/lttng-kretprobes.c +++ b/src/lttng-kretprobes.c @@ -124,8 +124,11 @@ int _lttng_kretprobes_handler(struct kretprobe_instance *krpi, { struct lttng_kernel_event_counter *event_counter = container_of(event, struct lttng_kernel_event_counter, parent); + struct lttng_kernel_event_counter_ctx event_counter_ctx; - (void) event_counter->chan->ops->event_counter_add(event_counter, 1); + event_counter_ctx.args_available = false; + (void) event_counter->chan->ops->counter_hit(event_counter, + NULL, NULL, &event_counter_ctx); break; } default: diff --git a/src/lttng-uprobes.c b/src/lttng-uprobes.c index 8144a49e..1c81b9de 100644 --- a/src/lttng-uprobes.c +++ b/src/lttng-uprobes.c @@ -109,10 +109,13 @@ int lttng_uprobes_event_handler_pre(struct uprobe_consumer *uc, struct pt_regs * { struct lttng_kernel_event_counter *event_counter = container_of(event, struct lttng_kernel_event_counter, parent); + struct lttng_kernel_event_counter_ctx event_counter_ctx; + event_counter_ctx.args_available = false; /* uprobes is invoked with preemption enabled. */ rcu_read_lock_sched_notrace(); - (void) event_counter->chan->ops->event_counter_add(event_counter, 1); + (void) event_counter->chan->ops->counter_hit(event_counter, + NULL, NULL, &event_counter_ctx); rcu_read_unlock_sched_notrace(); break; }