X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Flttng-ctl.c;h=3f1ab9fdc4bb8f17abe91345355b11f3263d61e2;hp=cfe4371186447a1bbe51f8676e59550c7b7efcf3;hb=97285430b75f44b6ce590e86cb9d996390e514c8;hpb=e283e4a062cc16b5839a8a479e12498789320b5e diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index cfe437118..3f1ab9fdc 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -4,20 +4,10 @@ * Linux Trace Toolkit Control Library * * Copyright (C) 2011 David Goulet - * Copyright (C) 2016 - Jérémie Galarneau + * Copyright (C) 2016 Jérémie Galarneau * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License, version 2.1 only, - * as published by the Free Software Foundation. + * SPDX-License-Identifier: LGPL-2.1-only * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _LGPL_SOURCE @@ -32,42 +22,33 @@ #include #include #include +#include +#include +#include +#include #include +#include +#include #include #include -#include -#include -#include -#include -#include #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" -#include "filter/filter-bytecode.h" -#include "filter/memstream.h" +#include +#include +#include +#include #include "lttng-ctl-helper.h" -#ifdef DEBUG -static const int print_xml = 1; -#define dbg_printf(fmt, args...) \ - printf("[debug liblttng-ctl] " fmt, ## args) -#else -static const int print_xml = 0; -#define dbg_printf(fmt, args...) \ -do { \ - /* do nothing but check printf format */ \ - if (0) \ - printf("[debug liblttnctl] " fmt, ## args); \ -} while (0) -#endif - #define COPY_DOMAIN_PACKED(dst, src) \ do { \ struct lttng_domain _tmp_domain; \ @@ -224,7 +205,7 @@ end: * Receive data from the sessiond socket. * * On success, returns the number of bytes received (>=0) - * On error, returns -1 (recvmsg() error) or -ENOTCONN + * On error, returns a negative lttng_error_code. */ static int recv_data_sessiond(void *buf, size_t len) { @@ -244,6 +225,30 @@ end: return ret; } +/* + * Receive a payload from the session daemon by appending to an existing + * payload. + * On success, returns the number of bytes received (>=0) + * On error, returns a negative lttng_error_code. + */ +static int recv_payload_sessiond(struct lttng_payload *payload, size_t len) +{ + int ret; + const size_t original_payload_size = payload->buffer.size; + + ret = lttng_dynamic_buffer_set_size( + &payload->buffer, payload->buffer.size + len); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + + ret = recv_data_sessiond( + payload->buffer.data + original_payload_size, len); +end: + return ret; +} + /* * Check if we are in the specified group. * @@ -552,7 +557,6 @@ int lttng_ctl_ask_sessiond_fds_varlen(struct lttcomm_session_msg *lsm, connected = 1; } - /* Send command to session daemon */ ret = send_session_msg(lsm); if (ret < 0) { /* Ret value is a valid lttng error code. */ @@ -606,6 +610,98 @@ end: return ret; } +LTTNG_HIDDEN +int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message, + struct lttng_payload *reply) +{ + int ret; + struct lttcomm_lttng_msg llm; + const int fd_count = lttng_payload_view_get_fd_handle_count(message); + + assert(reply->buffer.size == 0); + assert(lttng_dynamic_pointer_array_get_count(&reply->_fd_handles) == 0); + + ret = connect_sessiond(); + if (ret < 0) { + ret = -LTTNG_ERR_NO_SESSIOND; + goto end; + } else { + sessiond_socket = ret; + connected = 1; + } + + /* Send command to session daemon */ + ret = lttcomm_send_creds_unix_sock(sessiond_socket, message->buffer.data, + message->buffer.size); + if (ret < 0) { + ret = -LTTNG_ERR_FATAL; + goto end; + } + + if (fd_count > 0) { + ret = lttcomm_send_payload_view_fds_unix_sock(sessiond_socket, + message); + if (ret < 0) { + ret = -LTTNG_ERR_FATAL; + goto end; + } + } + + /* Get header from data transmission */ + ret = recv_payload_sessiond(reply, sizeof(llm)); + if (ret < 0) { + /* Ret value is a valid lttng error code. */ + goto end; + } + + llm = *((typeof(llm) *) reply->buffer.data); + + /* Check error code if OK */ + if (llm.ret_code != LTTNG_OK) { + ret = -llm.ret_code; + goto end; + } + + if (llm.cmd_header_size > 0) { + ret = recv_payload_sessiond(reply, llm.cmd_header_size); + if (ret < 0) { + goto end; + } + } + + /* Get command header from data transmission */ + if (llm.data_size > 0) { + ret = recv_payload_sessiond(reply, llm.data_size); + if (ret < 0) { + goto end; + } + } + + if (llm.fd_count > 0) { + ret = lttcomm_recv_payload_fds_unix_sock( + sessiond_socket, llm.fd_count, reply); + if (ret < 0) { + goto end; + } + } + + /* Don't return the llm header to the caller. */ + memmove(reply->buffer.data, reply->buffer.data + sizeof(llm), + reply->buffer.size - sizeof(llm)); + ret = lttng_dynamic_buffer_set_size( + &reply->buffer, reply->buffer.size - sizeof(llm)); + if (ret) { + /* Can't happen as size is reduced. */ + abort(); + } + + ret = reply->buffer.size; + +end: + disconnect_sessiond(); + return ret; +} + /* * Create lttng handle and return pointer. * @@ -906,7 +1002,7 @@ static char *set_agent_filter(const char *filter, struct lttng_event *ev) /* Add loglevel filtering if any for the JUL domain. */ if (ev->loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) { - char *op; + const char *op; if (ev->loglevel_type == LTTNG_EVENT_LOGLEVEL_RANGE) { op = ">="; @@ -940,133 +1036,6 @@ error: return NULL; } -/* - * Generate the filter bytecode from a given filter expression string. Put the - * newly allocated parser context in ctxp and populate the lsm object with the - * expression len. - * - * Return 0 on success else a LTTNG_ERR_* code and ctxp is untouched. - */ -static int generate_filter(char *filter_expression, - struct lttcomm_session_msg *lsm, struct filter_parser_ctx **ctxp) -{ - int ret; - struct filter_parser_ctx *ctx = NULL; - FILE *fmem = NULL; - - assert(filter_expression); - assert(lsm); - assert(ctxp); - - /* - * Casting const to non-const, as the underlying function will use it in - * read-only mode. - */ - fmem = lttng_fmemopen((void *) filter_expression, - strlen(filter_expression), "r"); - if (!fmem) { - fprintf(stderr, "Error opening memory as stream\n"); - ret = -LTTNG_ERR_FILTER_NOMEM; - goto error; - } - ctx = filter_parser_ctx_alloc(fmem); - if (!ctx) { - fprintf(stderr, "Error allocating parser\n"); - ret = -LTTNG_ERR_FILTER_NOMEM; - goto filter_alloc_error; - } - ret = filter_parser_ctx_append_ast(ctx); - if (ret) { - fprintf(stderr, "Parse error\n"); - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - if (print_xml) { - ret = filter_visitor_print_xml(ctx, stdout, 0); - if (ret) { - fflush(stdout); - fprintf(stderr, "XML print error\n"); - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - } - - dbg_printf("Generating IR... "); - fflush(stdout); - ret = filter_visitor_ir_generate(ctx); - if (ret) { - fprintf(stderr, "Generate IR error\n"); - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - dbg_printf("done\n"); - - dbg_printf("Validating IR... "); - fflush(stdout); - ret = filter_visitor_ir_check_binary_op_nesting(ctx); - if (ret) { - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - - /* Normalize globbing patterns in the expression. */ - ret = filter_visitor_ir_normalize_glob_patterns(ctx); - if (ret) { - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - - /* Validate strings used as literals in the expression. */ - ret = filter_visitor_ir_validate_string(ctx); - if (ret) { - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - - /* Validate globbing patterns in the expression. */ - ret = filter_visitor_ir_validate_globbing(ctx); - if (ret) { - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - - dbg_printf("done\n"); - - dbg_printf("Generating bytecode... "); - fflush(stdout); - ret = filter_visitor_bytecode_generate(ctx); - if (ret) { - fprintf(stderr, "Generate bytecode error\n"); - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - dbg_printf("done\n"); - dbg_printf("Size of bytecode generated: %u bytes.\n", - bytecode_get_len(&ctx->bytecode->b)); - - lsm->u.enable.bytecode_len = sizeof(ctx->bytecode->b) - + bytecode_get_len(&ctx->bytecode->b); - lsm->u.enable.expression_len = strlen(filter_expression) + 1; - - /* No need to keep the memory stream. */ - if (fclose(fmem) != 0) { - PERROR("fclose"); - } - - *ctxp = ctx; - return 0; - -parse_error: - filter_ir_free(ctx); - filter_parser_ctx_free(ctx); -filter_alloc_error: - if (fclose(fmem) != 0) { - PERROR("fclose"); - } -error: - return ret; -} - /* * Enable event(s) for a channel, possibly with exclusions and a filter. * If no event name is specified, all events are enabled. @@ -1081,17 +1050,16 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, int exclusion_count, char **exclusion_list) { struct lttcomm_session_msg lsm; - struct lttng_dynamic_buffer send_buffer; - int ret = 0, i, fd_to_send = -1; - bool send_fd = false; + struct lttng_payload payload; + int ret = 0, i; unsigned int free_filter_expression = 0; struct filter_parser_ctx *ctx = NULL; /* * 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. + * a variable-length payload from where to send the data. */ - lttng_dynamic_buffer_init(&send_buffer); + lttng_payload_init(&payload); /* * Cast as non-const since we may replace the filter expression @@ -1170,16 +1138,21 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, } } - ret = generate_filter(filter_expression, &lsm, &ctx); + ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx); if (ret) { goto filter_error; } + + lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b) + + bytecode_get_len(&ctx->bytecode->b); + lsm.u.enable.expression_len = strlen(filter_expression) + 1; } - ret = lttng_dynamic_buffer_set_capacity(&send_buffer, - lsm.u.enable.bytecode_len - + lsm.u.enable.expression_len - + LTTNG_SYMBOL_NAME_LEN * exclusion_count); + ret = lttng_dynamic_buffer_set_capacity(&payload.buffer, + lsm.u.enable.bytecode_len + + lsm.u.enable.expression_len + + LTTNG_SYMBOL_NAME_LEN * + exclusion_count); if (ret) { ret = -LTTNG_ERR_EXCLUSION_NOMEM; goto mem_error; @@ -1197,9 +1170,8 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, goto mem_error; } - ret = lttng_dynamic_buffer_append(&send_buffer, - *(exclusion_list + i), - LTTNG_SYMBOL_NAME_LEN); + ret = lttng_dynamic_buffer_append(&payload.buffer, + *(exclusion_list + i), LTTNG_SYMBOL_NAME_LEN); if (ret) { goto mem_error; } @@ -1207,7 +1179,7 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, /* Add filter expression next. */ if (filter_expression) { - ret = lttng_dynamic_buffer_append(&send_buffer, + ret = lttng_dynamic_buffer_append(&payload.buffer, filter_expression, lsm.u.enable.expression_len); if (ret) { goto mem_error; @@ -1215,7 +1187,7 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, } /* Add filter bytecode next. */ if (ctx && lsm.u.enable.bytecode_len != 0) { - ret = lttng_dynamic_buffer_append(&send_buffer, + ret = lttng_dynamic_buffer_append(&payload.buffer, &ctx->bytecode->b, lsm.u.enable.bytecode_len); if (ret) { goto mem_error; @@ -1231,13 +1203,11 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, * number of bytes that was appended to the buffer. */ ret = lttng_userspace_probe_location_serialize( - ev_ext->probe_location, &send_buffer, - &fd_to_send); + ev_ext->probe_location, &payload); if (ret < 0) { goto mem_error; } - 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 @@ -1247,11 +1217,34 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, } } - 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); + { + struct lttng_payload_view view = lttng_payload_view_from_payload( + &payload, 0, -1); + int fd_count = lttng_payload_view_get_fd_handle_count(&view); + int fd_to_send; + + if (fd_count < 0) { + goto mem_error; + } + + assert(fd_count == 0 || fd_count == 1); + if (fd_count == 1) { + struct fd_handle *handle = + lttng_payload_view_pop_fd_handle(&view); + + if (!handle) { + goto mem_error; + } + + fd_to_send = fd_handle_get_fd(handle); + fd_handle_put(handle); + } + + ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm, + fd_count ? &fd_to_send : NULL, fd_count, + view.buffer.size ? view.buffer.data : NULL, + view.buffer.size, NULL, NULL, 0); + } mem_error: if (filter_expression && ctx) { @@ -1273,7 +1266,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); + lttng_payload_reset(&payload); return ret; ask_sessiond: @@ -1379,10 +1372,14 @@ int lttng_disable_event_ext(struct lttng_handle *handle, } } - ret = generate_filter(filter_expression, &lsm, &ctx); + ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx); if (ret) { goto filter_error; } + + lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b) + + bytecode_get_len(&ctx->bytecode->b); + lsm.u.enable.expression_len = strlen(filter_expression) + 1; } varlen_data = zmalloc(lsm.u.disable.bytecode_len @@ -2195,21 +2192,31 @@ int lttng_list_events(struct lttng_handle *handle, const char *channel_name, struct lttng_event **events) { int ret; - struct lttcomm_session_msg lsm; - struct lttcomm_event_command_header *cmd_header = NULL; - size_t cmd_header_len; + struct lttcomm_session_msg lsm = {}; + const struct lttcomm_event_command_header *cmd_header = NULL; uint32_t nb_events, i; - void *comm_ext_at; - char *reception_buffer = NULL; + const void *comm_ext_at; struct lttng_dynamic_buffer listing; size_t storage_req; + struct lttng_payload payload; + struct lttng_payload payload_copy; + struct lttng_payload_view lsm_view = + lttng_payload_view_init_from_buffer( + (const char *) &lsm, 0, sizeof(lsm)); + struct lttng_buffer_view cmd_header_view; + struct lttng_buffer_view cmd_payload_view; + struct lttng_buffer_view flat_events_view; + struct lttng_buffer_view ext_view; /* Safety check. An handle and channel name are mandatory */ if (handle == NULL || channel_name == NULL) { - return -LTTNG_ERR_INVALID; + ret = -LTTNG_ERR_INVALID; + goto end; } - memset(&lsm, 0, sizeof(lsm)); + lttng_payload_init(&payload); + lttng_payload_init(&payload_copy); + lsm.cmd_type = LTTNG_LIST_EVENTS; lttng_ctl_copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); @@ -2217,26 +2224,41 @@ int lttng_list_events(struct lttng_handle *handle, sizeof(lsm.u.list.channel_name)); COPY_DOMAIN_PACKED(lsm.domain, handle->domain); - ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm, NULL, 0, NULL, 0, - (void **) &reception_buffer, (void **) &cmd_header, - &cmd_header_len); + ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &payload); if (ret < 0) { goto end; } - if (!cmd_header) { - ret = -LTTNG_ERR_UNK; + /* + * A copy of the payload is performed since it will be + * consumed twice. Consuming the same payload twice is invalid since + * it will cause any received file descriptor to become "shared" + * between different instances of the resulting objects. + */ + ret = lttng_payload_copy(&payload, &payload_copy); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + + cmd_header_view = lttng_buffer_view_from_dynamic_buffer( + &payload.buffer, 0, sizeof(*cmd_header)); + if (!cmd_header_view.data) { + ret = -LTTNG_ERR_INVALID_PROTOCOL; goto end; } + cmd_header = (typeof(cmd_header)) cmd_header_view.data; + /* Set number of events and free command header */ nb_events = cmd_header->nb_events; if (nb_events > INT_MAX) { ret = -LTTNG_ERR_OVERFLOW; goto end; } - free(cmd_header); - cmd_header = NULL; + + cmd_payload_view = lttng_buffer_view_from_dynamic_buffer( + &payload.buffer, sizeof(*cmd_header), -1); /* * The buffer that is returned must contain a "flat" version of @@ -2260,58 +2282,68 @@ int lttng_list_events(struct lttng_handle *handle, * - exclusions * - padding to align to 64-bits */ - comm_ext_at = reception_buffer + - (nb_events * sizeof(struct lttng_event)); + ext_view = lttng_buffer_view_from_view(&cmd_payload_view, + nb_events * sizeof(struct lttng_event), -1); + comm_ext_at = ext_view.data; storage_req = nb_events * sizeof(struct lttng_event); + { + struct lttng_payload_view payload_view = + lttng_payload_view_from_payload(&payload, 0, -1); - 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; + for (i = 0; i < nb_events; i++) { + const 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; + 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_payload_view probe_location_view = lttng_payload_view_from_view( + &payload_view, + (const char *) comm_ext_at - + payload_view.buffer.data, + ext_comm->userspace_probe_location_len); - 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_payload( + &probe_location_view, + &probe_location); + if (ret < 0) { + ret = -LTTNG_ERR_PROBE_LOCATION_INVAL; + goto end; + } - /* - * 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; + } - 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; } - probe_storage_req = ret; - comm_ext_at += ext_comm->userspace_probe_location_len; + storage_req += sizeof(struct lttng_event_extended); + storage_req += ext_comm->filter_len; + storage_req += ext_comm->nb_exclusions * + LTTNG_SYMBOL_NAME_LEN; + /* Padding to ensure the flat probe is aligned. */ + storage_req = ALIGN_TO(storage_req, sizeof(uint64_t)); + storage_req += probe_storage_req; } - - storage_req += sizeof(struct lttng_event_extended); - storage_req += ext_comm->filter_len; - storage_req += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; - /* Padding to ensure the flat probe is aligned. */ - storage_req = ALIGN_TO(storage_req, sizeof(uint64_t)); - storage_req += probe_storage_req; } lttng_dynamic_buffer_init(&listing); @@ -2325,100 +2357,120 @@ int lttng_list_events(struct lttng_handle *handle, goto end; } - ret = lttng_dynamic_buffer_append(&listing, reception_buffer, + cmd_payload_view = lttng_buffer_view_from_dynamic_buffer( + &payload_copy.buffer, sizeof(*cmd_header), -1); + flat_events_view = lttng_buffer_view_from_view(&cmd_payload_view, 0, nb_events * sizeof(struct lttng_event)); + ret = lttng_dynamic_buffer_append_view(&listing, &flat_events_view); if (ret) { ret = -LTTNG_ERR_NOMEM; goto free_dynamic_buffer; } - comm_ext_at = reception_buffer + - (nb_events * sizeof(struct lttng_event)); - for (i = 0; i < nb_events; i++) { - struct lttng_event *event = (struct lttng_event *) - (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.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; - - comm_ext_at += sizeof(*ext_comm); - - /* 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); + ext_view = lttng_buffer_view_from_view(&cmd_payload_view, + nb_events * sizeof(struct lttng_event), -1); + comm_ext_at = ext_view.data; + + { + struct lttng_payload_view payload_copy_view = + lttng_payload_view_from_payload( + &payload_copy, 0, -1); + + for (i = 0; i < nb_events; i++) { + struct lttng_event *event = (typeof(event))( + listing.data + + (sizeof(struct lttng_event) * i)); + const struct lttcomm_event_extended_header *ext_comm = + (typeof(ext_comm)) comm_ext_at; + struct lttng_event_extended *event_extended = + (typeof(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; } - comm_ext_at += ext_comm->filter_len; - } + event->extended.ptr = event_extended; + + comm_ext_at += sizeof(*ext_comm); + + /* 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; + /* 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; + goto free_dynamic_buffer; + } + comm_ext_at += ext_comm->nb_exclusions * + LTTNG_SYMBOL_NAME_LEN; + } - ret = lttng_dynamic_buffer_append(&listing, - 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; } - 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; - - probe_location_view = lttng_buffer_view_init( - comm_ext_at, 0, - ext_comm->userspace_probe_location_len); + /* Insert flattened userspace probe location. */ + if (ext_comm->userspace_probe_location_len) { + struct lttng_userspace_probe_location + *probe_location = NULL; + struct lttng_payload_view probe_location_view = lttng_payload_view_from_view( + &payload_copy_view, + (const char *) comm_ext_at - + payload_copy_view.buffer.data, + ext_comm->userspace_probe_location_len); + + ret = lttng_userspace_probe_location_create_from_payload( + &probe_location_view, + &probe_location); + if (ret < 0) { + ret = -LTTNG_ERR_PROBE_LOCATION_INVAL; + goto free_dynamic_buffer; + } - 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; + } - 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; } - - comm_ext_at += ext_comm->userspace_probe_location_len; } } @@ -2429,8 +2481,8 @@ int lttng_list_events(struct lttng_handle *handle, free_dynamic_buffer: lttng_dynamic_buffer_reset(&listing); end: - free(cmd_header); - free(reception_buffer); + lttng_payload_reset(&payload); + lttng_payload_reset(&payload_copy); return ret; } @@ -2827,172 +2879,6 @@ end: return ret; } -/* - * List IDs in the tracker. - * - * tracker_type is the type of tracker. - * ids is set to an allocated array of IDs currently tracked. On - * success, ids and contained ids must be freed/destroy by the caller. - * nr_ids is set to the number of entries contained by the ids array. - * - * Returns 0 on success, else a negative LTTng error code. - */ -int lttng_list_tracker_ids(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - struct lttng_tracker_ids **_ids) -{ - int ret, i; - struct lttcomm_session_msg lsm; - struct lttcomm_tracker_command_header *cmd_header = NULL; - char *cmd_payload = NULL, *p; - size_t cmd_header_len; - size_t nr_ids = 0; - struct lttng_tracker_ids *ids = NULL; - - if (handle == NULL) { - return -LTTNG_ERR_INVALID; - } - - memset(&lsm, 0, sizeof(lsm)); - lsm.cmd_type = LTTNG_LIST_TRACKER_IDS; - lsm.u.id_tracker_list.tracker_type = tracker_type; - lttng_ctl_copy_string(lsm.session.name, handle->session_name, - sizeof(lsm.session.name)); - COPY_DOMAIN_PACKED(lsm.domain, handle->domain); - - ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm, NULL, 0, NULL, 0, - (void **) &cmd_payload, (void **) &cmd_header, - &cmd_header_len); - if (ret < 0) { - goto error; - } - - /* Set number of tracker_id and free command header */ - nr_ids = cmd_header->nb_tracker_id; - if (nr_ids > INT_MAX) { - ret = -LTTNG_ERR_OVERFLOW; - goto error; - } - free(cmd_header); - cmd_header = NULL; - - ids = lttng_tracker_ids_create(nr_ids); - if (!ids) { - ret = -LTTNG_ERR_NOMEM; - goto error; - } - - p = cmd_payload; - for (i = 0; i < nr_ids; i++) { - struct lttcomm_tracker_id_header *tracker_id; - struct lttng_tracker_id *id; - enum lttng_tracker_id_status status; - - tracker_id = (struct lttcomm_tracker_id_header *) p; - p += sizeof(struct lttcomm_tracker_id_header); - id = lttng_tracker_ids_get_pointer_of_index(ids, i); - if (!id) { - ret = -LTTNG_ERR_INVALID; - goto error; - } - - switch (tracker_id->type) { - case LTTNG_ID_ALL: - status = lttng_tracker_id_set_all(id); - break; - case LTTNG_ID_VALUE: - id->value = tracker_id->u.value; - status = lttng_tracker_id_set_value( - id, tracker_id->u.value); - break; - case LTTNG_ID_STRING: - status = lttng_tracker_id_set_string(id, p); - p += tracker_id->u.var_data_len; - break; - default: - goto error; - } - - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -LTTNG_ERR_INVALID; - goto error; - } - } - free(cmd_payload); - *_ids = ids; - return 0; - -error: - lttng_tracker_ids_destroy(ids); - free(cmd_payload); - free(cmd_header); - return ret; -} - -/* - * List PIDs in the tracker. - * - * enabled is set to whether the PID tracker is enabled. - * pids is set to an allocated array of PIDs currently tracked. On - * success, pids must be freed by the caller. - * nr_pids is set to the number of entries contained by the pids array. - * - * Returns 0 on success, else a negative LTTng error code. - */ -int lttng_list_tracker_pids(struct lttng_handle *handle, - int *_enabled, int32_t **_pids, size_t *_nr_pids) -{ - struct lttng_tracker_ids *ids = NULL; - unsigned int nr_ids = 0; - int *pids = NULL; - int ret = 0, i; - enum lttng_tracker_id_status status; - const struct lttng_tracker_id *id; - - ret = lttng_list_tracker_ids(handle, LTTNG_TRACKER_PID, &ids); - if (ret < 0) { - return ret; - } - - status = lttng_tracker_ids_get_count(ids, &nr_ids); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -LTTNG_ERR_INVALID; - goto end; - } - - if (nr_ids == 1) { - id = lttng_tracker_ids_get_at_index(ids, 0); - if (id && lttng_tracker_id_get_type(id) == LTTNG_ID_ALL) { - *_enabled = 0; - goto end; - } - } - - *_enabled = 1; - - pids = zmalloc(nr_ids * sizeof(*pids)); - if (!pids) { - ret = -LTTNG_ERR_NOMEM; - goto end; - } - for (i = 0; i < nr_ids; i++) { - id = lttng_tracker_ids_get_at_index(ids, i); - status = lttng_tracker_id_get_value(id, &pids[i]); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -LTTNG_ERR_UNK; - goto end; - } - } - *_pids = pids; - *_nr_pids = nr_ids; -end: - lttng_tracker_ids_destroy(ids); - if (ret < 0) { - free(pids); - } - return ret; -} - /* * Regenerate the metadata for a session. * Return 0 on success, a negative error code on error. @@ -3064,10 +2950,16 @@ end: int lttng_register_trigger(struct lttng_trigger *trigger) { int ret; - struct lttcomm_session_msg lsm; - struct lttng_dynamic_buffer buffer; + struct lttcomm_session_msg lsm = { + .cmd_type = LTTNG_REGISTER_TRIGGER, + }; + struct lttcomm_session_msg *message_lsm; + struct lttng_payload message; + struct lttng_payload reply; + + lttng_payload_init(&message); + lttng_payload_init(&reply); - lttng_dynamic_buffer_init(&buffer); if (!trigger) { ret = -LTTNG_ERR_INVALID; goto end; @@ -3078,19 +2970,43 @@ int lttng_register_trigger(struct lttng_trigger *trigger) goto end; } - ret = lttng_trigger_serialize(trigger, &buffer); + ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm)); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + + /* + * This is needed to populate the trigger object size for the command + * header. + */ + message_lsm = (struct lttcomm_session_msg *) message.buffer.data; + + ret = lttng_trigger_serialize(trigger, &message); if (ret < 0) { ret = -LTTNG_ERR_UNK; goto end; } - memset(&lsm, 0, sizeof(lsm)); - lsm.cmd_type = LTTNG_REGISTER_TRIGGER; - lsm.u.trigger.length = (uint32_t) buffer.size; - ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, buffer.data, - buffer.size, NULL); + message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm); + + { + struct lttng_payload_view message_view = + lttng_payload_view_from_payload( + &message, 0, -1); + + message_lsm->fd_count = lttng_payload_view_get_fd_handle_count( + &message_view); + ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply); + if (ret < 0) { + goto end; + } + } + + ret = 0; end: - lttng_dynamic_buffer_reset(&buffer); + lttng_payload_reset(&message); + lttng_payload_reset(&reply); return ret; } @@ -3098,9 +3014,13 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger) { int ret; struct lttcomm_session_msg lsm; - struct lttng_dynamic_buffer buffer; + struct lttcomm_session_msg *message_lsm; + struct lttng_payload message; + struct lttng_payload reply; + + lttng_payload_init(&message); + lttng_payload_init(&reply); - lttng_dynamic_buffer_init(&buffer); if (!trigger) { ret = -LTTNG_ERR_INVALID; goto end; @@ -3111,144 +3031,51 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger) goto end; } - ret = lttng_trigger_serialize(trigger, &buffer); - if (ret < 0) { - ret = -LTTNG_ERR_UNK; - goto end; - } - memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_UNREGISTER_TRIGGER; - lsm.u.trigger.length = (uint32_t) buffer.size; - ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, buffer.data, - buffer.size, NULL); -end: - lttng_dynamic_buffer_reset(&buffer); - return ret; -} - -static int lttng_track_untrack_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id, - enum lttcomm_sessiond_command cmd) -{ - int ret; - struct lttcomm_session_msg lsm; - const char *var_data; - size_t var_data_len = 0; - int value; - enum lttng_tracker_id_status status; - /* NULL arguments are forbidden. No default values. */ - if (handle == NULL) { - goto error; + ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm)); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto end; } - memset(&lsm, 0, sizeof(lsm)); + /* + * This is needed to populate the trigger object size for the command + * header and number of fds sent. + */ + message_lsm = (struct lttcomm_session_msg *) message.buffer.data; - lsm.cmd_type = cmd; - lsm.u.id_tracker.tracker_type = tracker_type; - lsm.u.id_tracker.id_type = lttng_tracker_id_get_type(id); - switch (lsm.u.id_tracker.id_type) { - case LTTNG_ID_ALL: - break; - case LTTNG_ID_VALUE: - status = lttng_tracker_id_get_value(id, &value); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - goto error; - } - lsm.u.id_tracker.u.value = value; - break; - case LTTNG_ID_STRING: - status = lttng_tracker_id_get_string(id, &var_data); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - goto error; - } - var_data_len = strlen(var_data) + 1; /* Includes \0. */ - lsm.u.id_tracker.u.var_len = var_data_len; - break; - default: - goto error; + ret = lttng_trigger_serialize(trigger, &message); + if (ret < 0) { + ret = -LTTNG_ERR_UNK; + goto end; } - COPY_DOMAIN_PACKED(lsm.domain, handle->domain); - - lttng_ctl_copy_string(lsm.session.name, handle->session_name, - sizeof(lsm.session.name)); - - ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( - &lsm, (char *) var_data, var_data_len, NULL); - return ret; -error: - return -LTTNG_ERR_INVALID; -} - -/* - * Add ID to session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_track_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id) -{ - return lttng_track_untrack_id(handle, tracker_type, id, LTTNG_TRACK_ID); -} - -/* - * Remove ID from session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_untrack_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id) -{ - return lttng_track_untrack_id( - handle, tracker_type, id, LTTNG_UNTRACK_ID); -} - -/* - * Add PID to session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_track_pid(struct lttng_handle *handle, int pid) -{ - int ret; - struct lttng_tracker_id *id = NULL; - enum lttng_tracker_id_status status; - - id = lttng_tracker_id_create(); - status = lttng_tracker_id_set_value(id, pid); - if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { - ret = -LTTNG_ERR_INVALID; - goto error; - } + message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm); - ret = lttng_track_id(handle, LTTNG_TRACKER_PID, id); -error: - lttng_tracker_id_destroy(id); - return ret; -} + { + struct lttng_payload_view message_view = + lttng_payload_view_from_payload( + &message, 0, -1); -/* - * Remove PID from session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_untrack_pid(struct lttng_handle *handle, int pid) -{ - int ret; - struct lttng_tracker_id *id = NULL; - enum lttng_tracker_id_status status; + /* + * Update the message header with the number of fd that will be + * sent. + */ + message_lsm->fd_count = lttng_payload_view_get_fd_handle_count( + &message_view); - id = lttng_tracker_id_create(); - status = lttng_tracker_id_set_value(id, pid); - if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { - ret = -LTTNG_ERR_INVALID; - goto error; + ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply); + if (ret < 0) { + goto end; + } } - ret = lttng_untrack_id(handle, LTTNG_TRACKER_PID, id); -error: - lttng_tracker_id_destroy(id); + ret = 0; +end: + lttng_payload_reset(&message); + lttng_payload_reset(&reply); return ret; }