X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=50bacf0c236dc3ea4917a6f4100a80aa39b98623;hp=ba7dd3d4dd9452b92328547f7f09e24a7e389cf1;hb=d5a1b7aa06b4c924b1cd30623758343c74ecab5c;hpb=66ea93b10c703e1b3dda1e17109eed9138e4ece2 diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index ba7dd3d4d..50bacf0c2 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include #include "channel.h" @@ -55,7 +57,7 @@ #include "notification-thread-commands.h" #include "rotate.h" #include "rotation-thread.h" -#include "sessiond-timer.h" +#include "timer.h" #include "agent-thread.h" #include "cmd.h" @@ -383,9 +385,13 @@ end: } } -static void increment_extended_len(const char *filter_expression, - struct lttng_event_exclusion *exclusion, size_t *extended_len) +static int increment_extended_len(const char *filter_expression, + struct lttng_event_exclusion *exclusion, + const struct lttng_userspace_probe_location *probe_location, + size_t *extended_len) { + int ret = 0; + *extended_len += sizeof(struct lttcomm_event_extended_header); if (filter_expression) { @@ -395,14 +401,31 @@ static void increment_extended_len(const char *filter_expression, if (exclusion) { *extended_len += exclusion->count * LTTNG_SYMBOL_NAME_LEN; } + + if (probe_location) { + ret = lttng_userspace_probe_location_serialize(probe_location, + NULL, NULL); + if (ret < 0) { + goto end; + } + *extended_len += ret; + } + ret = 0; +end: + return ret; } -static void append_extended_info(const char *filter_expression, - struct lttng_event_exclusion *exclusion, void **extended_at) +static int append_extended_info(const char *filter_expression, + struct lttng_event_exclusion *exclusion, + struct lttng_userspace_probe_location *probe_location, + void **extended_at) { - struct lttcomm_event_extended_header extended_header; + int ret = 0; size_t filter_len = 0; size_t nb_exclusions = 0; + size_t userspace_probe_location_len = 0; + struct lttng_dynamic_buffer location_buffer; + struct lttcomm_event_extended_header extended_header; if (filter_expression) { filter_len = strlen(filter_expression) + 1; @@ -412,9 +435,21 @@ static void append_extended_info(const char *filter_expression, nb_exclusions = exclusion->count; } + if (probe_location) { + lttng_dynamic_buffer_init(&location_buffer); + ret = lttng_userspace_probe_location_serialize(probe_location, + &location_buffer, NULL); + if (ret < 0) { + ret = -1; + goto end; + } + userspace_probe_location_len = location_buffer.size; + } + /* Set header fields */ extended_header.filter_len = filter_len; extended_header.nb_exclusions = nb_exclusions; + extended_header.userspace_probe_location_len = userspace_probe_location_len; /* Copy header */ memcpy(*extended_at, &extended_header, sizeof(extended_header)); @@ -433,6 +468,15 @@ static void append_extended_info(const char *filter_expression, memcpy(*extended_at, &exclusion->names, len); *extended_at += len; } + + if (probe_location) { + memcpy(*extended_at, location_buffer.data, location_buffer.size); + *extended_at += location_buffer.size; + lttng_dynamic_buffer_reset(&location_buffer); + } + ret = 0; +end: + return ret; } /* @@ -446,7 +490,7 @@ static int list_lttng_agent_events(struct agent *agt, int i = 0, ret = 0; unsigned int nb_event = 0; struct agent_event *event; - struct lttng_event *tmp_events; + struct lttng_event *tmp_events = NULL; struct lttng_ht_iter iter; size_t extended_len = 0; void *extended_at; @@ -474,8 +518,13 @@ static int list_lttng_agent_events(struct agent *agt, */ rcu_read_lock(); cds_lfht_for_each_entry(agt->events->ht, &iter.iter, event, node.node) { - increment_extended_len(event->filter_expression, NULL, + ret = increment_extended_len(event->filter_expression, NULL, NULL, &extended_len); + if (ret) { + DBG("Error computing the length of extended info message"); + ret = -LTTNG_ERR_FATAL; + goto error; + } } rcu_read_unlock(); @@ -500,17 +549,25 @@ static int list_lttng_agent_events(struct agent *agt, i++; /* Append extended info */ - append_extended_info(event->filter_expression, NULL, + ret = append_extended_info(event->filter_expression, NULL, NULL, &extended_at); + if (ret) { + DBG("Error appending extended info message"); + ret = -LTTNG_ERR_FATAL; + goto error; + } } - rcu_read_unlock(); *events = tmp_events; ret = nb_event; - -error: assert(nb_event == i); + +end: + rcu_read_unlock(); return ret; +error: + free(tmp_events); + goto end; } /* @@ -559,8 +616,13 @@ static int list_lttng_ust_global_events(char *channel_name, continue; } - increment_extended_len(uevent->filter_expression, - uevent->exclusion, &extended_len); + ret = increment_extended_len(uevent->filter_expression, + uevent->exclusion, NULL, &extended_len); + if (ret) { + DBG("Error computing the length of extended info message"); + ret = -LTTNG_ERR_FATAL; + goto end; + } } if (nb_event == 0) { /* All events are internal, skip. */ @@ -620,8 +682,13 @@ static int list_lttng_ust_global_events(char *channel_name, i++; /* Append extended info */ - append_extended_info(uevent->filter_expression, - uevent->exclusion, &extended_at); + ret = append_extended_info(uevent->filter_expression, + uevent->exclusion, NULL, &extended_at); + if (ret) { + DBG("Error appending extended info message"); + ret = -LTTNG_ERR_FATAL; + goto end; + } } ret = nb_event; @@ -663,14 +730,20 @@ static int list_lttng_kernel_events(char *channel_name, /* Compute required extended infos size */ cds_list_for_each_entry(event, &kchan->events_list.head, list) { - increment_extended_len(event->filter_expression, NULL, + ret = increment_extended_len(event->filter_expression, NULL, + event->userspace_probe_location, &extended_len); + if (ret) { + DBG("Error computing the length of extended info message"); + ret = -LTTNG_ERR_FATAL; + goto error; + } } *total_size = nb_event * sizeof(struct lttng_event) + extended_len; *events = zmalloc(*total_size); if (*events == NULL) { - ret = LTTNG_ERR_FATAL; + ret = -LTTNG_ERR_FATAL; goto error; } @@ -699,6 +772,9 @@ static int list_lttng_kernel_events(char *channel_name, memcpy(&(*events)[i].attr.probe, &event->event->u.kprobe, sizeof(struct lttng_kernel_kprobe)); break; + case LTTNG_KERNEL_UPROBE: + (*events)[i].type = LTTNG_EVENT_USERSPACE_PROBE; + break; case LTTNG_KERNEL_FUNCTION: (*events)[i].type = LTTNG_EVENT_FUNCTION; memcpy(&((*events)[i].attr.ftrace), &event->event->u.ftrace, @@ -711,14 +787,21 @@ static int list_lttng_kernel_events(char *channel_name, (*events)[i].type = LTTNG_EVENT_SYSCALL; break; case LTTNG_KERNEL_ALL: + /* fall-through. */ + default: assert(0); break; } i++; /* Append extended info */ - append_extended_info(event->filter_expression, NULL, - &extended_at); + ret = append_extended_info(event->filter_expression, NULL, + event->userspace_probe_location, &extended_at); + if (ret) { + DBG("Error appending extended info message"); + ret = -LTTNG_ERR_FATAL; + goto error; + } } end: @@ -1995,6 +2078,7 @@ static int _cmd_enable_event(struct ltt_session *session, break; } case LTTNG_EVENT_PROBE: + case LTTNG_EVENT_USERSPACE_PROBE: case LTTNG_EVENT_FUNCTION: case LTTNG_EVENT_FUNCTION_ENTRY: case LTTNG_EVENT_TRACEPOINT: @@ -2092,8 +2176,7 @@ static int _cmd_enable_event(struct ltt_session *session, ret = validate_ust_event_name(event->name); if (ret) { WARN("Userspace event name %s failed validation.", - event->name ? - event->name : "NULL"); + event->name); ret = LTTNG_ERR_INVALID_EVENT_NAME; goto error; } @@ -2618,7 +2701,7 @@ int cmd_start_trace(struct ltt_session *session) session->rotated_after_last_stop = false; if (session->rotate_timer_period) { - ret = sessiond_rotate_timer_start(session, + ret = timer_session_rotation_schedule_timer_start(session, session->rotate_timer_period); if (ret < 0) { ERR("Failed to enable rotate timer"); @@ -2633,48 +2716,6 @@ error: return ret; } -static -int rename_active_chunk(struct ltt_session *session) -{ - int ret; - - session->current_archive_id++; - - /* - * The currently active tracing path is now the folder we - * want to rename. - */ - ret = lttng_strncpy(session->rotation_chunk.current_rotate_path, - session->rotation_chunk.active_tracing_path, - sizeof(session->rotation_chunk.current_rotate_path)); - if (ret) { - ERR("Failed to copy active tracing path"); - goto end; - } - - ret = rename_complete_chunk(session, time(NULL)); - if (ret < 0) { - ERR("Failed to rename current rotate path"); - goto end; - } - - /* - * We just renamed, the folder, we didn't do an actual rotation, so - * the active tracing path is now the renamed folder and we have to - * restore the rotate count. - */ - ret = lttng_strncpy(session->rotation_chunk.active_tracing_path, - session->rotation_chunk.current_rotate_path, - sizeof(session->rotation_chunk.active_tracing_path)); - if (ret) { - ERR("Failed to rename active session chunk tracing path"); - goto end; - } -end: - session->current_archive_id--; - return ret; -} - /* * Command LTTNG_STOP_TRACE processed by the client thread. */ @@ -2699,15 +2740,22 @@ int cmd_stop_trace(struct ltt_session *session) goto error; } - if (session->rotate_relay_pending_timer_enabled) { - sessiond_timer_rotate_pending_stop(session); - } - - if (session->rotate_timer_enabled) { - sessiond_rotate_timer_stop(session); + if (session->rotation_schedule_timer_enabled) { + if (timer_session_rotation_schedule_timer_stop( + session)) { + ERR("Failed to stop the \"rotation schedule\" timer of session %s", + session->name); + } } - if (session->current_archive_id > 0 && !session->rotate_pending) { + /* + * A rotation is still ongoing. The check timer will continue to wait + * for the rotation to complete. When the rotation finally completes, + * a check will be performed to rename the "active" chunk to the + * expected "timestamp_begin-timestamp_end" format. + */ + if (session->current_archive_id > 0 && + session->rotation_state != LTTNG_ROTATION_STATE_ONGOING) { ret = rename_active_chunk(session); if (ret) { /* @@ -3006,12 +3054,19 @@ int cmd_destroy_session(struct ltt_session *session, int wpipe, DBG("Begin destroy session %s (id %" PRIu64 ")", session->name, session->id); - if (session->rotate_relay_pending_timer_enabled) { - sessiond_timer_rotate_pending_stop(session); + if (session->rotation_pending_check_timer_enabled) { + if (timer_session_rotation_pending_check_stop(session)) { + ERR("Failed to stop the \"rotation pending check\" timer of session %s", + session->name); + } } - if (session->rotate_timer_enabled) { - sessiond_rotate_timer_stop(session); + if (session->rotation_schedule_timer_enabled) { + if (timer_session_rotation_schedule_timer_stop( + session)) { + ERR("Failed to stop the \"rotation schedule\" timer of session %s", + session->name); + } } if (session->rotate_size) { @@ -3481,10 +3536,8 @@ int cmd_data_pending(struct ltt_session *session) } } - /* - * A rotation is still pending, we have to wait. - */ - if (session->rotate_pending) { + /* A rotation is still pending, we have to wait. */ + if (session->rotation_state == LTTNG_ROTATION_STATE_ONGOING) { DBG("Rotate still pending for session %s", session->name); ret = 1; goto error; @@ -4468,28 +4521,33 @@ int cmd_set_session_shm_path(struct ltt_session *session, * Ask the consumer to rotate the session output directory. * The session lock must be held. * - * Return LTTNG_OK on success or else a LTTNG_ERR code. + * Returns LTTNG_OK on success or else a negative LTTng error code. */ int cmd_rotate_session(struct ltt_session *session, struct lttng_rotate_session_return *rotate_return) { int ret; + enum lttng_error_code cmd_ret = LTTNG_OK; size_t strf_ret; struct tm *timeinfo; char datetime[21]; time_t now; - bool ust_active = false; + /* + * Used to roll-back timestamps in case of failure to launch the + * rotation. + */ + time_t original_last_chunk_start_ts, original_current_chunk_start_ts; assert(session); if (!session->has_been_started) { - ret = -LTTNG_ERR_START_SESSION_ONCE; + cmd_ret = LTTNG_ERR_START_SESSION_ONCE; goto end; } if (session->live_timer || session->snapshot_mode || !session->output_traces) { - ret = -LTTNG_ERR_ROTATION_NOT_AVAILABLE; + cmd_ret = LTTNG_ERR_ROTATION_NOT_AVAILABLE; goto end; } @@ -4499,13 +4557,14 @@ int cmd_rotate_session(struct ltt_session *session, if (session->consumer->type == CONSUMER_DST_NET && (session->consumer->relay_major_version == 2 && session->consumer->relay_minor_version < 11)) { - ret = -LTTNG_ERR_ROTATION_NOT_AVAILABLE_RELAY; + cmd_ret = LTTNG_ERR_ROTATION_NOT_AVAILABLE_RELAY; goto end; } - if (session->rotate_pending || session->rotate_pending_relay) { - ret = -LTTNG_ERR_ROTATION_PENDING; - DBG("Rotate already in progress"); + if (session->rotation_state == LTTNG_ROTATION_STATE_ONGOING) { + DBG("Refusing to launch a rotation; a rotation is already in progress for session %s", + session->name); + cmd_ret = LTTNG_ERR_ROTATION_PENDING; goto end; } @@ -4516,7 +4575,7 @@ int cmd_rotate_session(struct ltt_session *session, if (session->rotated_after_last_stop) { DBG("Session \"%s\" was already rotated after stop, refusing rotation", session->name); - ret = -LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP; + cmd_ret = LTTNG_ERR_ROTATION_MULTIPLE_AFTER_STOP; goto end; } @@ -4524,21 +4583,17 @@ int cmd_rotate_session(struct ltt_session *session, if (session->current_archive_id == 0) { const char *base_path = NULL; + assert(session->kernel_session || session->ust_session); /* Either one of the two sessions is enough to get the root path. */ - if (session->kernel_session) { - base_path = session_get_base_path(session); - } else if (session->ust_session) { - base_path = session_get_base_path(session); - } else { - assert(0); - } + base_path = session_get_base_path(session); assert(base_path); + ret = lttng_strncpy(session->rotation_chunk.current_rotate_path, base_path, sizeof(session->rotation_chunk.current_rotate_path)); if (ret) { ERR("Failed to copy session base path to current rotation chunk path"); - ret = -LTTNG_ERR_UNK; + cmd_ret = LTTNG_ERR_UNK; goto end; } } else { @@ -4551,40 +4606,54 @@ int cmd_rotate_session(struct ltt_session *session, sizeof(session->rotation_chunk.current_rotate_path)); if (ret) { ERR("Failed to copy the active tracing path to the current rotate path"); - ret = -LTTNG_ERR_UNK; + cmd_ret = LTTNG_ERR_UNK; goto end; } } DBG("Current rotate path %s", session->rotation_chunk.current_rotate_path); - session->current_archive_id++; - session->rotate_pending = true; - session->rotation_state = LTTNG_ROTATION_STATE_ONGOING; - /* - * Create the path name for the next chunk. + * Channels created after this point will belong to the next + * archive id. */ + session->current_archive_id++; + now = time(NULL); if (now == (time_t) -1) { - ret = -LTTNG_ERR_ROTATION_NOT_AVAILABLE; + cmd_ret = LTTNG_ERR_ROTATION_NOT_AVAILABLE; goto end; } + + /* Sample chunk bounds for roll-back in case of error. */ + original_last_chunk_start_ts = session->last_chunk_start_ts; + original_current_chunk_start_ts = session->current_chunk_start_ts; + session->last_chunk_start_ts = session->current_chunk_start_ts; session->current_chunk_start_ts = now; timeinfo = localtime(&now); if (!timeinfo) { PERROR("Failed to sample local time in rotate session command"); - ret = -LTTNG_ERR_UNK; + cmd_ret = LTTNG_ERR_UNK; goto end; } strf_ret = strftime(datetime, sizeof(datetime), "%Y%m%dT%H%M%S%z", timeinfo); if (!strf_ret) { ERR("Failed to format local time timestamp in rotate session command"); - ret = -LTTNG_ERR_UNK; + cmd_ret = LTTNG_ERR_UNK; goto end; } + + /* + * A rotation has a local step even if the destination is a relay + * daemon; the buffers must be consumed by the consumer daemon. + */ + session->rotation_pending_local = true; + session->rotation_pending_relay = + session_get_consumer_destination_type(session) == CONSUMER_DST_NET; + session->rotation_state = LTTNG_ROTATION_STATE_ONGOING; + if (session->kernel_session) { /* * The active path for the next rotation/destroy. @@ -4597,8 +4666,8 @@ int cmd_rotate_session(struct ltt_session *session, datetime, session->current_archive_id + 1); if (ret < 0 || ret == sizeof(session->rotation_chunk.active_tracing_path)) { ERR("Failed to format active kernel tracing path in rotate session command"); - ret = -LTTNG_ERR_UNK; - goto end; + cmd_ret = LTTNG_ERR_UNK; + goto error; } /* * The sub-directory for the consumer @@ -4610,8 +4679,8 @@ int cmd_rotate_session(struct ltt_session *session, session->current_archive_id + 1); if (ret < 0 || ret == sizeof(session->kernel_session->consumer->chunk_path)) { ERR("Failed to format the kernel consumer's sub-directory in rotate session command"); - ret = -LTTNG_ERR_UNK; - goto end; + cmd_ret = LTTNG_ERR_UNK; + goto error; } /* * Create the new chunk folder, before the rotation begins so we don't @@ -4623,13 +4692,12 @@ int cmd_rotate_session(struct ltt_session *session, if (ret) { ERR("Failed to create kernel session tracing path at %s", session->kernel_session->consumer->chunk_path); - ret = -LTTNG_ERR_CREATE_DIR_FAIL; - goto end; + cmd_ret = LTTNG_ERR_CREATE_DIR_FAIL; + goto error; } - ret = kernel_rotate_session(session); - if (ret != LTTNG_OK) { - ret = -ret; - goto end; + cmd_ret = kernel_rotate_session(session); + if (cmd_ret != LTTNG_OK) { + goto error; } } if (session->ust_session) { @@ -4639,16 +4707,16 @@ int cmd_rotate_session(struct ltt_session *session, datetime, session->current_archive_id + 1); if (ret < 0) { ERR("Failed to format active UST tracing path in rotate session command"); - ret = -LTTNG_ERR_UNK; - goto end; + cmd_ret = LTTNG_ERR_UNK; + goto error; } ret = snprintf(session->ust_session->consumer->chunk_path, PATH_MAX, "/%s-%" PRIu64, datetime, session->current_archive_id + 1); if (ret < 0) { ERR("Failed to format the UST consumer's sub-directory in rotate session command"); - ret = -LTTNG_ERR_UNK; - goto end; + cmd_ret = LTTNG_ERR_UNK; + goto error; } /* * Create the new chunk folder, before the rotation begins so we don't @@ -4658,30 +4726,26 @@ int cmd_rotate_session(struct ltt_session *session, session->ust_session->uid, session->ust_session->gid); if (ret) { - ret = -LTTNG_ERR_CREATE_DIR_FAIL; - goto end; - } - ret = ust_app_rotate_session(session, &ust_active); - if (ret != LTTNG_OK) { - goto end; + cmd_ret = LTTNG_ERR_CREATE_DIR_FAIL; + goto error; } /* - * Handle the case where we did not start a rotation on any channel. - * The consumer will never wake up the rotation thread to perform the - * rename, so we have to do it here while we hold the session and - * session_list locks. + * TODO: ust_app_rotate_session must be adapted to return + * an lttng_error_code, like its kernel counterpart. */ - if (!session->kernel_session && !ust_active) { - ret = rename_complete_chunk(session, now); - if (ret < 0) { - ERR("Failed to rename completed rotation chunk"); - goto end; - } - session->rotate_pending = false; - session->rotation_state = LTTNG_ROTATION_STATE_COMPLETED; + cmd_ret = ust_app_rotate_session(session); + if (cmd_ret != LTTNG_OK) { + goto error; } } + ret = timer_session_rotation_pending_check_start(session, + DEFAULT_ROTATE_PENDING_TIMER); + if (ret) { + cmd_ret = LTTNG_ERR_UNK; + goto error; + } + if (!session->active) { session->rotated_after_last_stop = true; } @@ -4690,12 +4754,30 @@ int cmd_rotate_session(struct ltt_session *session, rotate_return->rotation_id = session->current_archive_id; } - DBG("Cmd rotate session %s, current_archive_id %" PRIu64 " sent", - session->name, session->current_archive_id); - ret = LTTNG_OK; + ret = notification_thread_command_session_rotation_ongoing( + notification_thread_handle, + session->name, session->uid, session->gid, + session->current_archive_id - 1); + if (ret != LTTNG_OK) { + ERR("Failed to notify notification thread that a session rotation is ongoing for session %s", + session->name); + cmd_ret = ret; + } + DBG("Cmd rotate session %s, archive_id %" PRIu64 " sent", + session->name, session->current_archive_id - 1); end: + ret = (cmd_ret == LTTNG_OK) ? cmd_ret : -((int) cmd_ret); return ret; +error: + session->last_chunk_start_ts = original_last_chunk_start_ts; + session->current_archive_id = original_current_chunk_start_ts; + if (session_reset_rotation_state(session, + LTTNG_ROTATION_STATE_NO_ROTATION)) { + ERR("Failed to reset rotation state of session \"%s\"", + session->name); + } + goto end; } /* @@ -4892,17 +4974,20 @@ int cmd_rotation_set_schedule(struct ltt_session *session, * Only start the timer if the session is active, * otherwise it will be started when the session starts. */ - ret = sessiond_rotate_timer_start(session, new_value); + ret = timer_session_rotation_schedule_timer_start( + session, new_value); if (ret) { ERR("Failed to enable session rotation timer in ROTATION_SET_SCHEDULE command"); ret = LTTNG_ERR_UNK; goto end; } } else { - ret = sessiond_rotate_timer_stop(session); + ret = timer_session_rotation_schedule_timer_stop( + session); if (ret) { ERR("Failed to disable session rotation timer in ROTATION_SET_SCHEDULE command"); ret = LTTNG_ERR_UNK; + goto end; } } break; @@ -4939,58 +5024,6 @@ end: return ret; } -/* - * Command ROTATE_GET_CURRENT_PATH from the lttng-ctl library. - * - * Configure the automatic rotation parameters. - * Set to -1ULL to disable them. - * - * Return LTTNG_OK on success or else a LTTNG_ERR code. - */ -int cmd_session_get_current_output(struct ltt_session *session, - struct lttng_session_get_current_output_return *output_return) -{ - int ret; - const char *path; - - if (!session->snapshot_mode) { - if (session->current_archive_id == 0) { - if (session->kernel_session) { - path = session_get_base_path(session); - } else if (session->ust_session) { - path = session_get_base_path(session); - } else { - abort(); - } - assert(path); - } else { - path = session->rotation_chunk.active_tracing_path; - } - } else { - /* - * A snapshot session does not have a "current" trace archive - * location. - */ - path = ""; - } - - DBG("Cmd get current output for session %s, returning %s", - session->name, path); - - ret = lttng_strncpy(output_return->path, - path, - sizeof(output_return->path)); - if (ret) { - ERR("Failed to copy trace output path to session get current output command reply"); - ret = -LTTNG_ERR_UNK; - goto end; - } - - ret = LTTNG_OK; -end: - return ret; -} - /* Wait for a given path to be removed before continuing. */ static enum lttng_error_code wait_on_path(void *path_data) {