From: Jérémie Galarneau Date: Mon, 16 Oct 2017 16:18:17 +0000 (-0400) Subject: lttng-ctl: locate extended event attributes at reception X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=commitdiff_plain;h=de453daa7054455a39fac38fb74306fc12349f54 lttng-ctl: locate extended event attributes at reception Locate the lttng_event's extended attributes at the time of reception instead of locating them on access. This is mostly preparation work for the addition of userspace probe locations to the protocol. Signed-off-by: Jérémie Galarneau --- diff --git a/src/lib/lttng-ctl/event.c b/src/lib/lttng-ctl/event.c index 691b4f95c..9413b7052 100644 --- a/src/lib/lttng-ctl/event.c +++ b/src/lib/lttng-ctl/event.c @@ -78,16 +78,15 @@ int lttng_event_get_filter_expression(struct lttng_event *event, const char **filter_expression) { int ret = 0; - struct lttcomm_event_extended_header *ext_header; + struct lttng_event_extended *event_extended; if (!event || !filter_expression) { ret = -LTTNG_ERR_INVALID; goto end; } - ext_header = event->extended.ptr; - - if (!ext_header) { + event_extended = (struct lttng_event_extended *) event->extended.ptr; + if (!event_extended) { /* * This can happen since the lttng_event structure is * used for other tasks where this pointer is never set. @@ -96,42 +95,35 @@ int lttng_event_get_filter_expression(struct lttng_event *event, goto end; } - if (ext_header->filter_len) { - *filter_expression = ((const char *) (ext_header)) + - sizeof(*ext_header); - } else { - *filter_expression = NULL; - } - + *filter_expression = event_extended->filter_expression; end: return ret; } int lttng_event_get_exclusion_name_count(struct lttng_event *event) { - int ret; - struct lttcomm_event_extended_header *ext_header; + int ret = 0; + struct lttng_event_extended *event_extended; if (!event) { ret = -LTTNG_ERR_INVALID; goto end; } - ext_header = event->extended.ptr; - if (!ext_header) { + event_extended = (struct lttng_event_extended *) event->extended.ptr; + if (!event_extended) { /* * This can happen since the lttng_event structure is * used for other tasks where this pointer is never set. */ - ret = 0; goto end; } - if (ext_header->nb_exclusions > INT_MAX) { + if (event_extended->exclusions.count > INT_MAX) { ret = -LTTNG_ERR_OVERFLOW; goto end; } - ret = (int) ext_header->nb_exclusions; + ret = (int) event_extended->exclusions.count; end: return ret; } @@ -140,30 +132,35 @@ int lttng_event_get_exclusion_name(struct lttng_event *event, size_t index, const char **exclusion_name) { int ret = 0; - struct lttcomm_event_extended_header *ext_header; - void *at; + struct lttng_event_extended *event_extended; if (!event || !exclusion_name) { ret = -LTTNG_ERR_INVALID; goto end; } - ext_header = event->extended.ptr; - if (!ext_header) { - ret = -LTTNG_ERR_INVALID; + if (index > UINT_MAX) { + ret = -LTTNG_ERR_OVERFLOW; goto end; } - if (index >= ext_header->nb_exclusions) { + event_extended = (struct lttng_event_extended *) event->extended.ptr; + if (!event_extended) { + /* + * This can happen since the lttng_event structure is + * used for other tasks where this pointer is never set. + */ ret = -LTTNG_ERR_INVALID; goto end; } - at = (void *) ext_header + sizeof(*ext_header); - at += ext_header->filter_len; - at += index * LTTNG_SYMBOL_NAME_LEN; - *exclusion_name = at; + if (index >= event_extended->exclusions.count) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + *exclusion_name = event_extended->exclusions.strings + + (index * LTTNG_SYMBOL_NAME_LEN); end: return ret; } diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index eadb00eda..197e52e8f 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -34,11 +34,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "filter/filter-ast.h" #include "filter/filter-parser.h" @@ -1895,7 +1897,11 @@ int lttng_list_events(struct lttng_handle *handle, struct lttcomm_event_command_header *cmd_header = NULL; size_t cmd_header_len; uint32_t nb_events, i; - void *extended_at; + void *comm_ext_at; + void *listing_at; + char *reception_buffer = NULL; + char *listing = NULL; + size_t storage_req; /* Safety check. An handle and channel name are mandatory */ if (handle == NULL || channel_name == NULL) { @@ -1911,42 +1917,110 @@ int lttng_list_events(struct lttng_handle *handle, lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm, NULL, 0, NULL, 0, - (void **) events, (void **) &cmd_header, &cmd_header_len); + (void **) &reception_buffer, (void **) &cmd_header, + &cmd_header_len); if (ret < 0) { - goto error; + goto end; } /* Set number of events and free command header */ nb_events = cmd_header->nb_events; if (nb_events > INT_MAX) { ret = -EOVERFLOW; - goto error; + goto end; } - ret = (int) nb_events; free(cmd_header); cmd_header = NULL; - /* Set extended info pointers */ - extended_at = ((void*) (*events)) + - nb_events * sizeof(struct lttng_event); + /* + * 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 + * 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 + * the returned events so that their members always point within the + * buffer. + * + * The layout of the returned buffer is as follows: + * - struct lttng_event[nb_events], + * - nb_events times the following: + * - struct lttng_event_extended, + * - flattened version of userspace_probe_location + * - filter_expression + * - exclusions + * - padding to align to 64-bits + */ + comm_ext_at = reception_buffer + + (nb_events * sizeof(struct lttng_event)); + storage_req = nb_events * sizeof(struct lttng_event); for (i = 0; i < nb_events; i++) { - struct lttcomm_event_extended_header *ext_header; - struct lttng_event *event = &(*events)[i]; + struct lttcomm_event_extended_header *ext_comm = + (struct lttcomm_event_extended_header *) comm_ext_at; - event->extended.ptr = extended_at; - ext_header = - (struct lttcomm_event_extended_header *) extended_at; - extended_at += sizeof(*ext_header); - extended_at += ext_header->filter_len; - extended_at += - ext_header->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; + comm_ext_at += sizeof(*ext_comm); + comm_ext_at += ext_comm->filter_len; + comm_ext_at += + ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; + + 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; } - return ret; -error: + listing = zmalloc(storage_req); + if (!listing) { + goto end; + } + memcpy(listing, reception_buffer, + nb_events * sizeof(struct lttng_event)); + + comm_ext_at = reception_buffer + + (nb_events * sizeof(struct lttng_event)); + listing_at = listing + + (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)); + 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; + + 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; + + /* 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; + + listing_at += ((uintptr_t) listing_at) % 8; + } + + *events = (struct lttng_event *) listing; + listing = NULL; + ret = (int) nb_events; +end: free(cmd_header); - free(*events); + free(reception_buffer); + free(listing); return ret; }