X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fsave.c;h=f8911aa53adb1157a13385e79f7ae508d94650c8;hp=8599d2d18a6796bc3c6ba90017f4ea55420c0d6d;hb=1adbdb1045a79cd4a02941c5994820ccb17a68c3;hpb=fb198a1138d32ac7218695c564909d96018eb1b7 diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index 8599d2d18..f8911aa53 100644 --- a/src/bin/lttng-sessiond/save.c +++ b/src/bin/lttng-sessiond/save.c @@ -16,6 +16,7 @@ */ #define _GNU_SOURCE +#define _LGPL_SOURCE #include #include #include @@ -25,13 +26,14 @@ #include #include #include -#include #include #include #include +#include "kernel.h" #include "save.h" #include "session.h" +#include "syscall.h" #include "trace-ust.h" static @@ -259,8 +261,14 @@ const char *get_ust_context_type_string( case LTTNG_UST_CONTEXT_PTHREAD_ID: context_type_string = config_event_context_pthread_id; break; + case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER: + /* + * Error, should not be stored in the XML, perf contexts + * are stored as a node of type event_perf_context_type. + */ default: context_type_string = NULL; + break; } return context_type_string; @@ -355,6 +363,16 @@ int save_kernel_event(struct config_writer *writer, goto end; } + if (event->filter_expression) { + ret = config_writer_write_element_string(writer, + config_element_filter, + event->filter_expression); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + } + if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION || event->event->instrumentation == LTTNG_KERNEL_KPROBE || event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) { @@ -367,6 +385,7 @@ int save_kernel_event(struct config_writer *writer, } switch (event->event->instrumentation) { + case LTTNG_KERNEL_SYSCALL: case LTTNG_KERNEL_FUNCTION: ret = config_writer_open_element(writer, config_element_function_attributes); @@ -480,9 +499,60 @@ end: return ret; } +static +int save_kernel_syscall(struct config_writer *writer, + struct ltt_kernel_channel *kchan) +{ + int ret, i; + ssize_t count; + struct lttng_event *events = NULL; + + assert(writer); + assert(kchan); + + count = syscall_list_channel(kchan, &events, 0); + if (!count) { + /* No syscalls, just gracefully return. */ + ret = 0; + goto end; + } + + for (i = 0; i < count; i++) { + struct ltt_kernel_event *kevent; + + /* Create a temporary kevent in order to save it. */ + /* + * TODO: struct lttng_event does not really work for a filter, + * but unfortunately, it is exposed as external API (and used as + * internal representation. Using NULL meanwhile. + */ + kevent = trace_kernel_create_event(&events[i], + NULL, NULL); + if (!kevent) { + ret = -ENOMEM; + goto end; + } + /* Init list in order so the destroy call can del the node. */ + CDS_INIT_LIST_HEAD(&kevent->list); + + ret = save_kernel_event(writer, kevent); + trace_kernel_destroy_event(kevent); + if (ret) { + goto end; + } + } + + /* Everything went well */ + ret = 0; + +end: + free(events); + return ret; +} + static int save_kernel_events(struct config_writer *writer, - struct ltt_kernel_event_list *event_list) + struct ltt_kernel_channel *kchan) { int ret; struct ltt_kernel_event *event; @@ -493,13 +563,19 @@ int save_kernel_events(struct config_writer *writer, goto end; } - cds_list_for_each_entry(event, &event_list->head, list) { + cds_list_for_each_entry(event, &kchan->events_list.head, list) { ret = save_kernel_event(writer, event); if (ret) { goto end; } } + /* Save syscalls if any. */ + ret = save_kernel_syscall(writer, kchan); + if (ret) { + goto end; + } + /* /events */ ret = config_writer_close_element(writer); if (ret) { @@ -566,11 +642,14 @@ int save_ust_event(struct config_writer *writer, goto end; } - ret = config_writer_write_element_signed_int(writer, - config_element_loglevel, event->attr.loglevel); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; + /* The log level is irrelevant if no "filtering" is enabled */ + if (event->attr.loglevel_type != LTTNG_UST_LOGLEVEL_ALL) { + ret = config_writer_write_element_signed_int(writer, + config_element_loglevel, event->attr.loglevel); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } } if (event->filter_expression) { @@ -639,6 +718,10 @@ int save_ust_events(struct config_writer *writer, cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) { event = caa_container_of(node, struct ltt_ust_event, node); + if (event->internal) { + /* Internal events must not be exposed to clients */ + continue; + } ret = save_ust_event(writer, event); if (ret) { rcu_read_unlock(); @@ -667,19 +750,13 @@ int save_kernel_context(struct config_writer *writer, goto end; } - ret = config_writer_open_element(writer, config_element_contexts); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - ret = config_writer_open_element(writer, config_element_context); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_COUNTER) { + if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) { ret = config_writer_open_element(writer, config_element_perf); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -738,6 +815,35 @@ int save_kernel_context(struct config_writer *writer, goto end; } +end: + return ret; +} + +static +int save_kernel_contexts(struct config_writer *writer, + struct ltt_kernel_channel *kchan) +{ + int ret; + struct ltt_kernel_context *ctx; + + if (cds_list_empty(&kchan->ctx_list)) { + ret = 0; + goto end; + } + + ret = config_writer_open_element(writer, config_element_contexts); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + cds_list_for_each_entry(ctx, &kchan->ctx_list, list) { + ret = save_kernel_context(writer, &ctx->ctx); + if (ret) { + goto end; + } + } + /* /contexts */ ret = config_writer_close_element(writer); if (ret) { @@ -767,12 +873,6 @@ int save_ust_context(struct config_writer *writer, cds_list_for_each_entry(ctx, ctx_list, list) { const char *context_type_string; - context_type_string = get_ust_context_type_string(ctx->ctx.ctx); - if (!context_type_string) { - ERR("Unsupported UST context type.") - ret = LTTNG_ERR_INVALID; - goto end; - } ret = config_writer_open_element(writer, config_element_context); @@ -781,11 +881,61 @@ int save_ust_context(struct config_writer *writer, goto end; } - ret = config_writer_write_element_string(writer, - config_element_type, context_type_string); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; + if (ctx->ctx.ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) { + /* Perf contexts are saved as event_perf_context_type */ + ret = config_writer_open_element(writer, + config_element_perf); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = config_writer_write_element_unsigned_int(writer, + config_element_type, + ctx->ctx.u.perf_counter.type); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = config_writer_write_element_unsigned_int(writer, + config_element_config, + ctx->ctx.u.perf_counter.config); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = config_writer_write_element_string(writer, + config_element_name, + ctx->ctx.u.perf_counter.name); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + /* /perf */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + } else { + /* Save context as event_context_type_type */ + context_type_string = get_ust_context_type_string( + ctx->ctx.ctx); + if (!context_type_string) { + ERR("Unsupported UST context type.") + ret = LTTNG_ERR_INVALID; + goto end; + } + + ret = config_writer_write_element_string(writer, + config_element_type, context_type_string); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } } /* /context */ @@ -840,12 +990,12 @@ int save_kernel_channel(struct config_writer *writer, goto end; } - ret = save_kernel_events(writer, &kchan->events_list); + ret = save_kernel_events(writer, kchan); if (ret) { goto end; } - ret = save_kernel_context(writer, kchan->ctx); + ret = save_kernel_contexts(writer, kchan); if (ret) { goto end; } @@ -990,7 +1140,7 @@ end: static int save_ust_session(struct config_writer *writer, - struct ltt_session *session, int save_jul) + struct ltt_session *session, int save_agent) { int ret; struct ltt_ust_channel *ust_chan; @@ -1002,7 +1152,7 @@ int save_ust_session(struct config_writer *writer, assert(session); ret = config_writer_write_element_string(writer, config_element_type, - save_jul ? config_domain_type_jul : config_domain_type_ust); + save_agent ? config_domain_type_jul : config_domain_type_ust); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -1032,11 +1182,13 @@ int save_ust_session(struct config_writer *writer, rcu_read_lock(); cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, &iter.iter, node, node) { - int jul_channel; + int agent_channel; ust_chan = caa_container_of(node, struct ltt_ust_channel, node); - jul_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name); - if (!(save_jul ^ jul_channel)) { + agent_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name) || + !strcmp(DEFAULT_LOG4J_CHANNEL_NAME, ust_chan->name) || + !strcmp(DEFAULT_PYTHON_CHANNEL_NAME, ust_chan->name); + if (!(save_agent ^ agent_channel)) { ret = save_ust_channel(writer, ust_chan, session->ust_session); if (ret) { rcu_read_unlock(); @@ -1056,6 +1208,99 @@ end: return ret; } +static +int save_pid_tracker(struct config_writer *writer, + struct ltt_session *sess, int domain) +{ + int ret = 0; + ssize_t nr_pids = 0, i; + int32_t *pids = NULL; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + { + nr_pids = kernel_list_tracker_pids(sess->kernel_session, &pids); + if (nr_pids < 0) { + ret = LTTNG_ERR_KERN_LIST_FAIL; + goto end; + } + break; + } + case LTTNG_DOMAIN_UST: + { + nr_pids = trace_ust_list_tracker_pids(sess->ust_session, &pids); + if (nr_pids < 0) { + ret = LTTNG_ERR_UST_LIST_FAIL; + goto end; + } + break; + } + case LTTNG_DOMAIN_JUL: + case LTTNG_DOMAIN_LOG4J: + case LTTNG_DOMAIN_PYTHON: + default: + ret = LTTNG_ERR_UNKNOWN_DOMAIN; + goto end; + } + + /* Only create a pid_tracker if enabled or untrack all */ + if (nr_pids != 1 || (nr_pids == 1 && pids[0] != -1)) { + ret = config_writer_open_element(writer, + config_element_pid_tracker); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = config_writer_open_element(writer, + config_element_targets); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + for (i = 0; i < nr_pids; i++) { + ret = config_writer_open_element(writer, + config_element_target_pid); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = config_writer_write_element_unsigned_int(writer, + config_element_pid, pids[i]); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + /* /pid_target */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + } + + /* /targets */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + /* /pid_tracker */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + } +end: + free(pids); + return ret; +} + static int save_domains(struct config_writer *writer, struct ltt_session *session) { @@ -1088,6 +1333,24 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) goto end; } + ret = config_writer_open_element(writer, + config_element_trackers); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL); + if (ret) { + goto end; + } + + /* /trackers */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } /* /domain */ ret = config_writer_close_element(writer); if (ret) { @@ -1097,6 +1360,8 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) } if (session->ust_session) { + unsigned long agent_count; + ret = config_writer_open_element(writer, config_element_domain); if (ret) { @@ -1109,34 +1374,52 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) goto end; } - /* /domain */ - ret = config_writer_close_element(writer); + ret = config_writer_open_element(writer, + config_element_trackers); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - } - if (session->ust_session && - session->ust_session->domain_jul.being_used) { - ret = config_writer_open_element(writer, - config_element_domain); + ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST); if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_ust_session(writer, session, 1); + /* /trackers */ + ret = config_writer_close_element(writer); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - /* /domain */ ret = config_writer_close_element(writer); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + agent_count = lttng_ht_get_count(session->ust_session->agents); + if (agent_count > 0) { + ret = config_writer_open_element(writer, + config_element_domain); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = save_ust_session(writer, session, 1); + if (ret) { + goto end; + } + + /* /domain */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + } } /* /domains */ @@ -1239,6 +1522,7 @@ end_net_output: ret = !output->dst.net.control_isset ? LTTNG_ERR_URL_CTRL_MISS : LTTNG_ERR_URL_DATA_MISS; + free(uri); goto end; } @@ -1397,6 +1681,7 @@ int save_session(struct ltt_session *session, struct lttng_save_session_attr *attr, lttng_sock_cred *creds) { int ret, fd; + unsigned int file_opened = 0; /* Indicate if the file has been opened */ char config_file_path[PATH_MAX]; size_t len; struct config_writer *writer = NULL; @@ -1408,6 +1693,7 @@ int save_session(struct ltt_session *session, assert(creds); session_name_len = strlen(session->name); + memset(config_file_path, 0, sizeof(config_file_path)); if (!session_access_ok(session, LTTNG_SOCK_GET_UID_CRED(creds), @@ -1418,13 +1704,15 @@ int save_session(struct ltt_session *session, provided_path = lttng_save_session_attr_get_output_url(attr); if (provided_path) { + DBG3("Save session in provided path %s", provided_path); len = strlen(provided_path); - if (len > PATH_MAX) { + if (len >= sizeof(config_file_path)) { ret = LTTNG_ERR_SET_URL; goto end; } strncpy(config_file_path, provided_path, len); } else { + ssize_t ret_len; char *home_dir = utils_get_user_home_dir( LTTNG_SOCK_GET_UID_CRED(creds)); if (!home_dir) { @@ -1432,22 +1720,24 @@ int save_session(struct ltt_session *session, goto end; } - len = snprintf(config_file_path, PATH_MAX, + ret_len = snprintf(config_file_path, sizeof(config_file_path), DEFAULT_SESSION_HOME_CONFIGPATH, home_dir); free(home_dir); - if (len < 0) { + if (ret_len < 0) { PERROR("snprintf save session"); ret = LTTNG_ERR_SET_URL; goto end; } + len = ret_len; } /* - * Check the path fits in PATH_MAX, including the / followed by trailing - * .lttng extension and the NULL terminated string. + * Check the path fits in the config file path dst including the '/' + * followed by trailing .lttng extension and the NULL terminated string. */ - if (len + session_name_len + 2 + - sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION) > PATH_MAX) { + if ((len + session_name_len + 2 + + sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION)) + > sizeof(config_file_path)) { ret = LTTNG_ERR_SET_URL; goto end; } @@ -1459,13 +1749,20 @@ int save_session(struct ltt_session *session, goto end; } + /* + * At this point, we know that everything fits in the buffer. Validation + * was done just above. + */ config_file_path[len++] = '/'; strncpy(config_file_path + len, session->name, session_name_len); len += session_name_len; strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION); + len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION); + config_file_path[len] = '\0'; if (!access(config_file_path, F_OK) && !attr->overwrite) { - /* A file with the same name already exists, skip */ + /* File exists, notify the user since the overwrite flag is off. */ + ret = LTTNG_ERR_SAVE_FILE_EXIST; goto end; } @@ -1477,8 +1774,9 @@ int save_session(struct ltt_session *session, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + file_opened = 1; - writer = config_writer_create(fd); + writer = config_writer_create(fd, 1); if (!writer) { ret = LTTNG_ERR_NOMEM; goto end; @@ -1503,13 +1801,23 @@ int save_session(struct ltt_session *session, goto end; } + if(session->shm_path[0] != '\0') { + ret = config_writer_write_element_string(writer, + config_element_shared_memory_path, + session->shm_path); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + } + ret = save_domains(writer, session); if (ret) { goto end; } ret = config_writer_write_element_bool(writer, config_element_started, - session->enabled); + session->active); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -1530,7 +1838,7 @@ int save_session(struct ltt_session *session, goto end; } } else { - ret = config_writer_write_element_signed_int(writer, + ret = config_writer_write_element_unsigned_int(writer, config_element_live_timer_interval, session->live_timer); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -1571,7 +1879,7 @@ end: } if (ret) { /* Delete file in case of error */ - if (unlink(config_file_path)) { + if (file_opened && unlink(config_file_path)) { PERROR("Unlinking XML session configuration."); } }