X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Flttng-ctl.c;h=7df8d6de7d2dae5f3da1c299fab160ec76d6808a;hb=1a1c3874df33e6f252c62830d29dafa85f3e423e;hp=eadb00eda37af2fb293723aab83aa237f9515144;hpb=a04d53fc9a0dd3a5d6f9be82d475dfec48205ac0;p=lttng-tools.git diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index eadb00eda..7df8d6de7 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -30,15 +30,19 @@ #include #include +#include #include #include #include #include +#include #include #include #include #include #include +#include +#include #include "filter/filter-ast.h" #include "filter/filter-parser.h" @@ -1024,8 +1028,9 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, int exclusion_count, char **exclusion_list) { struct lttcomm_session_msg lsm; - char *varlen_data; - int ret = 0; + struct lttng_dynamic_buffer send_buffer; + int ret = 0, i, fd_to_send = -1; + bool send_fd = false; unsigned int free_filter_expression = 0; struct filter_parser_ctx *ctx = NULL; /* @@ -1076,22 +1081,11 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, lsm.u.enable.exclusion_count = exclusion_count; lsm.u.enable.bytecode_len = 0; - /* - * For the JUL domain, a filter is enforced except for the enable all - * event. This is done to avoid having the event in all sessions thus - * filtering by logger name. - */ - if (exclusion_count == 0 && filter_expression == NULL && - (handle->domain.type != LTTNG_DOMAIN_JUL && - handle->domain.type != LTTNG_DOMAIN_LOG4J && - handle->domain.type != LTTNG_DOMAIN_PYTHON)) { - goto ask_sessiond; - } - /* * We have either a filter or some exclusions, so we need to set up * a variable-length memory block from where to send the data. */ + lttng_dynamic_buffer_init(&send_buffer); /* Parse filter expression. */ if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL @@ -1129,41 +1123,82 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, } } - varlen_data = zmalloc(lsm.u.enable.bytecode_len + ret = lttng_dynamic_buffer_set_capacity(&send_buffer, + lsm.u.enable.bytecode_len + lsm.u.enable.expression_len + LTTNG_SYMBOL_NAME_LEN * exclusion_count); - if (!varlen_data) { + if (ret) { ret = -LTTNG_ERR_EXCLUSION_NOMEM; goto mem_error; } /* Put exclusion names first in the data. */ - while (exclusion_count--) { - strncpy(varlen_data + LTTNG_SYMBOL_NAME_LEN * exclusion_count, - *(exclusion_list + exclusion_count), - LTTNG_SYMBOL_NAME_LEN - 1); + for (i = 0; i < exclusion_count; i++) { + size_t exclusion_len; + + exclusion_len = lttng_strnlen(*(exclusion_list + i), + LTTNG_SYMBOL_NAME_LEN); + if (exclusion_len == LTTNG_SYMBOL_NAME_LEN) { + /* Exclusion is not NULL-terminated. */ + ret = -LTTNG_ERR_INVALID; + goto mem_error; + } + + ret = lttng_dynamic_buffer_append(&send_buffer, + *(exclusion_list + i), + LTTNG_SYMBOL_NAME_LEN); + if (ret) { + goto mem_error; + } } + /* Add filter expression next. */ - if (lsm.u.enable.expression_len != 0) { - memcpy(varlen_data - + LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count, - filter_expression, - lsm.u.enable.expression_len); + if (filter_expression) { + ret = lttng_dynamic_buffer_append(&send_buffer, + filter_expression, lsm.u.enable.expression_len); + if (ret) { + goto mem_error; + } } /* Add filter bytecode next. */ if (ctx && lsm.u.enable.bytecode_len != 0) { - memcpy(varlen_data - + LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count - + lsm.u.enable.expression_len, - &ctx->bytecode->b, - lsm.u.enable.bytecode_len); + ret = lttng_dynamic_buffer_append(&send_buffer, + &ctx->bytecode->b, lsm.u.enable.bytecode_len); + if (ret) { + goto mem_error; + } } + if (ev->extended.ptr) { + struct lttng_event_extended *ev_ext = + (struct lttng_event_extended *) ev->extended.ptr; + + if (ev_ext->probe_location) { + /* + * lttng_userspace_probe_location_serialize returns the + * number of bytes that was appended to the buffer. + */ + ret = lttng_userspace_probe_location_serialize( + ev_ext->probe_location, &send_buffer, + &fd_to_send); + if (ret) { + goto mem_error; + } - ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, varlen_data, - (LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count) + - lsm.u.enable.bytecode_len + lsm.u.enable.expression_len, - NULL); - free(varlen_data); + send_fd = fd_to_send >= 0; + /* + * Set the size of the userspace probe location element + * of the buffer so that the receiving side knows where + * to split it. + */ + lsm.u.enable.userspace_probe_location_len = ret; + } + } + + ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm, + send_fd ? &fd_to_send : NULL, + send_fd ? 1 : 0, + send_buffer.size ? send_buffer.data : NULL, + send_buffer.size, NULL, NULL, 0); mem_error: if (filter_expression && ctx) { @@ -1185,6 +1220,7 @@ error: * Return directly to the caller and don't ask the sessiond since * something went wrong in the parsing of data above. */ + lttng_dynamic_buffer_reset(&send_buffer); return ret; ask_sessiond: @@ -1895,7 +1931,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 +1951,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; }