Introduce extension points for trace hit counters
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 23 Jul 2024 19:20:51 +0000 (15:20 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 26 Jul 2024 20:05:27 +0000 (16:05 -0400)
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 <mathieu.desnoyers@efficios.com>
include/lttng/abi.h
include/lttng/events-internal.h
include/lttng/events.h
include/lttng/tracepoint-event-impl.h
src/lttng-abi.c
src/lttng-counter-client-percpu-32-modular.c
src/lttng-counter-client-percpu-64-modular.c
src/lttng-events.c
src/lttng-kprobes.c
src/lttng-kretprobes.c
src/lttng-uprobes.c

index 7b26dafc5b238e87ef1498ea88c399b15e489086..8f0a1472350cf626072c7e7c70f9221c46023304 100644 (file)
@@ -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;
index 55d34c443faed001a0c9018219a24d3cb158a4d5..224bfec1854e876df063c12ed766784b094b607a 100644 (file)
@@ -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 {
index ba30c2b7108d27584901c0ead4e4e751d4454c79..8c04ec280820dd663ba5ab5e7dfc9ea3c5c9c0fb 100644 (file)
@@ -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 {
index e047950a9af2ad667dc49426c6d6ada0bd50325c..a0053044f722cba42831e5babf4ab1d979cc98b8 100644 (file)
@@ -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:                                                                        \
index 97fbfe9524d59a9cf5303449297c6d66532e7fab..5a3b616fddc7d9daac92c3cf422a48cd641b9eab 100644 (file)
@@ -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:
index b8b79a7e5be7d98cd7b87c05082461a4eb6b9cdf..eb9d74d898f57142a510fe9dba56cd1442c534e6 100644 (file)
@@ -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,
        },
 };
 
index 4ff38a3efe7c132ba1fba5c1c753a4f56427d3b8..829e6a7020f02099823338ab20a329c776901dc5 100644 (file)
@@ -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,
        },
 };
 
index 8a6c6478d3b4bf9e75bd09489cebab80319efd1b..95184984d27cc15721080da921a950fd7f4fb0c9 100644 (file)
@@ -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;
 
index 5fa2a11a5db53c71a4ed41de8d64af2f4fd4a1d8..75eb414140de0b852cc17c2542737a20c0a6925a 100644 (file)
@@ -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:
index 29a50e37091da7e47ac6f46a8d6fd8a85651229c..7bc3849926a282d96f57b44472d6ccdb2dc83e86 100644 (file)
@@ -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:
index 8144a49e264457e9ce226910334e29e28321a821..1c81b9de5ee8cbdaef7639fb3735a3afe51b4d7e 100644 (file)
@@ -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;
        }
This page took 0.038211 seconds and 4 git commands to generate.