lttng-ctl: implement listing of userspace probe locations
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 17 Oct 2017 21:22:43 +0000 (17:22 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 24 Aug 2018 19:28:41 +0000 (15:28 -0400)
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/common/sessiond-comm/sessiond-comm.h
src/common/userspace-probe.c
src/lib/lttng-ctl/lttng-ctl.c

index 62224bd75db8cf24f5e3ece8739eed6a51b6363e..56c925973038f51ea571a7ee177071e20ce5cb2a 100644 (file)
@@ -410,6 +410,11 @@ struct lttcomm_event_extended_header {
         * character.
         */
        uint32_t nb_exclusions;
+
+       /*
+        * Size of the event's userspace probe location (if applicable).
+        */
+       uint32_t userspace_probe_location_len;
 } LTTNG_PACKED;
 
 /*
index 6776d4b780c333e3453c606584bcaa316e5d2020..106fdadf6e82990b19d2f103c5b128d131284648 100644 (file)
@@ -415,6 +415,8 @@ int lttng_userspace_probe_location_serialize(
                goto end;
        }
 
+       memset(&location_generic_comm, 0, sizeof(location_generic_comm));
+
        location_generic_comm.type = (int8_t) location->type;
        if (buffer) {
                ret = lttng_dynamic_buffer_append(buffer, &location_generic_comm,
index 7df8d6de7d2dae5f3da1c299fab160ec76d6808a..c79cc6dd59eb251a7b5c237b1dd7e4c4108dcbe3 100644 (file)
@@ -1180,7 +1180,7 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
                        ret = lttng_userspace_probe_location_serialize(
                                ev_ext->probe_location, &send_buffer,
                                &fd_to_send);
-                       if (ret) {
+                       if (ret < 0) {
                                goto mem_error;
                        }
 
@@ -1932,9 +1932,8 @@ int lttng_list_events(struct lttng_handle *handle,
        size_t cmd_header_len;
        uint32_t nb_events, i;
        void *comm_ext_at;
-       void *listing_at;
        char *reception_buffer = NULL;
-       char *listing = NULL;
+       struct lttng_dynamic_buffer listing;
        size_t storage_req;
 
        /* Safety check. An handle and channel name are mandatory */
@@ -1970,12 +1969,12 @@ int lttng_list_events(struct lttng_handle *handle,
         * The buffer that is returned must contain a "flat" version of
         * the events that are returned. In other words, all pointers
         * within an lttng_event must point to a location within the returned
-        * buffer so that the user may free by simply calling free() on the
-        * returned buffer. This is needed in order to maintain API
+        * buffer so that the user may free everything by simply calling free()
+        * on the returned buffer. This is needed in order to maintain API
         * compatibility.
         *
-        * A first pass is performed to figure the size of the buffer that
-        * must be returned. A second pass is then performed to setup
+        * A first pass is performed to compute the size of the buffer that
+        * must be allocated. A second pass is then performed to setup
         * the returned events so that their members always point within the
         * buffer.
         *
@@ -1995,66 +1994,170 @@ int lttng_list_events(struct lttng_handle *handle,
        for (i = 0; i < nb_events; i++) {
                struct lttcomm_event_extended_header *ext_comm =
                        (struct lttcomm_event_extended_header *) comm_ext_at;
+               int probe_storage_req = 0;
 
                comm_ext_at += sizeof(*ext_comm);
                comm_ext_at += ext_comm->filter_len;
                comm_ext_at +=
                        ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
 
+               if (ext_comm->userspace_probe_location_len) {
+                       struct lttng_userspace_probe_location *probe_location = NULL;
+                       struct lttng_buffer_view probe_location_view;
+
+                       probe_location_view = lttng_buffer_view_init(
+                                       comm_ext_at, 0,
+                                       ext_comm->userspace_probe_location_len);
+
+                       /*
+                        * Create a temporary userspace probe location to
+                        * determine the size needed by a "flattened" version
+                        * of that same probe location.
+                        */
+                       ret = lttng_userspace_probe_location_create_from_buffer(
+                                       &probe_location_view, &probe_location);
+                       if (ret < 0) {
+                               ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+                               goto end;
+                       }
+
+                       ret = lttng_userspace_probe_location_flatten(
+                                       probe_location, NULL);
+                       lttng_userspace_probe_location_destroy(probe_location);
+                       if (ret < 0) {
+                               ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+                               goto end;
+                       }
+
+                       probe_storage_req = ret;
+                       comm_ext_at += ext_comm->userspace_probe_location_len;
+                       ret = 0;
+               }
+
                storage_req += sizeof(struct lttng_event_extended);
-               /* TODO: missing size of flat userspace probe. */
                storage_req += ext_comm->filter_len;
                storage_req += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
-               storage_req += storage_req % 8;
+               /* Padding to ensure the flat probe is aligned. */
+               storage_req = ALIGN_TO(storage_req, sizeof(uint64_t));
+               storage_req += probe_storage_req;
        }
 
-       listing = zmalloc(storage_req);
-       if (!listing) {
+       lttng_dynamic_buffer_init(&listing);
+       /*
+        * We must ensure that "listing" is never resized so as to preserve
+        * the validity of the flattened objects.
+        */
+       ret = lttng_dynamic_buffer_set_capacity(&listing, storage_req);
+       if (ret) {
+               ret = -LTTNG_ERR_NOMEM;
                goto end;
        }
-       memcpy(listing, reception_buffer,
-               nb_events * sizeof(struct lttng_event));
+
+       ret = lttng_dynamic_buffer_append(&listing, reception_buffer,
+                       nb_events * sizeof(struct lttng_event));
+       if (ret) {
+               ret = -LTTNG_ERR_NOMEM;
+               goto free_dynamic_buffer;
+       }
 
        comm_ext_at = reception_buffer +
-               (nb_events * sizeof(struct lttng_event));
-       listing_at = listing +
-               (nb_events * sizeof(struct lttng_event));
+                       (nb_events * sizeof(struct lttng_event));
        for (i = 0; i < nb_events; i++) {
                struct lttng_event *event = (struct lttng_event *)
-                       (listing + (sizeof(struct lttng_event) * i));
+                       (listing.data + (sizeof(struct lttng_event) * i));
                struct lttcomm_event_extended_header *ext_comm =
                        (struct lttcomm_event_extended_header *) comm_ext_at;
                struct lttng_event_extended *event_extended =
-                       (struct lttng_event_extended *) listing_at;
+                       (struct lttng_event_extended *)
+                               (listing.data + listing.size);
 
+               /* Insert struct lttng_event_extended. */
+               ret = lttng_dynamic_buffer_set_size(&listing,
+                               listing.size + sizeof(*event_extended));
+               if (ret) {
+                       ret = -LTTNG_ERR_NOMEM;
+                       goto free_dynamic_buffer;
+               }
                event->extended.ptr = event_extended;
-               listing_at += sizeof(*event_extended);
+
                comm_ext_at += sizeof(*ext_comm);
 
-               /* Copy filter expression. */
-               memcpy(listing_at, comm_ext_at, ext_comm->filter_len);
-               event_extended->filter_expression = listing_at;
-               comm_ext_at += ext_comm->filter_len;
-               listing_at += ext_comm->filter_len;
+               /* Insert filter expression. */
+               if (ext_comm->filter_len) {
+                       event_extended->filter_expression = listing.data +
+                                       listing.size;
+                       ret = lttng_dynamic_buffer_append(&listing, comm_ext_at,
+                                       ext_comm->filter_len);
+                       if (ret) {
+                               ret = -LTTNG_ERR_NOMEM;
+                               goto free_dynamic_buffer;
+                       }
+                       comm_ext_at += ext_comm->filter_len;
+               }
+
+               /* Insert exclusions. */
+               if (ext_comm->nb_exclusions) {
+                       event_extended->exclusions.count =
+                                       ext_comm->nb_exclusions;
+                       event_extended->exclusions.strings =
+                                       listing.data + listing.size;
+
+                       ret = lttng_dynamic_buffer_append(&listing,
+                                       comm_ext_at,
+                                       ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN);
+                       if (ret) {
+                               ret = -LTTNG_ERR_NOMEM;
+                       }
+                       comm_ext_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
+               }
+
+               /* Insert padding to align to 64-bits. */
+               ret = lttng_dynamic_buffer_set_size(&listing,
+                               ALIGN_TO(listing.size, sizeof(uint64_t)));
+               if (ret) {
+                       ret = -LTTNG_ERR_NOMEM;
+                       goto free_dynamic_buffer;
+               }
+
+               /* Insert flattened userspace probe location. */
+               if (ext_comm->userspace_probe_location_len) {
+                       struct lttng_userspace_probe_location *probe_location = NULL;
+                       struct lttng_buffer_view probe_location_view;
 
-               /* Copy exclusions. */
-               event_extended->exclusions.count = ext_comm->nb_exclusions;
-               event_extended->exclusions.strings = listing_at;
-               memcpy(listing_at, comm_ext_at,
-                       ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN);
-               listing_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
-               comm_ext_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
+                       probe_location_view = lttng_buffer_view_init(
+                                       comm_ext_at, 0,
+                                       ext_comm->userspace_probe_location_len);
 
-               listing_at += ((uintptr_t) listing_at) % 8;
+                       ret = lttng_userspace_probe_location_create_from_buffer(
+                                       &probe_location_view, &probe_location);
+                       if (ret < 0) {
+                               ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+                               goto free_dynamic_buffer;
+                       }
+
+                       event_extended->probe_location = (struct lttng_userspace_probe_location *)
+                                       (listing.data + listing.size);
+                       ret = lttng_userspace_probe_location_flatten(
+                                       probe_location, &listing);
+                       lttng_userspace_probe_location_destroy(probe_location);
+                       if (ret < 0) {
+                               ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+                               goto free_dynamic_buffer;
+                       }
+
+                       comm_ext_at += ext_comm->userspace_probe_location_len;
+               }
        }
 
-       *events = (struct lttng_event *) listing;
-       listing = NULL;
+       /* Don't reset listing buffer as we return its content. */
+       *events = (struct lttng_event *) listing.data;
+       lttng_dynamic_buffer_init(&listing);
        ret = (int) nb_events;
+free_dynamic_buffer:
+       lttng_dynamic_buffer_reset(&listing);
 end:
        free(cmd_header);
        free(reception_buffer);
-       free(listing);
        return ret;
 }
 
This page took 0.0347 seconds and 4 git commands to generate.