X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=d443d7926b7d9c25fc1b3dcdcbb8b1ced0bc97a4;hp=c054db917a40c4f86bd217255224a060875f116e;hb=cfedea034e0a305d13e65d0d8068e21cb1af3d44;hpb=fb83fe64f250bec7416f18891a8264450c61ead3 diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index c054db917..d443d7926 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "channel.h" #include "consumer.h" @@ -39,6 +40,7 @@ #include "utils.h" #include "syscall.h" #include "agent.h" +#include "buffer-registry.h" #include "cmd.h" @@ -185,7 +187,14 @@ static int get_ust_runtime_stats(struct ltt_session *session, int ret; struct ltt_ust_session *usess; + if (!discarded_events || !lost_packets) { + ret = -1; + goto end; + } + usess = session->ust_session; + assert(discarded_events); + assert(lost_packets); if (!usess || !session->has_been_started) { *discarded_events = 0; @@ -214,6 +223,7 @@ static int get_ust_runtime_stats(struct ltt_session *session, *lost_packets += uchan->per_pid_closed_app_lost; } else { ERR("Unsupported buffer type"); + assert(0); ret = -1; goto end; } @@ -265,7 +275,7 @@ static void list_lttng_channels(enum lttng_domain_type domain, rcu_read_lock(); cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, &iter.iter, uchan, node.node) { - uint64_t discarded_events, lost_packets; + uint64_t discarded_events = 0, lost_packets = 0; strncpy(channels[i].name, uchan->name, LTTNG_SYMBOL_NAME_LEN); channels[i].attr.overwrite = uchan->attr.overwrite; @@ -278,11 +288,21 @@ static void list_lttng_channels(enum lttng_domain_type domain, channels[i].enabled = uchan->enabled; channels[i].attr.tracefile_size = uchan->tracefile_size; channels[i].attr.tracefile_count = uchan->tracefile_count; + + /* + * Map enum lttng_ust_output to enum lttng_event_output. + */ switch (uchan->attr.output) { case LTTNG_UST_MMAP: - default: channels[i].attr.output = LTTNG_EVENT_MMAP; break; + default: + /* + * LTTNG_UST_MMAP is the only supported UST + * output mode. + */ + assert(0); + break; } ret = get_ust_runtime_stats(session, uchan, @@ -580,7 +600,7 @@ static int list_lttng_kernel_events(char *channel_name, if (nb_event == 0) { *total_size = 0; *events = NULL; - goto syscall; + goto end; } /* Compute required extended infos size */ @@ -596,7 +616,7 @@ static int list_lttng_kernel_events(char *channel_name, goto error; } - extended_at = ((uint8_t *) events) + + extended_at = ((void *) *events) + nb_event * sizeof(struct lttng_event); /* Kernel channels */ @@ -643,19 +663,7 @@ static int list_lttng_kernel_events(char *channel_name, &extended_at); } -syscall: - if (syscall_table) { - ssize_t new_size; - - new_size = syscall_list_channel(kchan, events, nb_event); - if (new_size < 0) { - free(events); - ret = -new_size; - goto error; - } - nb_event = new_size; - } - +end: return nb_event; error: @@ -805,7 +813,8 @@ error: * Else, it's stays untouched and a lttcomm error code is returned. */ static int create_connect_relayd(struct lttng_uri *uri, - struct lttcomm_relayd_sock **relayd_sock) + struct lttcomm_relayd_sock **relayd_sock, + struct consumer_output *consumer) { int ret; struct lttcomm_relayd_sock *rsock; @@ -841,6 +850,8 @@ static int create_connect_relayd(struct lttng_uri *uri, ret = LTTNG_ERR_RELAYD_VERSION_FAIL; goto close_sock; } + consumer->relay_major_version = rsock->major; + consumer->relay_minor_version = rsock->minor; } else if (uri->stype == LTTNG_STREAM_DATA) { DBG3("Creating relayd data socket from URI"); } else { @@ -876,7 +887,7 @@ static int send_consumer_relayd_socket(enum lttng_domain_type domain, struct lttcomm_relayd_sock *rsock = NULL; /* Connect to relayd and make version check if uri is the control. */ - ret = create_connect_relayd(relayd_uri, &rsock); + ret = create_connect_relayd(relayd_uri, &rsock, consumer); if (ret != LTTNG_OK) { goto error; } @@ -1011,6 +1022,10 @@ int cmd_setup_relayd(struct ltt_session *session) /* Session is now ready for network streaming. */ session->net_handle = 1; } + session->consumer->relay_major_version = + usess->consumer->relay_major_version; + session->consumer->relay_minor_version = + usess->consumer->relay_minor_version; } if (ksess && ksess->consumer && ksess->consumer->type == CONSUMER_DST_NET @@ -1029,6 +1044,10 @@ int cmd_setup_relayd(struct ltt_session *session) /* Session is now ready for network streaming. */ session->net_handle = 1; } + session->consumer->relay_major_version = + ksess->consumer->relay_major_version; + session->consumer->relay_minor_version = + ksess->consumer->relay_minor_version; } error: @@ -1791,7 +1810,7 @@ static int _cmd_enable_event(struct ltt_session *session, int wpipe, bool internal_event) { int ret, channel_created = 0; - struct lttng_channel *attr; + struct lttng_channel *attr = NULL; assert(session); assert(event); @@ -1834,15 +1853,16 @@ static int _cmd_enable_event(struct ltt_session *session, ret = LTTNG_ERR_FATAL; goto error; } - strncpy(attr->name, channel_name, sizeof(attr->name)); + if (lttng_strncpy(attr->name, channel_name, + sizeof(attr->name))) { + ret = LTTNG_ERR_INVALID; + goto error; + } ret = cmd_enable_channel(session, domain, attr, wpipe); if (ret != LTTNG_OK) { - free(attr); goto error; } - free(attr); - channel_created = 1; } @@ -1971,14 +1991,16 @@ static int _cmd_enable_event(struct ltt_session *session, ret = LTTNG_ERR_FATAL; goto error; } - strncpy(attr->name, channel_name, sizeof(attr->name)); + if (lttng_strncpy(attr->name, channel_name, + sizeof(attr->name))) { + ret = LTTNG_ERR_INVALID; + goto error; + } ret = cmd_enable_channel(session, domain, attr, wpipe); if (ret != LTTNG_OK) { - free(attr); goto error; } - free(attr); /* Get the newly created channel reference back */ uchan = trace_ust_find_channel_by_name( @@ -2153,6 +2175,7 @@ error: free(filter_expression); free(filter); free(exclusion); + free(attr); rcu_read_unlock(); return ret; } @@ -3363,6 +3386,156 @@ error: return ret; } +/* + * Check if we can regenerate the metadata for this session. + * Only kernel, UST per-uid and non-live sessions are supported. + * + * Return 0 if the metadata can be generated, a LTTNG_ERR code otherwise. + */ +static +int check_metadata_regenerate_support(struct ltt_session *session) +{ + int ret; + + assert(session); + + if (session->live_timer != 0) { + ret = LTTNG_ERR_LIVE_SESSION; + goto end; + } + if (!session->active) { + ret = LTTNG_ERR_SESSION_NOT_STARTED; + goto end; + } + if (session->ust_session) { + switch (session->ust_session->buffer_type) { + case LTTNG_BUFFER_PER_UID: + break; + case LTTNG_BUFFER_PER_PID: + ret = LTTNG_ERR_PER_PID_SESSION; + goto end; + default: + assert(0); + ret = LTTNG_ERR_UNK; + goto end; + } + } + if (session->consumer->type == CONSUMER_DST_NET && + session->consumer->relay_minor_version < 8) { + ret = LTTNG_ERR_RELAYD_VERSION_FAIL; + goto end; + } + ret = 0; + +end: + return ret; +} + +static +int ust_metadata_regenerate(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++; + 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_METADATA_REGENERATE from the lttng-ctl library. + * + * Ask the consumer to truncate the existing metadata file(s) and + * then regenerate the metadata. Live and per-pid sessions are not + * supported and return an error. + * + * Return 0 on success or else a LTTNG_ERR code. + */ +int cmd_metadata_regenerate(struct ltt_session *session) +{ + int ret; + + assert(session); + + ret = check_metadata_regenerate_support(session); + if (ret) { + goto end; + } + + if (session->kernel_session) { + ret = kernctl_session_metadata_regenerate( + session->kernel_session->fd); + if (ret < 0) { + ERR("Failed to regenerate the kernel metadata"); + goto end; + } + } + + if (session->ust_session) { + ret = ust_metadata_regenerate(session->ust_session); + if (ret < 0) { + ERR("Failed to regenerate the UST metadata"); + goto end; + } + } + DBG("Cmd metadata regenerate for session %s", session->name); + ret = LTTNG_OK; + +end: + return ret; +} + + /* * Send relayd sockets from snapshot output to consumer. Ignore request if the * snapshot output is *not* set with a remote destination. @@ -3424,13 +3597,6 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess, assert(output); assert(session); - /* Get the datetime for the snapshot output directory. */ - ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime, - sizeof(output->datetime)); - if (!ret) { - ret = LTTNG_ERR_INVALID; - goto error; - } /* * Copy kernel session sockets so we can communicate with the right @@ -3478,14 +3644,6 @@ static int record_ust_snapshot(struct ltt_ust_session *usess, assert(output); assert(session); - /* Get the datetime for the snapshot output directory. */ - ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime, - sizeof(output->datetime)); - if (!ret) { - ret = LTTNG_ERR_INVALID; - goto error; - } - /* * Copy UST session sockets so we can communicate with the right * consumer for the snapshot record command. @@ -3507,9 +3665,6 @@ static int record_ust_snapshot(struct ltt_ust_session *usess, case EINVAL: ret = LTTNG_ERR_INVALID; break; - case ENODATA: - ret = LTTNG_ERR_SNAPSHOT_NODATA; - break; default: ret = LTTNG_ERR_SNAPSHOT_FAIL; break; @@ -3627,12 +3782,21 @@ int cmd_snapshot_record(struct ltt_session *session, unsigned int use_tmp_output = 0; struct snapshot_output tmp_output; unsigned int snapshot_success = 0; + char datetime[16]; assert(session); assert(output); DBG("Cmd snapshot record for session %s", session->name); + /* Get the datetime for the snapshot output directory. */ + ret = utils_get_current_time_str("%Y%m%d-%H%M%S", datetime, + sizeof(datetime)); + if (!ret) { + ret = LTTNG_ERR_INVALID; + goto error; + } + /* * Permission denied to create an output if the session is not * set in no output mode. @@ -3663,138 +3827,100 @@ int cmd_snapshot_record(struct ltt_session *session, } /* Use the global session count for the temporary snapshot. */ tmp_output.nb_snapshot = session->snapshot.nb_snapshot; + + /* Use the global datetime */ + memcpy(tmp_output.datetime, datetime, sizeof(datetime)); use_tmp_output = 1; } - if (session->kernel_session) { - struct ltt_kernel_session *ksess = session->kernel_session; + if (use_tmp_output) { + int64_t nb_packets_per_stream; - if (use_tmp_output) { - int64_t nb_packets_per_stream; + nb_packets_per_stream = get_session_nb_packets_per_stream(session, + tmp_output.max_size); + if (nb_packets_per_stream < 0) { + ret = LTTNG_ERR_MAX_SIZE_INVALID; + goto error; + } - nb_packets_per_stream = get_session_nb_packets_per_stream(session, - tmp_output.max_size); - if (nb_packets_per_stream < 0) { - ret = LTTNG_ERR_MAX_SIZE_INVALID; + if (session->kernel_session) { + ret = record_kernel_snapshot(session->kernel_session, + &tmp_output, session, + wait, nb_packets_per_stream); + if (ret != LTTNG_OK) { goto error; } - ret = record_kernel_snapshot(ksess, &tmp_output, session, + } + + if (session->ust_session) { + ret = record_ust_snapshot(session->ust_session, + &tmp_output, session, wait, nb_packets_per_stream); if (ret != LTTNG_OK) { goto error; } - snapshot_success = 1; - } else { - struct snapshot_output *sout; - struct lttng_ht_iter iter; - - rcu_read_lock(); - cds_lfht_for_each_entry(session->snapshot.output_ht->ht, - &iter.iter, sout, node.node) { - int64_t nb_packets_per_stream; - - /* - * Make a local copy of the output and assign the possible - * temporary value given by the caller. - */ - memset(&tmp_output, 0, sizeof(tmp_output)); - memcpy(&tmp_output, sout, sizeof(tmp_output)); - - if (output->max_size != (uint64_t) -1ULL) { - tmp_output.max_size = output->max_size; - } + } - nb_packets_per_stream = get_session_nb_packets_per_stream(session, - tmp_output.max_size); - if (nb_packets_per_stream < 0) { - ret = LTTNG_ERR_MAX_SIZE_INVALID; - goto error; - } + snapshot_success = 1; + } else { + struct snapshot_output *sout; + struct lttng_ht_iter iter; - /* Use temporary name. */ - if (*output->name != '\0') { - strncpy(tmp_output.name, output->name, - sizeof(tmp_output.name)); - } + rcu_read_lock(); + cds_lfht_for_each_entry(session->snapshot.output_ht->ht, + &iter.iter, sout, node.node) { + int64_t nb_packets_per_stream; - tmp_output.nb_snapshot = session->snapshot.nb_snapshot; + /* + * Make a local copy of the output and assign the possible + * temporary value given by the caller. + */ + memset(&tmp_output, 0, sizeof(tmp_output)); + memcpy(&tmp_output, sout, sizeof(tmp_output)); - ret = record_kernel_snapshot(ksess, &tmp_output, - session, wait, nb_packets_per_stream); - if (ret != LTTNG_OK) { - rcu_read_unlock(); - goto error; - } - snapshot_success = 1; + if (output->max_size != (uint64_t) -1ULL) { + tmp_output.max_size = output->max_size; } - rcu_read_unlock(); - } - } - - if (session->ust_session) { - struct ltt_ust_session *usess = session->ust_session; - - if (use_tmp_output) { - int64_t nb_packets_per_stream; nb_packets_per_stream = get_session_nb_packets_per_stream(session, tmp_output.max_size); if (nb_packets_per_stream < 0) { ret = LTTNG_ERR_MAX_SIZE_INVALID; + rcu_read_unlock(); goto error; } - ret = record_ust_snapshot(usess, &tmp_output, session, - wait, nb_packets_per_stream); - if (ret != LTTNG_OK) { - goto error; - } - snapshot_success = 1; - } else { - struct snapshot_output *sout; - struct lttng_ht_iter iter; - rcu_read_lock(); - cds_lfht_for_each_entry(session->snapshot.output_ht->ht, - &iter.iter, sout, node.node) { - int64_t nb_packets_per_stream; - - /* - * Make a local copy of the output and assign the possible - * temporary value given by the caller. - */ - memset(&tmp_output, 0, sizeof(tmp_output)); - memcpy(&tmp_output, sout, sizeof(tmp_output)); + /* Use temporary name. */ + if (*output->name != '\0') { + strncpy(tmp_output.name, output->name, + sizeof(tmp_output.name)); + } - if (output->max_size != (uint64_t) -1ULL) { - tmp_output.max_size = output->max_size; - } + tmp_output.nb_snapshot = session->snapshot.nb_snapshot; + memcpy(tmp_output.datetime, datetime, sizeof(datetime)); - nb_packets_per_stream = get_session_nb_packets_per_stream(session, - tmp_output.max_size); - if (nb_packets_per_stream < 0) { - ret = LTTNG_ERR_MAX_SIZE_INVALID; + if (session->kernel_session) { + ret = record_kernel_snapshot(session->kernel_session, + &tmp_output, session, + wait, nb_packets_per_stream); + if (ret != LTTNG_OK) { rcu_read_unlock(); goto error; } + } - /* Use temporary name. */ - if (*output->name != '\0') { - strncpy(tmp_output.name, output->name, - sizeof(tmp_output.name)); - } - - tmp_output.nb_snapshot = session->snapshot.nb_snapshot; - - ret = record_ust_snapshot(usess, &tmp_output, session, + if (session->ust_session) { + ret = record_ust_snapshot(session->ust_session, + &tmp_output, session, wait, nb_packets_per_stream); if (ret != LTTNG_OK) { rcu_read_unlock(); goto error; } - snapshot_success = 1; } - rcu_read_unlock(); + snapshot_success = 1; } + rcu_read_unlock(); } if (snapshot_success) {