X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=cc81906b6267ffc104ee357741d0b099af9fbc3c;hp=9af6d9d4acce64b9b9855e46ed462a624573c693;hb=7802bae326824ecb116cb0d782bb7472eaa6f6e4;hpb=93ec662e687dc15a3601704a1e0c96c51ad228c9 diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 9af6d9d4a..cc81906b6 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -187,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; @@ -216,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; } @@ -267,9 +275,12 @@ 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); + if (lttng_strncpy(channels[i].name, uchan->name, + LTTNG_SYMBOL_NAME_LEN)) { + break; + } channels[i].attr.overwrite = uchan->attr.overwrite; channels[i].attr.subbuf_size = uchan->attr.subbuf_size; channels[i].attr.num_subbuf = uchan->attr.num_subbuf; @@ -750,12 +761,15 @@ static int add_uri_to_consumer(struct consumer_output *consumer, DBG2("Setting trace directory path from URI to %s", uri->dst.path); memset(consumer->dst.trace_path, 0, sizeof(consumer->dst.trace_path)); - strncpy(consumer->dst.trace_path, uri->dst.path, - sizeof(consumer->dst.trace_path)); + /* Explicit length checks for strcpy and strcat. */ + if (strlen(uri->dst.path) + strlen(default_trace_dir) + >= sizeof(consumer->dst.trace_path)) { + ret = LTTNG_ERR_FATAL; + goto error; + } + strcpy(consumer->dst.trace_path, uri->dst.path); /* Append default trace dir */ - strncat(consumer->dst.trace_path, default_trace_dir, - sizeof(consumer->dst.trace_path) - - strlen(consumer->dst.trace_path) - 1); + strcat(consumer->dst.trace_path, default_trace_dir); /* Flag consumer as local. */ consumer->type = CONSUMER_DST_LOCAL; break; @@ -1319,16 +1333,6 @@ int cmd_enable_channel(struct ltt_session *session, attr->attr.switch_timer_interval = 0; } - /* - * The ringbuffer (both in user space and kernel) behave badly in overwrite - * mode and with less than 2 subbuf so block it right away and send back an - * invalid attribute error. - */ - if (attr->attr.overwrite && attr->attr.num_subbuf < 2) { - ret = LTTNG_ERR_INVALID; - goto error; - } - switch (domain->type) { case LTTNG_DOMAIN_KERNEL: { @@ -1802,7 +1806,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); @@ -1845,15 +1849,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; } @@ -1982,14 +1987,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( @@ -2164,6 +2171,7 @@ error: free(filter_expression); free(filter); free(exclusion); + free(attr); rcu_read_unlock(); return ret; } @@ -2429,7 +2437,15 @@ int cmd_stop_trace(struct ltt_session *session) if (ksession && ksession->active) { DBG("Stop kernel tracing"); - /* Flush metadata if exist */ + ret = kernel_stop_session(ksession); + if (ret < 0) { + ret = LTTNG_ERR_KERN_STOP_FAIL; + goto error; + } + + kernel_wait_quiescent(kernel_tracer_fd); + + /* Flush metadata after stopping (if exists) */ if (ksession->metadata_stream_fd >= 0) { ret = kernel_metadata_flush_buffer(ksession->metadata_stream_fd); if (ret < 0) { @@ -2437,7 +2453,7 @@ int cmd_stop_trace(struct ltt_session *session) } } - /* Flush all buffers before stopping */ + /* Flush all buffers after stopping */ cds_list_for_each_entry(kchan, &ksession->channel_list.head, list) { ret = kernel_flush_buffer(kchan); if (ret < 0) { @@ -2445,14 +2461,6 @@ int cmd_stop_trace(struct ltt_session *session) } } - ret = kernel_stop_session(ksession); - if (ret < 0) { - ret = LTTNG_ERR_KERN_STOP_FAIL; - goto error; - } - - kernel_wait_quiescent(kernel_tracer_fd); - ksession->active = 0; } @@ -2740,64 +2748,6 @@ int cmd_destroy_session(struct ltt_session *session, int wpipe) return ret; } -/* - * Command LTTNG_CALIBRATE processed by the client thread. - */ -int cmd_calibrate(enum lttng_domain_type domain, - struct lttng_calibrate *calibrate) -{ - int ret; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - { - struct lttng_kernel_calibrate kcalibrate; - - switch (calibrate->type) { - case LTTNG_CALIBRATE_FUNCTION: - default: - /* Default and only possible calibrate option. */ - kcalibrate.type = LTTNG_KERNEL_CALIBRATE_KRETPROBE; - break; - } - - ret = kernel_calibrate(kernel_tracer_fd, &kcalibrate); - if (ret < 0) { - ret = LTTNG_ERR_KERN_ENABLE_FAIL; - goto error; - } - break; - } - case LTTNG_DOMAIN_UST: - { - struct lttng_ust_calibrate ucalibrate; - - switch (calibrate->type) { - case LTTNG_CALIBRATE_FUNCTION: - default: - /* Default and only possible calibrate option. */ - ucalibrate.type = LTTNG_UST_CALIBRATE_TRACEPOINT; - break; - } - - ret = ust_app_calibrate_glb(&ucalibrate); - if (ret < 0) { - ret = LTTNG_ERR_UST_CALIBRATE_FAIL; - goto error; - } - break; - } - default: - ret = LTTNG_ERR_UND; - goto error; - } - - ret = LTTNG_OK; - -error: - return ret; -} - /* * Command LTTNG_REGISTER_CONSUMER processed by the client thread. */ @@ -3199,11 +3149,10 @@ int cmd_snapshot_add_output(struct ltt_session *session, DBG("Cmd snapshot add output for session %s", session->name); /* - * Permission denied to create an output if the session is not - * set in no output mode. + * Can't create an output if the session is not set in no-output mode. */ if (session->output_traces) { - ret = LTTNG_ERR_EPERM; + ret = LTTNG_ERR_NOT_SNAPSHOT_SESSION; goto error; } @@ -3267,7 +3216,7 @@ int cmd_snapshot_del_output(struct ltt_session *session, * set in no output mode. */ if (session->output_traces) { - ret = LTTNG_ERR_EPERM; + ret = LTTNG_ERR_NOT_SNAPSHOT_SESSION; goto error; } @@ -3319,19 +3268,19 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, * set in no output mode. */ if (session->output_traces) { - ret = -LTTNG_ERR_EPERM; - goto error; + ret = -LTTNG_ERR_NOT_SNAPSHOT_SESSION; + goto end; } if (session->snapshot.nb_output == 0) { ret = 0; - goto error; + goto end; } list = zmalloc(session->snapshot.nb_output * sizeof(*list)); if (!list) { ret = -LTTNG_ERR_NOMEM; - goto error; + goto end; } /* Copy list from session to the new list object. */ @@ -3341,10 +3290,18 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, assert(output->consumer); list[idx].id = output->id; list[idx].max_size = output->max_size; - strncpy(list[idx].name, output->name, sizeof(list[idx].name)); + if (lttng_strncpy(list[idx].name, output->name, + sizeof(list[idx].name))) { + ret = -LTTNG_ERR_INVALID; + goto error; + } if (output->consumer->type == CONSUMER_DST_LOCAL) { - strncpy(list[idx].ctrl_url, output->consumer->dst.trace_path, - sizeof(list[idx].ctrl_url)); + if (lttng_strncpy(list[idx].ctrl_url, + output->consumer->dst.trace_path, + sizeof(list[idx].ctrl_url))) { + ret = -LTTNG_ERR_INVALID; + goto error; + } } else { /* Control URI. */ ret = uri_to_str_url(&output->consumer->dst.net.control, @@ -3369,8 +3326,9 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, list = NULL; ret = session->snapshot.nb_output; error: - free(list); rcu_read_unlock(); + free(list); +end: return ret; } @@ -3381,7 +3339,7 @@ error: * Return 0 if the metadata can be generated, a LTTNG_ERR code otherwise. */ static -int check_metadata_regenerate_support(struct ltt_session *session) +int check_regenerate_metadata_support(struct ltt_session *session) { int ret; @@ -3420,7 +3378,28 @@ end: } static -int ust_metadata_regenerate(struct ltt_ust_session *usess) +int clear_metadata_file(int fd) +{ + int ret; + + ret = lseek(fd, 0, SEEK_SET); + if (ret < 0) { + PERROR("lseek"); + 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; @@ -3440,6 +3419,15 @@ int ust_metadata_regenerate(struct ltt_ust_session *usess) 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) { @@ -3481,7 +3469,7 @@ end: } /* - * Command LTTNG_METADATA_REGENERATE from the lttng-ctl library. + * Command LTTNG_REGENERATE_METADATA 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 @@ -3489,19 +3477,19 @@ end: * * Return 0 on success or else a LTTNG_ERR code. */ -int cmd_metadata_regenerate(struct ltt_session *session) +int cmd_regenerate_metadata(struct ltt_session *session) { int ret; assert(session); - ret = check_metadata_regenerate_support(session); + ret = check_regenerate_metadata_support(session); if (ret) { goto end; } if (session->kernel_session) { - ret = kernctl_session_metadata_regenerate( + ret = kernctl_session_regenerate_metadata( session->kernel_session->fd); if (ret < 0) { ERR("Failed to regenerate the kernel metadata"); @@ -3510,7 +3498,7 @@ int cmd_metadata_regenerate(struct ltt_session *session) } if (session->ust_session) { - ret = ust_metadata_regenerate(session->ust_session); + ret = ust_regenerate_metadata(session->ust_session); if (ret < 0) { ERR("Failed to regenerate the UST metadata"); goto end; @@ -3523,6 +3511,60 @@ end: return ret; } +/* + * Command LTTNG_REGENERATE_STATEDUMP from the lttng-ctl library. + * + * Ask the tracer to regenerate a new statedump. + * + * Return 0 on success or else a LTTNG_ERR code. + */ +int cmd_regenerate_statedump(struct ltt_session *session) +{ + int ret; + + assert(session); + + if (!session->active) { + ret = LTTNG_ERR_SESSION_NOT_STARTED; + goto end; + } + ret = 0; + + if (session->kernel_session) { + ret = kernctl_session_regenerate_statedump( + session->kernel_session->fd); + /* + * Currently, the statedump in kernel can only fail if out + * of memory. + */ + if (ret < 0) { + if (ret == -ENOMEM) { + ret = LTTNG_ERR_REGEN_STATEDUMP_NOMEM; + } else { + ret = LTTNG_ERR_REGEN_STATEDUMP_FAIL; + } + ERR("Failed to regenerate the kernel statedump"); + goto end; + } + } + + if (session->ust_session) { + ret = ust_app_regenerate_statedump_all(session->ust_session); + /* + * Currently, the statedump in UST always returns 0. + */ + if (ret < 0) { + ret = LTTNG_ERR_REGEN_STATEDUMP_FAIL; + ERR("Failed to regenerate the UST statedump"); + goto end; + } + } + DBG("Cmd regenerate statedump for session %s", session->name); + ret = LTTNG_OK; + +end: + return ret; +} /* * Send relayd sockets from snapshot output to consumer. Ignore request if the @@ -3585,13 +3627,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 @@ -3639,14 +3674,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. @@ -3668,9 +3695,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; @@ -3788,18 +3812,27 @@ 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. */ if (session->output_traces) { - ret = LTTNG_ERR_EPERM; + ret = LTTNG_ERR_NOT_SNAPSHOT_SESSION; goto error; } @@ -3824,138 +3857,104 @@ 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)); - - 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; + /* Use temporary name. */ + if (*output->name != '\0') { + if (lttng_strncpy(tmp_output.name, output->name, + sizeof(tmp_output.name))) { + ret = LTTNG_ERR_INVALID; 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; + memcpy(tmp_output.datetime, datetime, sizeof(datetime)); - tmp_output.nb_snapshot = session->snapshot.nb_snapshot; + 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; + } + } - 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) {