Implement extensible LTTNG_UST_ABI_COUNTER_EVENT protocol command
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 13 Apr 2022 20:24:52 +0000 (16:24 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 12 Jul 2024 15:39:51 +0000 (11:39 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: Ib0414f90ab74d21e6847e79062bd7b5236e2097b

include/lttng/ust-abi.h
include/lttng/ust-ctl.h
src/common/events.h
src/lib/lttng-ust-ctl/ustctl.c
src/lib/lttng-ust/events.h
src/lib/lttng-ust/lttng-events.c
src/lib/lttng-ust/lttng-ust-abi.c
src/lib/lttng-ust/lttng-ust-comm.c

index e9d77c74c324ddda39e7537dd2034cd9d7301e22..a995e3ac00970609832a3c973dafe169f596b490 100644 (file)
@@ -107,8 +107,6 @@ struct lttng_ust_abi_event_notifier_notification {
        char padding[LTTNG_UST_ABI_EVENT_NOTIFIER_NOTIFICATION_PADDING];
 } __attribute__((packed));
 
-#define LTTNG_UST_ABI_COUNTER_DIMENSION_MAX 4
-
 enum lttng_ust_abi_key_token_type {
        LTTNG_UST_ABI_KEY_TOKEN_STRING = 0,             /* arg: strtab_offset. */
        LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME = 1,         /* no arg. */
@@ -125,33 +123,35 @@ enum lttng_ust_abi_counter_bitness {
        LTTNG_UST_ABI_COUNTER_BITNESS_64 = 1,
 };
 
-#define LTTNG_UST_ABI_KEY_ARG_PADDING1         256
-#define LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX 256
+#define LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX 4096
+
+struct lttng_ust_abi_counter_key_string {
+       uint32_t string_len;            /* string length (includes \0) */
+       char str[];                     /* Null-terminated string. */
+} __attribute__((packed));
+
 struct lttng_ust_abi_key_token {
-       uint32_t type;  /* enum lttng_ust_key_token_type */
-       union {
-               char string[LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX];
-               char padding[LTTNG_UST_ABI_KEY_ARG_PADDING1];
-       } arg;
+       uint32_t len;                           /* length of this structure. */
+       uint32_t type;                          /* enum lttng_ust_key_token_type */
+
+       /* Followed by a struct lttng_ust_abi_counter_key_string for LTTNG_UST_ABI_KEY_TOKEN_STRING. */
 } __attribute__((packed));
 
-#define LTTNG_UST_ABI_NR_KEY_TOKEN 4
 struct lttng_ust_abi_counter_key_dimension {
+       uint32_t len;                           /* length of this structure */
        uint32_t nr_key_tokens;
-       struct lttng_ust_abi_key_token key_tokens[LTTNG_UST_ABI_NR_KEY_TOKEN];
-} __attribute__((packed));
 
-#define LTTNG_UST_ABI_COUNTER_DIMENSION_MAX 4
-struct lttng_ust_abi_counter_key {
-       uint32_t nr_dimensions;
-       struct lttng_ust_abi_counter_key_dimension key_dimensions[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX];
+       /* Followed by a variable-length array of key tokens */
 } __attribute__((packed));
 
-#define LTTNG_UST_ABI_COUNTER_EVENT_PADDING1   16
+#define LTTNG_UST_ABI_COUNTER_EVENT_MAX_LEN    4096U
 struct lttng_ust_abi_counter_event {
+       uint32_t len;                           /* length of this structure */
+
        struct lttng_ust_abi_event event;
-       struct lttng_ust_abi_counter_key key;
-       char padding[LTTNG_UST_ABI_COUNTER_EVENT_PADDING1];
+       uint32_t number_key_dimensions;         /* array of dimensions is an array of var. len. elements. */
+
+       /* Followed by a variable-length array of key dimensions */
 } __attribute__((packed));
 
 enum lttng_ust_abi_counter_dimension_flags {
@@ -180,12 +180,6 @@ struct lttng_ust_abi_counter_conf {
        uint32_t elem_len;                      /* array stride (size of lttng_ust_abi_counter_dimension) */
 } __attribute__((packed));
 
-struct lttng_ust_abi_counter_value {
-       uint32_t number_dimensions;
-       uint64_t dimension_indexes[LTTNG_UST_ABI_COUNTER_DIMENSION_MAX];
-       int64_t value;
-} __attribute__((packed));
-
 #define LTTNG_UST_ABI_COUNTER_DATA_MAX_LEN     4096U
 struct lttng_ust_abi_counter {
        uint64_t len;
index e244b997c6bd0c9583f6d3d32e3ad7c2dbfe48dd..07f08ca79ca5fd6d7e0ad4f9b72a2e0db651b832 100644 (file)
@@ -660,6 +660,7 @@ int lttng_ust_ctl_counter_clear(struct lttng_ust_ctl_daemon_counter *counter,
 
 int lttng_ust_ctl_counter_create_event(int sock,
                struct lttng_ust_abi_counter_event *counter_event,
+               size_t counter_event_len,
                struct lttng_ust_abi_object_data *counter_data,
                struct lttng_ust_abi_object_data **counter_event_data);
 
index bc085ffc0128cc995eead1467d9176ab26f8379c..94e8038bcceb465189c8da65b4b639fac833c6c3 100644 (file)
@@ -52,6 +52,9 @@ union lttng_ust_abi_args {
        struct {
                int shm_fd;
        } counter_shm;
+       struct {
+               uint32_t len;
+       } counter_event;
 };
 
 struct lttng_ust_abi_objd_ops {
@@ -71,7 +74,7 @@ enum lttng_key_token_type {
        LTTNG_KEY_TOKEN_PROVIDER_NAME = 2,
 };
 
-#define LTTNG_KEY_TOKEN_STRING_LEN_MAX LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX
+#define LTTNG_KEY_TOKEN_STRING_LEN_MAX 4096
 struct lttng_key_token {
        enum lttng_key_token_type type;
        union {
@@ -79,13 +82,13 @@ struct lttng_key_token {
        } arg;
 };
 
-#define LTTNG_NR_KEY_TOKEN LTTNG_UST_ABI_NR_KEY_TOKEN
+#define LTTNG_NR_KEY_TOKEN 8
 struct lttng_counter_key_dimension {
        size_t nr_key_tokens;
        struct lttng_key_token key_tokens[LTTNG_NR_KEY_TOKEN];
 };
 
-#define LTTNG_COUNTER_DIMENSION_MAX LTTNG_UST_ABI_COUNTER_DIMENSION_MAX
+#define LTTNG_COUNTER_DIMENSION_MAX 4
 struct lttng_counter_key {
        size_t nr_dimensions;
        struct lttng_counter_key_dimension key_dimensions[LTTNG_COUNTER_DIMENSION_MAX];
index 3a2e58f66e57889e6cc2de08e85681c7dd5c4d43..53d63c6daeb4a7b9719bd4ce04aa585f790a6f83 100644 (file)
@@ -3318,6 +3318,7 @@ int lttng_ust_ctl_counter_clear(struct lttng_ust_ctl_daemon_counter *counter,
  */
 int lttng_ust_ctl_counter_create_event(int sock,
                struct lttng_ust_abi_counter_event *counter_event,
+               size_t counter_event_len,
                struct lttng_ust_abi_object_data *counter_data,
                struct lttng_ust_abi_object_data **_counter_event_data)
 {
@@ -3337,15 +3338,15 @@ int lttng_ust_ctl_counter_create_event(int sock,
        memset(&lum, 0, sizeof(lum));
        lum.handle = counter_data->handle;
        lum.cmd = LTTNG_UST_ABI_COUNTER_EVENT;
-       lum.u.counter_event.len = sizeof(*counter_event);
+       lum.u.counter_event.len = counter_event_len;
        ret = ustcomm_send_app_cmd(sock, &lum, &lur);
        if (ret) {
                free(counter_event_data);
                return ret;
        }
        /* Send struct lttng_ust_counter_event */
-       len = ustcomm_send_unix_sock(sock, counter_event, sizeof(*counter_event));
-       if (len != sizeof(*counter_event)) {
+       len = ustcomm_send_unix_sock(sock, counter_event, counter_event_len);
+       if (len != counter_event_len) {
                free(counter_event_data);
                if (len < 0)
                        return len;
index 093d8d09b25479aef129d13898faf3650d3de767..3fd58aa4600ee034c0f861321aedbae93e874291 100644 (file)
@@ -29,8 +29,8 @@ struct lttng_event_recorder_enabler *lttng_event_recorder_enabler_create(
  */
 struct lttng_event_counter_enabler *lttng_event_counter_enabler_create(
                enum lttng_enabler_format_type format_type,
-               const struct lttng_ust_abi_event *event_param,
-               const struct lttng_ust_abi_counter_key *key,
+               const struct lttng_ust_abi_counter_event *counter_event,
+               const struct lttng_counter_key *key,
                struct lttng_ust_channel_counter *chan)
        __attribute__((visibility("hidden")));
 
index 69a6c7b4c3e72cbee9ee398265a19ff69e3d0332..82da68f6f27662cebd4dd82e9d545e7c3857cb1d 100644 (file)
@@ -1692,59 +1692,6 @@ void lttng_ust_abi_events_exit(void)
                lttng_session_destroy(session_priv->pub);
 }
 
-static
-int copy_counter_key(struct lttng_counter_key *key,
-                    const struct lttng_ust_abi_counter_key *key_param)
-{
-       size_t i, j, nr_dimensions;
-
-       nr_dimensions = key_param->nr_dimensions;
-       if (nr_dimensions > LTTNG_UST_ABI_COUNTER_DIMENSION_MAX)
-               return -EINVAL;
-       key->nr_dimensions = nr_dimensions;
-       for (i = 0; i < nr_dimensions; i++) {
-               const struct lttng_ust_abi_counter_key_dimension *udim =
-                       &key_param->key_dimensions[i];
-               struct lttng_counter_key_dimension *dim =
-                       &key->key_dimensions[i];
-               size_t nr_key_tokens;
-
-               nr_key_tokens = udim->nr_key_tokens;
-               if (!nr_key_tokens || nr_key_tokens > LTTNG_UST_ABI_NR_KEY_TOKEN)
-                       return -EINVAL;
-               dim->nr_key_tokens = nr_key_tokens;
-               for (j = 0; j < nr_key_tokens; j++) {
-                       const struct lttng_ust_abi_key_token *utoken =
-                               &udim->key_tokens[j];
-                       struct lttng_key_token *token =
-                               &dim->key_tokens[j];
-
-                       switch (utoken->type) {
-                       case LTTNG_UST_ABI_KEY_TOKEN_STRING:
-                       {
-                               size_t len;
-
-                               token->type = LTTNG_UST_ABI_KEY_TOKEN_STRING;
-                               len = strnlen(utoken->arg.string, LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX);
-                               if (!len || len >= LTTNG_UST_ABI_KEY_TOKEN_STRING_LEN_MAX)
-                                       return -EINVAL;
-                               strcpy(token->arg.string, utoken->arg.string);
-                               break;
-                       }
-                       case LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME:
-                               token->type = LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME;
-                               break;
-                       case LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME:
-                               token->type = LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME;
-                               break;
-                       default:
-                               return -EINVAL;
-                       }
-               }
-       }
-       return 0;
-}
-
 /*
  * Enabler management.
  */
@@ -1777,8 +1724,8 @@ struct lttng_event_recorder_enabler *lttng_event_recorder_enabler_create(
 
 struct lttng_event_counter_enabler *lttng_event_counter_enabler_create(
                enum lttng_enabler_format_type format_type,
-               const struct lttng_ust_abi_event *event_param,
-               const struct lttng_ust_abi_counter_key *key,
+               const struct lttng_ust_abi_counter_event *counter_event,
+               const struct lttng_counter_key *key,
                struct lttng_ust_channel_counter *chan)
 {
        struct lttng_event_counter_enabler *event_enabler;
@@ -1790,18 +1737,13 @@ struct lttng_event_counter_enabler *lttng_event_counter_enabler_create(
        event_enabler->parent.parent.format_type = format_type;
        CDS_INIT_LIST_HEAD(&event_enabler->parent.parent.filter_bytecode_head);
        CDS_INIT_LIST_HEAD(&event_enabler->parent.parent.excluder_head);
-       memcpy(&event_enabler->parent.parent.event_param, event_param,
+       memcpy(&event_enabler->parent.parent.event_param, &counter_event->event,
                sizeof(event_enabler->parent.parent.event_param));
        event_enabler->chan = chan;
-       if (key) {
-               if (copy_counter_key(&event_enabler->key, key)) {
-                       free(event_enabler);
-                       return NULL;
-               }
-       }
+       memcpy(&event_enabler->key, key, sizeof(struct lttng_counter_key));
        /* ctx left NULL */
        event_enabler->parent.parent.enabled = 0;
-       event_enabler->parent.parent.user_token = event_param->token;
+       event_enabler->parent.parent.user_token = counter_event->event.token;
        event_enabler->parent.chan = chan->parent;
        cds_list_add(&event_enabler->parent.node, &event_enabler->chan->parent->session->priv->enablers_head);
        lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session);
index d71a818d0313668cd9b3f6b5dbb6aa4a9e4d44bb..f9bddd012a03b7be0c1f1e9b824aac6af6115c2a 100644 (file)
@@ -1367,18 +1367,118 @@ objd_error:
        return ret;
 }
 
+static
+int copy_counter_key(struct lttng_counter_key *internal_key,
+                    unsigned long arg, size_t arg_len,
+                    const struct lttng_ust_abi_counter_event *counter_event)
+{
+       size_t i, j, nr_dimensions, offset = 0;
+       char *addr = (char *)arg;
+       int ret;
+
+       nr_dimensions = counter_event->number_key_dimensions;
+       if (nr_dimensions != 1)
+               return -EINVAL;
+       internal_key->nr_dimensions = nr_dimensions;
+       offset += counter_event->len;
+       for (i = 0; i < nr_dimensions; i++) {
+               const struct lttng_ust_abi_counter_key_dimension *abi_dim;
+               struct lttng_ust_abi_counter_key_dimension dim;
+               struct lttng_counter_key_dimension *internal_dim = &internal_key->key_dimensions[i];
+               size_t nr_key_tokens;
+
+               abi_dim = (const struct lttng_ust_abi_counter_key_dimension *)(addr + offset);
+               offset += abi_dim->len;
+               if (offset > arg_len || abi_dim->len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_key_dimension, nr_key_tokens))
+                       return -EINVAL;
+               ret = copy_abi_struct(&dim, sizeof(dim), abi_dim, abi_dim->len);
+               if (ret)
+                       return ret;
+               nr_key_tokens = dim.nr_key_tokens;
+               if (!nr_key_tokens || nr_key_tokens > LTTNG_NR_KEY_TOKEN)
+                       return -EINVAL;
+               internal_dim->nr_key_tokens = nr_key_tokens;
+               for (j = 0; j < nr_key_tokens; j++) {
+                       const struct lttng_ust_abi_key_token *abi_token;
+                       struct lttng_ust_abi_key_token token;
+                       struct lttng_key_token *internal_token = &internal_dim->key_tokens[j];
+
+                       abi_token = (const struct lttng_ust_abi_key_token *)(addr + offset);
+                       offset += abi_token->len;
+                       if (offset > arg_len || abi_token->len < lttng_ust_offsetofend(struct lttng_ust_abi_key_token, type))
+                               return -EINVAL;
+                       ret = copy_abi_struct(&token, sizeof(token), abi_token, abi_token->len);
+                       if (ret)
+                               return ret;
+                       switch (token.type) {
+                       case LTTNG_UST_ABI_KEY_TOKEN_STRING:
+                       {
+                               const struct lttng_ust_abi_counter_key_string *abi_key_string;
+
+                               abi_key_string = (const struct lttng_ust_abi_counter_key_string *)(addr + offset);
+                               offset += sizeof(struct lttng_ust_abi_counter_key_string);
+                               if (offset > arg_len)
+                                       return -EINVAL;
+                               internal_token->type = LTTNG_KEY_TOKEN_STRING;
+                               if (!abi_key_string->string_len || abi_key_string->string_len > LTTNG_KEY_TOKEN_STRING_LEN_MAX)
+                                       return -EINVAL;
+                               offset += abi_key_string->string_len;
+                               if (offset > arg_len)
+                                       return -EINVAL;
+                               if (abi_key_string->str[abi_key_string->string_len - 1] != '\0' ||
+                                               strlen(abi_key_string->str) + 1 != abi_key_string->string_len)
+                                       return -EINVAL;
+                               memcpy(internal_token->arg.string, abi_key_string->str, abi_key_string->string_len);
+                               break;
+                       }
+                       case LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME:
+                               internal_token->type = LTTNG_KEY_TOKEN_EVENT_NAME;
+                               break;
+                       case LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME:
+                               internal_token->type = LTTNG_KEY_TOKEN_PROVIDER_NAME;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+       }
+       return 0;
+}
+
 static
 int lttng_abi_create_event_counter_enabler(int channel_objd,
                        struct lttng_ust_channel_counter *channel,
-                       struct lttng_ust_abi_event *event_param,
-                       const struct lttng_ust_abi_counter_key *key_param,
-                       void *owner,
-                       enum lttng_enabler_format_type format_type)
+                       unsigned long arg, size_t arg_len, void *owner)
 {
+       struct lttng_ust_abi_counter_event *abi_counter_event = (struct lttng_ust_abi_counter_event *)arg;
+       struct lttng_ust_abi_counter_event counter_event = {};
+       struct lttng_counter_key counter_key = {};
        struct lttng_event_counter_enabler *enabler;
+       enum lttng_enabler_format_type format_type;
        int event_objd, ret;
 
-       event_param->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
+       if (arg_len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_event, number_key_dimensions)) {
+               return -EINVAL;
+       }
+       if (arg_len < abi_counter_event->len ||
+                       abi_counter_event->len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_event, number_key_dimensions)) {
+               return -EINVAL;
+       }
+       ret = copy_abi_struct(&counter_event, sizeof(counter_event),
+                       abi_counter_event, abi_counter_event->len);
+       if (ret) {
+               return ret;
+       }
+       counter_event.event.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
+       if (strutils_is_star_glob_pattern(counter_event.event.name)) {
+               format_type = LTTNG_ENABLER_FORMAT_STAR_GLOB;
+       } else {
+               format_type = LTTNG_ENABLER_FORMAT_EVENT;
+       }
+       ret = copy_counter_key(&counter_key, arg, arg_len, &counter_event);
+       if (ret) {
+               return ret;
+       }
        event_objd = objd_alloc(NULL, &lttng_event_enabler_ops, owner,
                "event enabler");
        if (event_objd < 0) {
@@ -1389,8 +1489,7 @@ int lttng_abi_create_event_counter_enabler(int channel_objd,
         * We tolerate no failure path after event creation. It will stay
         * invariant for the rest of the session.
         */
-       enabler = lttng_event_counter_enabler_create(format_type, event_param,
-                       key_param, channel);
+       enabler = lttng_event_counter_enabler_create(format_type, &counter_event, &counter_key, channel);
        if (!enabler) {
                ret = -ENOMEM;
                goto event_error;
@@ -1595,24 +1694,8 @@ long lttng_counter_cmd(int objd, unsigned int cmd, unsigned long arg,
        }
        case LTTNG_UST_ABI_COUNTER_EVENT:
        {
-               struct lttng_ust_abi_counter_event *counter_event_param =
-                       (struct lttng_ust_abi_counter_event *) arg;
-               struct lttng_ust_abi_event *event_param = &counter_event_param->event;
-               struct lttng_ust_abi_counter_key *key_param = &counter_event_param->key;
-
-               if (strutils_is_star_glob_pattern(event_param->name)) {
-                       /*
-                        * If the event name is a star globbing pattern,
-                        * we create the special star globbing enabler.
-                        */
-                       return lttng_abi_create_event_counter_enabler(objd, counter,
-                                       event_param, key_param, owner,
-                                       LTTNG_ENABLER_FORMAT_STAR_GLOB);
-               } else {
-                       return lttng_abi_create_event_counter_enabler(objd, counter,
-                                       event_param, key_param, owner,
-                                       LTTNG_ENABLER_FORMAT_EVENT);
-               }
+               return lttng_abi_create_event_counter_enabler(objd, counter,
+                               arg, uargs->counter_event.len, owner);
        }
        case LTTNG_UST_ABI_ENABLE:
                return lttng_channel_enable(counter->parent);
index 423cedbcd7104602a47b63404cf451c75bf48476..fe2437b8f9fbb811b01ef11d4297c4fef98b011a 100644 (file)
@@ -1058,6 +1058,7 @@ int handle_message(struct sock_info *sock_info,
        union lttng_ust_abi_args args;
        char ctxstr[LTTNG_UST_ABI_SYM_NAME_LEN];        /* App context string. */
        ssize_t len;
+       struct lttng_ust_abi_counter_event *counter_event = NULL;
 
        memset(&lur, 0, sizeof(lur));
 
@@ -1486,20 +1487,24 @@ int handle_message(struct sock_info *sock_info,
        case LTTNG_UST_ABI_COUNTER_EVENT:
        {
                /* Receive struct lttng_ust_abi_counter_event */
-               struct lttng_ust_abi_counter_event counter_event;
-
-               if (sizeof(counter_event) != lum->u.counter_event.len) {
-                       DBG("incorrect counter event data message size: %u", lum->u.counter_event.len);
+               if (lum->u.counter_event.len > LTTNG_UST_ABI_COUNTER_EVENT_MAX_LEN) {
+                       DBG("counter event data message too large: %u", lum->u.counter_event.len);
                        ret = -EINVAL;
                        goto error;
                }
-               len = ustcomm_recv_unix_sock(sock, &counter_event, sizeof(counter_event));
+               args.counter_event.len = lum->u.counter_event.len;
+               counter_event = zmalloc(lum->u.counter_event.len);
+               if (!counter_event) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
+               len = ustcomm_recv_unix_sock(sock, counter_event, lum->u.counter_event.len);
                switch (len) {
                case 0: /* orderly shutdown */
                        ret = 0;
                        goto error;
                default:
-                       if (len == sizeof(counter_event)) {
+                       if (len == lum->u.counter_event.len) {
                                DBG("counter event data received");
                                break;
                        } else if (len < 0) {
@@ -1519,7 +1524,7 @@ int handle_message(struct sock_info *sock_info,
                }
                if (ops->cmd)
                        ret = ops->cmd(lum->handle, lum->cmd,
-                                       (unsigned long) &counter_event,
+                                       (unsigned long) counter_event,
                                        &args, sock_info);
                else
                        ret = -ENOSYS;
@@ -1636,6 +1641,7 @@ int handle_message(struct sock_info *sock_info,
 error:
        ust_unlock();
 
+       free(counter_event);
        return ret;
 }
 
This page took 0.032302 seconds and 4 git commands to generate.