X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fsave.c;h=1a98515fa0c73f0272c82b346aa102ff5f5117f8;hp=812137f93f40b1257f6b2973a993f35af6e763cf;hb=9897fbc95aea23f996b7543d86363a3dd72a0c53;hpb=54a9842323bdcf75da5f0e31a433191af7f687fd diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index 812137f93..1a98515fa 100644 --- a/src/bin/lttng-sessiond/save.c +++ b/src/bin/lttng-sessiond/save.c @@ -15,7 +15,7 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE +#define _LGPL_SOURCE #include #include #include @@ -24,14 +24,17 @@ #include #include -#include +#include #include #include #include +#include "kernel.h" #include "save.h" #include "session.h" +#include "syscall.h" #include "trace-ust.h" +#include "agent.h" static int save_kernel_channel_attributes(struct config_writer *writer, @@ -258,8 +261,17 @@ 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_APP_CONTEXT: + context_type_string = config_event_context_app; + 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; @@ -354,6 +366,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) { @@ -366,6 +388,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); @@ -481,7 +504,7 @@ end: 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; @@ -492,7 +515,7 @@ 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; @@ -565,11 +588,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) { @@ -594,7 +620,8 @@ int save_ust_event(struct config_writer *writer, for (i = 0; i < event->exclusion->count; i++) { ret = config_writer_write_element_string(writer, config_element_exclusion, - &event->exclusion->names[0][i]); + LTTNG_EVENT_EXCLUSION_NAME_AT( + event->exclusion, i)); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -638,6 +665,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(); @@ -657,20 +688,101 @@ end: } static -int save_kernel_context(struct config_writer *writer, - struct lttng_kernel_context *ctx) +int init_ust_event_from_agent_event(struct ltt_ust_event *ust_event, + struct agent_event *agent_event) { int ret = 0; + enum lttng_ust_loglevel_type ust_loglevel_type; + + ust_event->enabled = agent_event->enabled; + ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT; + strncpy(ust_event->attr.name, agent_event->name, LTTNG_SYMBOL_NAME_LEN); + switch (agent_event->loglevel_type) { + case LTTNG_EVENT_LOGLEVEL_ALL: + ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL; + break; + case LTTNG_EVENT_LOGLEVEL_SINGLE: + ust_loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE; + break; + case LTTNG_EVENT_LOGLEVEL_RANGE: + ust_loglevel_type = LTTNG_UST_LOGLEVEL_RANGE; + break; + default: + ERR("Invalid agent_event loglevel_type."); + ret = -1; + goto end; + } - if (!ctx) { + ust_event->attr.loglevel_type = ust_loglevel_type; + ust_event->attr.loglevel = agent_event->loglevel_value; + ust_event->filter_expression = agent_event->filter_expression; + ust_event->exclusion = agent_event->exclusion; +end: + return ret; +} + +static +int save_agent_events(struct config_writer *writer, + struct ltt_ust_channel *chan, + struct agent *agent) +{ + int ret; + struct lttng_ht_iter iter; + struct lttng_ht_node_str *node; + + ret = config_writer_open_element(writer, config_element_events); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_open_element(writer, config_element_contexts); + rcu_read_lock(); + cds_lfht_for_each_entry(agent->events->ht, &iter.iter, node, node) { + int ret; + struct agent_event *agent_event; + struct ltt_ust_event fake_event; + + memset(&fake_event, 0, sizeof(fake_event)); + agent_event = caa_container_of(node, struct agent_event, node); + + /* + * Initialize a fake ust event to reuse the same serialization + * function since UST and agent events contain the same info + * (and one could wonder why they don't reuse the same + * structures...). + */ + ret = init_ust_event_from_agent_event(&fake_event, agent_event); + if (ret) { + rcu_read_unlock(); + goto end; + } + ret = save_ust_event(writer, &fake_event); + if (ret) { + rcu_read_unlock(); + goto end; + } + } + rcu_read_unlock(); + + /* /events */ + ret = config_writer_close_element(writer); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } +end: + return ret; +} + +static +int save_kernel_context(struct config_writer *writer, + struct lttng_kernel_context *ctx) +{ + int ret = 0; + + if (!ctx) { + goto end; + } ret = config_writer_open_element(writer, config_element_context); if (ret) { @@ -678,8 +790,9 @@ int save_kernel_context(struct config_writer *writer, goto end; } - if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_COUNTER) { - ret = config_writer_open_element(writer, config_element_perf); + if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) { + ret = config_writer_open_element(writer, + config_element_context_perf); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -737,6 +850,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) { @@ -747,6 +889,124 @@ end: return ret; } +static +int save_ust_context_perf_thread_counter(struct config_writer *writer, + struct ltt_ust_context *ctx) +{ + int ret; + + assert(writer); + assert(ctx); + + /* Perf contexts are saved as event_perf_context_type */ + ret = config_writer_open_element(writer, config_element_context_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; + } +end: + return ret; +} + +static +int save_ust_context_app_ctx(struct config_writer *writer, + struct ltt_ust_context *ctx) +{ + int ret; + + assert(writer); + assert(ctx); + + /* Application contexts are saved as application_context_type */ + ret = config_writer_open_element(writer, config_element_context_app); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = config_writer_write_element_string(writer, + config_element_context_app_provider_name, + ctx->ctx.u.app_ctx.provider_name); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = config_writer_write_element_string(writer, + config_element_context_app_ctx_name, + ctx->ctx.u.app_ctx.ctx_name); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + /* /app */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } +end: + return ret; +} + +static +int save_ust_context_generic(struct config_writer *writer, + struct ltt_ust_context *ctx) +{ + int ret; + const char *context_type_string; + + assert(writer); + assert(ctx); + + /* 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_SAVE_IO_FAIL; + 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; + } +end: + return ret; +} + static int save_ust_context(struct config_writer *writer, struct cds_list_head *ctx_list) @@ -764,15 +1024,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); if (ret) { @@ -780,10 +1031,18 @@ int save_ust_context(struct config_writer *writer, goto end; } - ret = config_writer_write_element_string(writer, - config_element_type, context_type_string); + switch (ctx->ctx.ctx) { + case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER: + ret = save_ust_context_perf_thread_counter(writer, ctx); + break; + case LTTNG_UST_CONTEXT_APP_CONTEXT: + ret = save_ust_context_app_ctx(writer, ctx); + break; + default: + /* Save generic context. */ + ret = save_ust_context_generic(writer, ctx); + } if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -839,12 +1098,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; } @@ -917,10 +1176,31 @@ int save_ust_channel(struct config_writer *writer, goto end; } - ret = save_ust_events(writer, ust_chan->events); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; + if (ust_chan->domain == LTTNG_DOMAIN_UST) { + ret = save_ust_events(writer, ust_chan->events); + if (ret) { + goto end; + } + } else { + struct agent *agent = NULL; + + agent = trace_ust_find_agent(session, ust_chan->domain); + if (!agent) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + ERR("Could not find agent associated to UST subdomain"); + goto end; + } + + /* + * Channels associated with a UST sub-domain (such as JUL, Log4j + * or Python) don't have any non-internal events. We retrieve + * the "agent" events associated with this channel and serialize + * them. + */ + ret = save_agent_events(writer, ust_chan, agent); + if (ret) { + goto end; + } } ret = save_ust_context(writer, &ust_chan->ctx_list); @@ -988,20 +1268,155 @@ end: } static -int save_ust_session(struct config_writer *writer, - struct ltt_session *session, int save_jul) +const char *get_config_domain_str(enum lttng_domain_type domain) +{ + const char *str_dom; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + str_dom = config_domain_type_kernel; + break; + case LTTNG_DOMAIN_UST: + str_dom = config_domain_type_ust; + break; + case LTTNG_DOMAIN_JUL: + str_dom = config_domain_type_jul; + break; + case LTTNG_DOMAIN_LOG4J: + str_dom = config_domain_type_log4j; + break; + case LTTNG_DOMAIN_PYTHON: + str_dom = config_domain_type_python; + break; + default: + assert(0); + } + + return str_dom; +} + +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_ust_domain(struct config_writer *writer, + struct ltt_session *session, enum lttng_domain_type domain) { int ret; struct ltt_ust_channel *ust_chan; const char *buffer_type_string; struct lttng_ht_node_str *node; struct lttng_ht_iter iter; + const char *config_domain_name; assert(writer); assert(session); - ret = config_writer_write_element_string(writer, config_element_type, - save_jul ? config_domain_type_jul : config_domain_type_ust); + ret = config_writer_open_element(writer, + config_element_domain); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + config_domain_name = get_config_domain_str(domain); + if (!config_domain_name) { + ret = LTTNG_ERR_INVALID; + goto end; + } + + ret = config_writer_write_element_string(writer, + config_element_type, config_domain_name); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -1031,11 +1446,8 @@ 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; - 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)) { + if (domain == ust_chan->domain) { ret = save_ust_channel(writer, ust_chan, session->ust_session); if (ret) { rcu_read_unlock(); @@ -1051,6 +1463,34 @@ int save_ust_session(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + if (domain == LTTNG_DOMAIN_UST) { + 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_UST); + if (ret) { + goto end; + } + + /* /trackers */ + ret = config_writer_close_element(writer); + if (ret) { + goto end; + } + } + + /* /domain */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + end: return ret; } @@ -1087,27 +1527,24 @@ 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) { - ret = config_writer_open_element(writer, - config_element_domain); + ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL); if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_ust_session(writer, session, 0); + /* /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) { @@ -1116,24 +1553,24 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) } } - if (session->ust_session && - session->ust_session->domain_jul.being_used) { - ret = config_writer_open_element(writer, - config_element_domain); + if (session->ust_session) { + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST); if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_ust_session(writer, session, 1); + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL); if (ret) { goto end; } - /* /domain */ - ret = config_writer_close_element(writer); + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J); + if (ret) { + goto end; + } + + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON); if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } } @@ -1492,7 +1929,7 @@ int save_session(struct ltt_session *session, } file_opened = 1; - writer = config_writer_create(fd); + writer = config_writer_create(fd, 1); if (!writer) { ret = LTTNG_ERR_NOMEM; goto end; @@ -1517,13 +1954,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; @@ -1544,7 +1991,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;