X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.cpp;h=b519f9e70e54ad7ce32e1f1205b4750f800006bf;hb=40a3f14a2c83923d06ae3a59bf8c00438290a877;hp=0ca7f217244bd81d7cba98431347d60e7f61c9b4;hpb=ae2275afab15b194011e92058c63039542212748;p=deliverable%2Flttng-tools.git diff --git a/src/bin/lttng-sessiond/cmd.cpp b/src/bin/lttng-sessiond/cmd.cpp index 0ca7f2172..b519f9e70 100644 --- a/src/bin/lttng-sessiond/cmd.cpp +++ b/src/bin/lttng-sessiond/cmd.cpp @@ -9,63 +9,77 @@ #define _LGPL_SOURCE #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 -#include -#include +#include #include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "agent-thread.h" -#include "agent.h" -#include "buffer-registry.h" -#include "channel.h" -#include "cmd.h" -#include "consumer.h" -#include "event-notifier-error-accounting.h" -#include "event.h" -#include "health-sessiond.h" -#include "kernel-consumer.h" -#include "kernel.h" -#include "lttng-sessiond.h" -#include "lttng-syscall.h" -#include "notification-thread-commands.h" -#include "notification-thread.h" -#include "rotate.h" -#include "rotation-thread.h" -#include "session.h" -#include "timer.h" -#include "tracker.h" -#include "utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "agent-thread.hpp" +#include "agent.hpp" +#include "buffer-registry.hpp" +#include "channel.hpp" +#include "cmd.hpp" +#include "consumer.hpp" +#include "event-notifier-error-accounting.hpp" +#include "event.hpp" +#include "health-sessiond.hpp" +#include "kernel-consumer.hpp" +#include "kernel.hpp" +#include "lttng-sessiond.hpp" +#include "lttng-syscall.hpp" +#include "notification-thread-commands.hpp" +#include "notification-thread.hpp" +#include "rotate.hpp" +#include "rotation-thread.hpp" +#include "session.hpp" +#include "timer.hpp" +#include "tracker.hpp" +#include "utils.hpp" /* Sleep for 100ms between each check for the shm path's deletion. */ #define SESSION_DESTROY_SHM_PATH_CHECK_DELAY_US 100000 +namespace lsu = lttng::sessiond::ust; + +static enum lttng_error_code wait_on_path(void *path); + +namespace { struct cmd_destroy_session_reply_context { int reply_sock_fd; bool implicit_rotation_on_destroy; @@ -76,15 +90,13 @@ struct cmd_destroy_session_reply_context { enum lttng_error_code destruction_status; }; -static enum lttng_error_code wait_on_path(void *path); - /* * Command completion handler that is used by the destroy command * when a session that has a non-default shm_path is being destroyed. * * See comment in cmd_destroy_session() for the rationale. */ -static struct destroy_completion_handler { +struct destroy_completion_handler { struct cmd_completion_handler handler; char shm_path[member_sizeof(struct ltt_session, shm_path)]; } destroy_completion_handler = { @@ -95,17 +107,17 @@ static struct destroy_completion_handler { .shm_path = { 0 }, }; -static struct cmd_completion_handler *current_completion_handler; - /* * Used to keep a unique index for each relayd socket created where this value * is associated with streams on the consumer so it can match the right relayd * to send to. It must be accessed with the relayd_net_seq_idx_lock * held. */ -static pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER; -static uint64_t relayd_net_seq_idx; +pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER; +uint64_t relayd_net_seq_idx; +} /* namespace */ +static struct cmd_completion_handler *current_completion_handler; static int validate_ust_event_name(const char *); static int cmd_enable_event_internal(struct ltt_session *session, const struct lttng_domain *domain, @@ -114,7 +126,8 @@ static int cmd_enable_event_internal(struct ltt_session *session, struct lttng_bytecode *filter, struct lttng_event_exclusion *exclusion, int wpipe); -static int cmd_enable_channel_internal(struct ltt_session *session, +static enum lttng_error_code cmd_enable_channel_internal( + struct ltt_session *session, const struct lttng_domain *domain, const struct lttng_channel *_attr, int wpipe); @@ -748,9 +761,8 @@ error: * On success, the relayd_sock pointer is set to the created socket. * Else, it remains untouched and an LTTng error code is returned. */ -static enum lttng_error_code create_connect_relayd(struct lttng_uri *uri, - struct lttcomm_relayd_sock **relayd_sock, - struct consumer_output *consumer) +static lttng_error_code create_connect_relayd( + struct lttng_uri *uri, struct lttcomm_relayd_sock **relayd_sock) { int ret; enum lttng_error_code status = LTTNG_OK; @@ -779,8 +791,6 @@ static enum lttng_error_code create_connect_relayd(struct lttng_uri *uri, /* Create socket for control stream. */ if (uri->stype == LTTNG_STREAM_CONTROL) { - uint64_t result_flags; - DBG3("Creating relayd stream socket from URI"); /* Check relayd version */ @@ -793,18 +803,6 @@ static enum lttng_error_code create_connect_relayd(struct lttng_uri *uri, status = LTTNG_ERR_RELAYD_CONNECT_FAIL; goto close_sock; } - consumer->relay_major_version = rsock->major; - consumer->relay_minor_version = rsock->minor; - ret = relayd_get_configuration(rsock, 0, - &result_flags); - if (ret < 0) { - ERR("Unable to get relayd configuration"); - status = LTTNG_ERR_RELAYD_CONNECT_FAIL; - goto close_sock; - } - if (result_flags & LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED) { - consumer->relay_allows_clear = true; - } } else if (uri->stype == LTTNG_STREAM_DATA) { DBG3("Creating relayd data socket from URI"); } else { @@ -834,27 +832,21 @@ error: * * Returns LTTNG_OK on success or an LTTng error code on failure. */ -static enum lttng_error_code send_consumer_relayd_socket( - unsigned int session_id, +static enum lttng_error_code send_consumer_relayd_socket(unsigned int session_id, struct lttng_uri *relayd_uri, struct consumer_output *consumer, struct consumer_socket *consumer_sock, - const char *session_name, const char *hostname, - const char *base_path, int session_live_timer, + const char *session_name, + const char *hostname, + const char *base_path, + int session_live_timer, const uint64_t *current_chunk_id, time_t session_creation_time, - bool session_name_contains_creation_time) + bool session_name_contains_creation_time, + struct lttcomm_relayd_sock& rsock) { int ret; - struct lttcomm_relayd_sock *rsock = NULL; - enum lttng_error_code status; - - /* Connect to relayd and make version check if uri is the control. */ - status = create_connect_relayd(relayd_uri, &rsock, consumer); - if (status != LTTNG_OK) { - goto relayd_comm_error; - } - LTTNG_ASSERT(rsock); + enum lttng_error_code status = LTTNG_OK; /* Set the network sequence index if not set. */ if (consumer->net_seq_index == (uint64_t) -1ULL) { @@ -869,14 +861,13 @@ static enum lttng_error_code send_consumer_relayd_socket( } /* Send relayd socket to consumer. */ - ret = consumer_send_relayd_socket(consumer_sock, rsock, consumer, - relayd_uri->stype, session_id, - session_name, hostname, base_path, - session_live_timer, current_chunk_id, - session_creation_time, session_name_contains_creation_time); + ret = consumer_send_relayd_socket(consumer_sock, &rsock, consumer, relayd_uri->stype, + session_id, session_name, hostname, base_path, session_live_timer, + current_chunk_id, session_creation_time, + session_name_contains_creation_time); if (ret < 0) { status = LTTNG_ERR_ENABLE_CONSUMER_FAIL; - goto close_sock; + goto error; } /* Flag that the corresponding socket was sent. */ @@ -886,12 +877,7 @@ static enum lttng_error_code send_consumer_relayd_socket( consumer_sock->data_sock_sent = 1; } - /* - * Close socket which was dup on the consumer side. The session daemon does - * NOT keep track of the relayd socket(s) once transfer to the consumer. - */ - -close_sock: +error: if (status != LTTNG_OK) { /* * The consumer output for this session should not be used anymore @@ -900,13 +886,34 @@ close_sock: */ consumer->enabled = 0; } - (void) relayd_close(rsock); - free(rsock); -relayd_comm_error: return status; } +static bool is_trace_format_configuration_supported( + uint64_t supported_trace_format, lttng::trace_format_descriptor& trace_format) +{ + static const std::unordered_map + mapping = { + {LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1, + LTTCOMM_RELAYD_CONFIGURATION_TRACE_FORMAT_SUPPORTED_CTF1}, + {LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2, + LTTCOMM_RELAYD_CONFIGURATION_TRACE_FORMAT_SUPPORTED_CTF2}, + }; + + auto it = mapping.find(trace_format.type()); + if (it == mapping.end()) { + return false; + } + + if (!(supported_trace_format & it->second)) { + return false; + } + + return true; +} + /* * Send both relayd sockets to a specific consumer and domain. This is a * helper function to facilitate sending the information to the consumer for a @@ -916,26 +923,57 @@ relayd_comm_error: * * Returns LTTNG_OK, or an LTTng error code on failure. */ -static enum lttng_error_code send_consumer_relayd_sockets( - enum lttng_domain_type domain, - unsigned int session_id, struct consumer_output *consumer, - struct consumer_socket *sock, const char *session_name, - const char *hostname, const char *base_path, int session_live_timer, - const uint64_t *current_chunk_id, time_t session_creation_time, - bool session_name_contains_creation_time) +static lttng_error_code send_consumer_relayd_sockets(const ltt_session& session, + struct consumer_output *consumer, + struct consumer_socket *sock, + const char *base_path, + const uint64_t *current_chunk_id) { enum lttng_error_code status = LTTNG_OK; + struct lttcomm_relayd_sock *control_sock = nullptr; + struct lttcomm_relayd_sock *data_sock = nullptr; LTTNG_ASSERT(consumer); LTTNG_ASSERT(sock); /* Sending control relayd socket. */ if (!sock->control_sock_sent) { - status = send_consumer_relayd_socket(session_id, - &consumer->dst.net.control, consumer, sock, - session_name, hostname, base_path, session_live_timer, - current_chunk_id, session_creation_time, - session_name_contains_creation_time); + int ret; + uint64_t result_flags = 0; + uint64_t supported_trace_format = 0; + /* Connect to relayd and make version check if uri is the control. */ + status = create_connect_relayd(&consumer->dst.net.control, &control_sock); + if (status != LTTNG_OK) { + goto error; + } + LTTNG_ASSERT(control_sock); + + consumer->relay_major_version = control_sock->major; + consumer->relay_minor_version = control_sock->minor; + + ret = relayd_get_configuration(control_sock, 0, result_flags, nullptr); + if (ret < 0) { + ERR("Unable to get relayd configuration"); + status = LTTNG_ERR_RELAYD_CONNECT_FAIL; + goto error; + } + + if (result_flags & LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED) { + consumer->relay_allows_clear = true; + } + + if (!is_trace_format_configuration_supported( + supported_trace_format, *session.trace_format)) { + ERR("Relayd does not support the requested trace format"); + status = LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON; + goto error; + } + + status = send_consumer_relayd_socket(session.id, &consumer->dst.net.control, + consumer, sock, session.name, session.hostname, base_path, + session.live_timer, current_chunk_id, session.creation_time, + session.name_contains_creation_time, *control_sock); + if (status != LTTNG_OK) { goto error; } @@ -943,17 +981,34 @@ static enum lttng_error_code send_consumer_relayd_sockets( /* Sending data relayd socket. */ if (!sock->data_sock_sent) { - status = send_consumer_relayd_socket(session_id, - &consumer->dst.net.data, consumer, sock, - session_name, hostname, base_path, session_live_timer, - current_chunk_id, session_creation_time, - session_name_contains_creation_time); + /* Connect to relayd and make version check if uri is the control. */ + status = create_connect_relayd(&consumer->dst.net.data, &data_sock); + if (status != LTTNG_OK) { + goto error; + } + LTTNG_ASSERT(data_sock); + + status = send_consumer_relayd_socket(session.id, &consumer->dst.net.data, consumer, + sock, session.name, session.hostname, base_path, session.live_timer, + current_chunk_id, session.creation_time, + session.name_contains_creation_time, *data_sock); + if (status != LTTNG_OK) { goto error; } } error: + if (control_sock != nullptr) { + relayd_close(control_sock); + free(control_sock); + } + + if (data_sock != nullptr) { + relayd_close(data_sock); + free(data_sock); + } + return status; } @@ -995,17 +1050,12 @@ int cmd_setup_relayd(struct ltt_session *session) if (usess && usess->consumer && usess->consumer->type == CONSUMER_DST_NET && usess->consumer->enabled) { /* For each consumer socket, send relayd sockets */ - cds_lfht_for_each_entry(usess->consumer->socks->ht, &iter.iter, - socket, node.node) { + cds_lfht_for_each_entry ( + usess->consumer->socks->ht, &iter.iter, socket, node.node) { pthread_mutex_lock(socket->lock); - ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_UST, session->id, - usess->consumer, socket, - session->name, session->hostname, + ret = send_consumer_relayd_sockets(*session, usess->consumer, socket, session->base_path, - session->live_timer, - current_chunk_id.is_set ? ¤t_chunk_id.value : NULL, - session->creation_time, - session->name_contains_creation_time); + current_chunk_id.is_set ? ¤t_chunk_id.value : NULL); pthread_mutex_unlock(socket->lock); if (ret != LTTNG_OK) { goto error; @@ -1023,17 +1073,12 @@ int cmd_setup_relayd(struct ltt_session *session) if (ksess && ksess->consumer && ksess->consumer->type == CONSUMER_DST_NET && ksess->consumer->enabled) { - cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter, - socket, node.node) { + cds_lfht_for_each_entry ( + ksess->consumer->socks->ht, &iter.iter, socket, node.node) { pthread_mutex_lock(socket->lock); - ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_KERNEL, session->id, - ksess->consumer, socket, - session->name, session->hostname, + ret = send_consumer_relayd_sockets(*session, ksess->consumer, socket, session->base_path, - session->live_timer, - current_chunk_id.is_set ? ¤t_chunk_id.value : NULL, - session->creation_time, - session->name_contains_creation_time); + current_chunk_id.is_set ? ¤t_chunk_id.value : NULL); pthread_mutex_unlock(socket->lock); if (ret != LTTNG_OK) { goto error; @@ -1274,12 +1319,32 @@ end: return ret; } -static int cmd_enable_channel_internal(struct ltt_session *session, +static enum lttng_error_code kernel_domain_check_trace_format_requirements( + const lttng::trace_format_descriptor& descriptor) +{ + enum lttng_error_code ret_code = LTTNG_OK; + switch (descriptor.type()) { + case LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1: + /* Supported by all kernel tracer. */ + break; + case LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2: + if (!kernel_supports_ctf2()) { + ret_code = LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_KERNEL_TRACER; + } + break; + default: + abort(); + } + return ret_code; +} + +static enum lttng_error_code cmd_enable_channel_internal( + struct ltt_session *session, const struct lttng_domain *domain, const struct lttng_channel *_attr, int wpipe) { - int ret; + enum lttng_error_code ret_code; struct ltt_ust_session *usess = session->ust_session; struct lttng_ht *chan_ht; size_t len; @@ -1291,7 +1356,7 @@ static int cmd_enable_channel_internal(struct ltt_session *session, attr = lttng_channel_copy(_attr); if (!attr) { - ret = -LTTNG_ERR_NOMEM; + ret_code = LTTNG_ERR_NOMEM; goto end; } @@ -1300,7 +1365,7 @@ static int cmd_enable_channel_internal(struct ltt_session *session, /* Validate channel name */ if (attr->name[0] == '.' || memchr(attr->name, '/', len) != NULL) { - ret = LTTNG_ERR_INVALID_CHANNEL_NAME; + ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME; goto end; } @@ -1330,6 +1395,13 @@ static int cmd_enable_channel_internal(struct ltt_session *session, attr->name, session->name); lttng_channel_set_monitor_timer_interval(attr, 0); } + + ret_code = kernel_domain_check_trace_format_requirements(*session->trace_format); + if (ret_code != LTTNG_OK) { + WARN("Kernel tracer does not support the configured trace format of session '%s'", + session->name); + goto error; + } break; } case LTTNG_DOMAIN_UST: @@ -1339,12 +1411,12 @@ static int cmd_enable_channel_internal(struct ltt_session *session, case LTTNG_DOMAIN_PYTHON: if (!agent_tracing_is_enabled()) { DBG("Attempted to enable a channel in an agent domain but the agent thread is not running"); - ret = LTTNG_ERR_AGENT_TRACING_DISABLED; + ret_code = LTTNG_ERR_AGENT_TRACING_DISABLED; goto error; } break; default: - ret = LTTNG_ERR_UNKNOWN_DOMAIN; + ret_code = LTTNG_ERR_UNKNOWN_DOMAIN; goto error; } @@ -1361,7 +1433,7 @@ static int cmd_enable_channel_internal(struct ltt_session *session, * some point in time before. The tracer does not allow it. */ if (session->has_been_started) { - ret = LTTNG_ERR_TRACE_ALREADY_STARTED; + ret_code = LTTNG_ERR_TRACE_ALREADY_STARTED; goto error; } @@ -1370,16 +1442,16 @@ static int cmd_enable_channel_internal(struct ltt_session *session, /* Enforce mmap output for snapshot sessions. */ attr->attr.output = LTTNG_EVENT_MMAP; } - ret = channel_kernel_create( + ret_code = channel_kernel_create( session->kernel_session, attr, wpipe); if (attr->name[0] != '\0') { session->kernel_session->has_non_default_channel = 1; } } else { - ret = channel_kernel_enable(session->kernel_session, kchan); + ret_code = channel_kernel_enable(session->kernel_session, kchan); } - if (ret != LTTNG_OK) { + if (ret_code != LTTNG_OK) { goto error; } @@ -1404,19 +1476,19 @@ static int cmd_enable_channel_internal(struct ltt_session *session, if (domain->type == LTTNG_DOMAIN_JUL) { if (strncmp(attr->name, DEFAULT_JUL_CHANNEL_NAME, LTTNG_SYMBOL_NAME_LEN)) { - ret = LTTNG_ERR_INVALID_CHANNEL_NAME; + ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME; goto error; } } else if (domain->type == LTTNG_DOMAIN_LOG4J) { if (strncmp(attr->name, DEFAULT_LOG4J_CHANNEL_NAME, LTTNG_SYMBOL_NAME_LEN)) { - ret = LTTNG_ERR_INVALID_CHANNEL_NAME; + ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME; goto error; } } else if (domain->type == LTTNG_DOMAIN_PYTHON) { if (strncmp(attr->name, DEFAULT_PYTHON_CHANNEL_NAME, LTTNG_SYMBOL_NAME_LEN)) { - ret = LTTNG_ERR_INVALID_CHANNEL_NAME; + ret_code = LTTNG_ERR_INVALID_CHANNEL_NAME; goto error; } } @@ -1430,32 +1502,32 @@ static int cmd_enable_channel_internal(struct ltt_session *session, * some point in time before. The tracer does not allow it. */ if (session->has_been_started) { - ret = LTTNG_ERR_TRACE_ALREADY_STARTED; + ret_code = LTTNG_ERR_TRACE_ALREADY_STARTED; goto error; } - ret = channel_ust_create(usess, attr, domain->buf_type); + ret_code = channel_ust_create(usess, attr, domain->buf_type); if (attr->name[0] != '\0') { usess->has_non_default_channel = 1; } } else { - ret = channel_ust_enable(usess, uchan); + ret_code = channel_ust_enable(usess, uchan); } break; } default: - ret = LTTNG_ERR_UNKNOWN_DOMAIN; + ret_code = LTTNG_ERR_UNKNOWN_DOMAIN; goto error; } - if (ret == LTTNG_OK && attr->attr.output != LTTNG_EVENT_MMAP) { + if (ret_code == LTTNG_OK && attr->attr.output != LTTNG_EVENT_MMAP) { session->has_non_mmap_channel = true; } error: rcu_read_unlock(); end: lttng_channel_destroy(attr); - return ret; + return ret_code; } enum lttng_error_code cmd_process_attr_tracker_get_tracking_policy( @@ -1922,8 +1994,8 @@ int cmd_add_context(struct command_ctx *cmd_ctx, ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; goto error; } - /* break is _not_ missing here. */ } + /* fall through */ case LTTNG_DOMAIN_UST: { struct ltt_ust_session *usess = session->ust_session; @@ -2131,7 +2203,7 @@ static int _cmd_enable_event(struct ltt_session *session, } } if (filter) { - filter_a = (lttng_bytecode *) zmalloc(sizeof(*filter_a) + filter->len); + filter_a = zmalloc(sizeof(*filter_a) + filter->len); if (!filter_a) { free(filter_expression_a); ret = LTTNG_ERR_FATAL; @@ -2359,7 +2431,7 @@ static int _cmd_enable_event(struct ltt_session *session, struct lttng_bytecode) + filter->len; - filter_copy = (lttng_bytecode *) zmalloc(filter_size); + filter_copy = zmalloc(filter_size); if (!filter_copy) { ret = LTTNG_ERR_NOMEM; goto error; @@ -2739,7 +2811,7 @@ int cmd_start_trace(struct ltt_session *session) goto error; } - session->active = 1; + session->active = true; session->rotated_after_last_stop = false; session->cleared_after_last_stop = false; if (session->output_traces && !session->current_trace_chunk) { @@ -2818,7 +2890,7 @@ int cmd_start_trace(struct ltt_session *session) */ session->rotated_after_last_stop = false; - if (session->rotate_timer_period) { + if (session->rotate_timer_period && !session->rotation_schedule_timer_enabled) { int int_ret = timer_session_rotation_schedule_timer_start( session, session->rotate_timer_period); @@ -2834,9 +2906,9 @@ int cmd_start_trace(struct ltt_session *session) error: if (ret == LTTNG_OK) { /* Flag this after a successful start. */ - session->has_been_started |= 1; + session->has_been_started = true; } else { - session->active = 0; + session->active = false; /* Restore initial state on error. */ session->rotated_after_last_stop = session_rotated_after_last_stop; @@ -3095,6 +3167,8 @@ enum lttng_error_code cmd_create_session_from_descriptor( const char *session_name; struct ltt_session *new_session = NULL; enum lttng_session_descriptor_status descriptor_status; + const lttng_trace_format_descriptor *trace_format_descriptor = NULL; + lttng::trace_format_descriptor::uptr trace_format_descriptor_ptr; session_lock_list(); if (home_path) { @@ -3118,12 +3192,52 @@ enum lttng_error_code cmd_create_session_from_descriptor( goto end; } - ret_code = session_create(session_name, creds->uid, creds->gid, + descriptor_status = lttng_session_descriptor_get_trace_format_descriptor( + descriptor, &trace_format_descriptor); + if (descriptor_status != LTTNG_SESSION_DESCRIPTOR_STATUS_OK) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + try { + trace_format_descriptor_ptr = + reinterpret_cast( + trace_format_descriptor) + ->clone(); + } catch (std::exception& e) { + ERR("%s", e.what()); + ret_code = LTTNG_ERR_UNK; + goto end; + } + + ret_code = session_create(session_name, creds->uid, creds->gid, trace_format_descriptor_ptr, &new_session); if (ret_code != LTTNG_OK) { goto end; } + ret_code = notification_thread_command_add_session(the_notification_thread_handle, + new_session->id, new_session->name, new_session->uid, new_session->gid); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Announce the session's destruction to the notification thread when it is destroyed. */ + ret = session_add_destroy_notifier( + new_session, + [](const struct ltt_session *session, + void *user_data __attribute__((unused))) { + (void) notification_thread_command_remove_session( + the_notification_thread_handle, session->id); + }, + NULL); + if (ret) { + PERROR("Failed to add notification thread command to session's destroy notifiers: session name = %s", + new_session->name); + ret = LTTNG_ERR_NOMEM; + goto end; + } + if (!session_name) { ret = lttng_session_descriptor_set_session_name(descriptor, new_session->name); @@ -3288,6 +3402,7 @@ void cmd_destroy_session_reply(const struct ltt_session *session, .cmd_header_size = sizeof(struct lttcomm_session_destroy_command_header), .data_size = 0, + .fd_count = 0, }; size_t payload_size_before_location; @@ -3370,11 +3485,12 @@ int cmd_destroy_session(struct ltt_session *session, struct cmd_destroy_session_reply_context *reply_context = NULL; if (sock_fd) { - reply_context = (cmd_destroy_session_reply_context *) zmalloc(sizeof(*reply_context)); + reply_context = zmalloc(); if (!reply_context) { ret = LTTNG_ERR_NOMEM; goto end; } + reply_context->reply_sock_fd = *sock_fd; } @@ -3573,12 +3689,13 @@ int cmd_register_consumer(struct ltt_session *session, goto error; } - socket->lock = (pthread_mutex_t *) zmalloc(sizeof(pthread_mutex_t)); + socket->lock = zmalloc(); if (socket->lock == NULL) { PERROR("zmalloc pthread mutex"); ret = LTTNG_ERR_FATAL; goto error; } + pthread_mutex_init(socket->lock, NULL); socket->registered = 1; @@ -3641,7 +3758,7 @@ ssize_t cmd_list_domains(struct ltt_session *session, goto end; } - *domains = (lttng_domain *) zmalloc(nb_dom * sizeof(struct lttng_domain)); + *domains = calloc(nb_dom); if (*domains == NULL) { ret = LTTNG_ERR_FATAL; goto error; @@ -3909,23 +4026,38 @@ end: * The session list lock MUST be acquired before calling this function. Use * session_lock_list() and session_unlock_list(). */ -void cmd_list_lttng_sessions(struct lttng_session *sessions, - size_t session_count, uid_t uid, gid_t gid) +enum lttng_error_code cmd_list_lttng_sessions( + struct lttng_payload *reply_payload, uid_t uid, gid_t gid) { - int ret; - unsigned int i = 0; + int buffer_resize_ret; + enum lttng_error_code ret_code = LTTNG_OK; + struct lttcomm_list_command_header reply_command_header = {}; + size_t reply_command_header_offset; struct ltt_session *session; struct ltt_session_list *list = session_get_list(); - struct lttng_session_extended *extended = - (typeof(extended)) (&sessions[session_count]); + int ret; + unsigned int i = 0; + + assert(reply_payload); + + /* Reserve space for command reply header. */ + reply_command_header_offset = reply_payload->buffer.size; + buffer_resize_ret = lttng_dynamic_buffer_set_size(&reply_payload->buffer, + reply_command_header_offset + sizeof(struct lttcomm_list_command_header)); + if (buffer_resize_ret) { + ret_code = LTTNG_ERR_NOMEM; + goto error; + } DBG("Getting all available session for UID %d GID %d", uid, gid); - /* - * Iterate over session list and append data after the control struct in - * the buffer. - */ + cds_list_for_each_entry(session, &list->head, list) { + struct lttng_session tmp_session = {}; + struct lttng_session_extended tmp_extended = {}; + + tmp_session.extended.ptr = &tmp_extended; + if (!session_get(session)) { continue; } @@ -3944,10 +4076,10 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, if (session->consumer->type == CONSUMER_DST_NET || (ksess && ksess->consumer->type == CONSUMER_DST_NET) || (usess && usess->consumer->type == CONSUMER_DST_NET)) { - ret = build_network_session_path(sessions[i].path, - sizeof(sessions[i].path), session); + ret = build_network_session_path( + tmp_session.path, sizeof(tmp_session.path), session); } else { - ret = snprintf(sessions[i].path, sizeof(sessions[i].path), "%s", + ret = snprintf(tmp_session.path, sizeof(tmp_session.path), "%s", session->consumer->dst.session_root_path); } if (ret < 0) { @@ -3956,16 +4088,33 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, continue; } - strncpy(sessions[i].name, session->name, NAME_MAX); - sessions[i].name[NAME_MAX - 1] = '\0'; - sessions[i].enabled = session->active; - sessions[i].snapshot_mode = session->snapshot_mode; - sessions[i].live_timer_interval = session->live_timer; - extended[i].creation_time.value = (uint64_t) session->creation_time; - extended[i].creation_time.is_set = 1; + strncpy(tmp_session.name, session->name, NAME_MAX); + tmp_session.name[NAME_MAX - 1] = '\0'; + tmp_session.enabled = session->active; + tmp_session.snapshot_mode = session->snapshot_mode; + tmp_session.live_timer_interval = session->live_timer; + LTTNG_OPTIONAL_SET(&tmp_extended.creation_time, (uint64_t) session->creation_time); + ret = lttng_session_serialize(&tmp_session, reply_payload); + if (ret) { + ret_code = LTTNG_ERR_FATAL; + goto error; + } i++; session_put(session); } + + if (i > UINT32_MAX) { + ret_code = LTTNG_ERR_OVERFLOW; + goto error; + } + + /* Update command reply header. */ + reply_command_header.count = (uint32_t) i; + memcpy(reply_payload->buffer.data + reply_command_header_offset, &reply_command_header, + sizeof(reply_command_header)); + ret_code = LTTNG_OK; +error: + return ret_code; } /* @@ -4183,7 +4332,7 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, goto end; } - list = (lttng_snapshot_output *) zmalloc(session->snapshot.nb_output * sizeof(*list)); + list = calloc(session->snapshot.nb_output); if (!list) { ret = -LTTNG_ERR_NOMEM; goto end; @@ -4283,99 +4432,6 @@ end: return ret; } -static -int clear_metadata_file(int fd) -{ - int ret; - off_t lseek_ret; - - lseek_ret = lseek(fd, 0, SEEK_SET); - if (lseek_ret < 0) { - PERROR("lseek"); - ret = -1; - goto end; - } - - ret = ftruncate(fd, 0); - if (ret < 0) { - PERROR("ftruncate"); - goto end; - } - -end: - return ret; -} - -static -int ust_regenerate_metadata(struct ltt_ust_session *usess) -{ - int ret = 0; - struct buffer_reg_uid *uid_reg = NULL; - struct buffer_reg_session *session_reg = NULL; - - rcu_read_lock(); - cds_list_for_each_entry(uid_reg, &usess->buffer_reg_uid_list, lnode) { - struct ust_registry_session *registry; - struct ust_registry_channel *chan; - struct lttng_ht_iter iter_chan; - - session_reg = uid_reg->registry; - registry = session_reg->reg.ust; - - pthread_mutex_lock(®istry->lock); - registry->metadata_len_sent = 0; - memset(registry->metadata, 0, registry->metadata_alloc_len); - registry->metadata_len = 0; - registry->metadata_version++; - if (registry->metadata_fd > 0) { - /* Clear the metadata file's content. */ - ret = clear_metadata_file(registry->metadata_fd); - if (ret) { - pthread_mutex_unlock(®istry->lock); - goto end; - } - } - - ret = ust_metadata_session_statedump(registry, NULL, - registry->major, registry->minor); - if (ret) { - pthread_mutex_unlock(®istry->lock); - ERR("Failed to generate session metadata (err = %d)", - ret); - goto end; - } - cds_lfht_for_each_entry(registry->channels->ht, &iter_chan.iter, - chan, node.node) { - struct ust_registry_event *event; - struct lttng_ht_iter iter_event; - - ret = ust_metadata_channel_statedump(registry, chan); - if (ret) { - pthread_mutex_unlock(®istry->lock); - ERR("Failed to generate channel metadata " - "(err = %d)", ret); - goto end; - } - cds_lfht_for_each_entry(chan->ht->ht, &iter_event.iter, - event, node.node) { - ret = ust_metadata_event_statedump(registry, - chan, event); - if (ret) { - pthread_mutex_unlock(®istry->lock); - ERR("Failed to generate event metadata " - "(err = %d)", ret); - goto end; - } - } - } - pthread_mutex_unlock(®istry->lock); - } - -end: - rcu_read_unlock(); - return ret; -} - /* * Command LTTNG_REGENERATE_METADATA from the lttng-ctl library. * @@ -4406,7 +4462,7 @@ int cmd_regenerate_metadata(struct ltt_session *session) } if (session->ust_session) { - ret = ust_regenerate_metadata(session->ust_session); + ret = trace_ust_regenerate_metadata(session->ust_session); if (ret < 0) { ERR("Failed to regenerate the UST metadata"); goto end; @@ -5035,17 +5091,10 @@ static enum lttng_error_code set_relayd_for_snapshot( * snapshot output. */ rcu_read_lock(); - cds_lfht_for_each_entry(output->socks->ht, &iter.iter, - socket, node.node) { + cds_lfht_for_each_entry (output->socks->ht, &iter.iter, socket, node.node) { pthread_mutex_lock(socket->lock); - status = send_consumer_relayd_sockets(LTTNG_DOMAIN_NONE, session->id, - output, socket, - session->name, session->hostname, - base_path, - session->live_timer, - current_chunk_id.is_set ? ¤t_chunk_id.value : NULL, - session->creation_time, - session->name_contains_creation_time); + status = send_consumer_relayd_sockets(*session, output, socket, base_path, + current_chunk_id.is_set ? ¤t_chunk_id.value : NULL); pthread_mutex_unlock(socket->lock); if (status != LTTNG_OK) { rcu_read_unlock(); @@ -5067,7 +5116,7 @@ static enum lttng_error_code record_kernel_snapshot( struct ltt_kernel_session *ksess, const struct consumer_output *output, const struct ltt_session *session, - int wait, uint64_t nb_packets_per_stream) + uint64_t nb_packets_per_stream) { enum lttng_error_code status; @@ -5076,7 +5125,7 @@ static enum lttng_error_code record_kernel_snapshot( LTTNG_ASSERT(session); status = kernel_snapshot_record( - ksess, output, wait, nb_packets_per_stream); + ksess, output, nb_packets_per_stream); return status; } @@ -5088,7 +5137,7 @@ static enum lttng_error_code record_kernel_snapshot( static enum lttng_error_code record_ust_snapshot(struct ltt_ust_session *usess, const struct consumer_output *output, const struct ltt_session *session, - int wait, uint64_t nb_packets_per_stream) + uint64_t nb_packets_per_stream) { enum lttng_error_code status; @@ -5097,7 +5146,7 @@ static enum lttng_error_code record_ust_snapshot(struct ltt_ust_session *usess, LTTNG_ASSERT(session); status = ust_app_snapshot_record( - usess, output, wait, nb_packets_per_stream); + usess, output, nb_packets_per_stream); return status; } @@ -5191,7 +5240,7 @@ int64_t get_session_nb_packets_per_stream(const struct ltt_session *session, static enum lttng_error_code snapshot_record(struct ltt_session *session, - const struct snapshot_output *snapshot_output, int wait) + const struct snapshot_output *snapshot_output) { int64_t nb_packets_per_stream; char snapshot_chunk_name[LTTNG_NAME_MAX]; @@ -5311,7 +5360,7 @@ enum lttng_error_code snapshot_record(struct ltt_session *session, if (session->kernel_session) { ret_code = record_kernel_snapshot(session->kernel_session, snapshot_kernel_consumer_output, session, - wait, nb_packets_per_stream); + nb_packets_per_stream); if (ret_code != LTTNG_OK) { goto error_close_trace_chunk; } @@ -5320,7 +5369,7 @@ enum lttng_error_code snapshot_record(struct ltt_session *session, if (session->ust_session) { ret_code = record_ust_snapshot(session->ust_session, snapshot_ust_consumer_output, session, - wait, nb_packets_per_stream); + nb_packets_per_stream); if (ret_code != LTTNG_OK) { goto error_close_trace_chunk; } @@ -5368,7 +5417,8 @@ error: * Return LTTNG_OK on success or else a LTTNG_ERR code. */ int cmd_snapshot_record(struct ltt_session *session, - const struct lttng_snapshot_output *output, int wait) + const struct lttng_snapshot_output *output, + int wait __attribute__((unused))) { enum lttng_error_code cmd_ret = LTTNG_OK; int ret; @@ -5430,7 +5480,7 @@ int cmd_snapshot_record(struct ltt_session *session, /* Use the global datetime */ memcpy(tmp_output->datetime, datetime, sizeof(datetime)); - cmd_ret = snapshot_record(session, tmp_output, wait); + cmd_ret = snapshot_record(session, tmp_output); if (cmd_ret != LTTNG_OK) { goto error; } @@ -5470,7 +5520,7 @@ int cmd_snapshot_record(struct ltt_session *session, } } - cmd_ret = snapshot_record(session, &output_copy, wait); + cmd_ret = snapshot_record(session, &output_copy); if (cmd_ret != LTTNG_OK) { rcu_read_unlock(); goto error; @@ -5686,8 +5736,7 @@ int cmd_rotate_session(struct ltt_session *session, chunk_being_archived = NULL; if (!quiet_rotation) { ret = notification_thread_command_session_rotation_ongoing( - the_notification_thread_handle, session->name, - session->uid, session->gid, + the_notification_thread_handle, session->id, ongoing_rotation_chunk_id); if (ret != LTTNG_OK) { ERR("Failed to notify notification thread that a session rotation is ongoing for session %s",