X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fsave.c;h=1a98515fa0c73f0272c82b346aa102ff5f5117f8;hp=851b9ac5b2f27171dd5bc06fb0ec8b7ad4f02e44;hb=9897fbc95aea23f996b7543d86363a3dd72a0c53;hpb=22c34f481f5a4491981e86a57f884852fc324a21 diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index 851b9ac5b..1a98515fa 100644 --- a/src/bin/lttng-sessiond/save.c +++ b/src/bin/lttng-sessiond/save.c @@ -15,7 +15,6 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE #define _LGPL_SOURCE #include #include @@ -25,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -35,6 +34,7 @@ #include "session.h" #include "syscall.h" #include "trace-ust.h" +#include "agent.h" static int save_kernel_channel_attributes(struct config_writer *writer, @@ -261,6 +261,9 @@ 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 @@ -363,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) { @@ -489,57 +502,6 @@ 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_channel *kchan) @@ -560,12 +522,6 @@ int save_kernel_events(struct config_writer *writer, } } - /* Save syscalls if any. */ - ret = save_kernel_syscall(writer, kchan); - if (ret) { - goto end; - } - /* /events */ ret = config_writer_close_element(writer); if (ret) { @@ -632,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) { @@ -661,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; @@ -727,6 +687,93 @@ end: return ret; } +static +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; + } + + 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; + } + + 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) @@ -744,7 +791,8 @@ int save_kernel_context(struct config_writer *writer, } if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) { - ret = config_writer_open_element(writer, config_element_perf); + ret = config_writer_open_element(writer, + config_element_context_perf); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; @@ -841,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) @@ -858,9 +1024,6 @@ int save_ust_context(struct config_writer *writer, } cds_list_for_each_entry(ctx, ctx_list, list) { - const char *context_type_string; - - ret = config_writer_open_element(writer, config_element_context); if (ret) { @@ -868,61 +1031,19 @@ int save_ust_context(struct config_writer *writer, 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; - } + 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) { + goto end; } /* /context */ @@ -1055,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); @@ -1126,73 +1268,31 @@ end: } static -int save_ust_session(struct config_writer *writer, - struct ltt_session *session, int save_agent) +const char *get_config_domain_str(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; - - assert(writer); - assert(session); - - ret = config_writer_write_element_string(writer, config_element_type, - save_agent ? config_domain_type_jul : config_domain_type_ust); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - - buffer_type_string = get_buffer_type_string( - session->ust_session->buffer_type); - if (!buffer_type_string) { - ERR("Unsupported buffer type."); - ret = LTTNG_ERR_INVALID; - goto end; - } - - ret = config_writer_write_element_string(writer, - config_element_buffer_type, buffer_type_string); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - - ret = config_writer_open_element(writer, config_element_channels); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - - rcu_read_lock(); - cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, - &iter.iter, node, node) { - int agent_channel; + const char *str_dom; - ust_chan = caa_container_of(node, struct ltt_ust_channel, node); - 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(); - goto end; - } - } + 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); } - rcu_read_unlock(); - /* /channels */ - ret = config_writer_close_element(writer); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } -end: - return ret; + return str_dom; } static @@ -1289,45 +1389,90 @@ end: } static -int save_domains(struct config_writer *writer, struct ltt_session *session) +int save_ust_domain(struct config_writer *writer, + struct ltt_session *session, enum lttng_domain_type domain) { - int ret = 0; + 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); - if (!session->kernel_session && !session->ust_session) { + ret = config_writer_open_element(writer, + config_element_domain); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_open_element(writer, config_element_domains); + 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; + } + + buffer_type_string = get_buffer_type_string( + session->ust_session->buffer_type); + if (!buffer_type_string) { + ERR("Unsupported buffer type."); + ret = LTTNG_ERR_INVALID; + goto end; + } + + ret = config_writer_write_element_string(writer, + config_element_buffer_type, buffer_type_string); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + ret = config_writer_open_element(writer, config_element_channels); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } - if (session->kernel_session) { - ret = config_writer_open_element(writer, - config_element_domain); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; + rcu_read_lock(); + cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, + &iter.iter, node, node) { + ust_chan = caa_container_of(node, struct ltt_ust_channel, node); + if (domain == ust_chan->domain) { + ret = save_ust_channel(writer, ust_chan, session->ust_session); + if (ret) { + rcu_read_unlock(); + goto end; + } } + } + rcu_read_unlock(); - ret = save_kernel_session(writer, session); - if (ret) { - goto end; - } + /* /channels */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + if (domain == LTTNG_DOMAIN_UST) { ret = config_writer_open_element(writer, - config_element_trackers); + config_element_trackers); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL); + ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST); if (ret) { goto end; } @@ -1335,20 +1480,41 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) /* /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; } } - if (session->ust_session) { - unsigned long agent_count; + /* /domain */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + +end: + return ret; +} + +static +int save_domains(struct config_writer *writer, struct ltt_session *session) +{ + int ret = 0; + + assert(writer); + assert(session); + if (!session->kernel_session && !session->ust_session) { + goto end; + } + + ret = config_writer_open_element(writer, config_element_domains); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + + if (session->kernel_session) { ret = config_writer_open_element(writer, config_element_domain); if (ret) { @@ -1356,7 +1522,7 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) goto end; } - ret = save_ust_session(writer, session, 0); + ret = save_kernel_session(writer, session); if (ret) { goto end; } @@ -1368,7 +1534,7 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) goto end; } - ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST); + ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL); if (ret) { goto end; } @@ -1385,27 +1551,27 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) 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; - } + if (session->ust_session) { + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST); + if (ret) { + goto end; + } - ret = save_ust_session(writer, session, 1); - if (ret) { - goto end; - } + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL); + if (ret) { + goto end; + } - /* /domain */ - ret = config_writer_close_element(writer); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J); + if (ret) { + goto end; + } + + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON); + if (ret) { + goto end; } }