X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fsave.c;h=b09aeccc67a8438617d47d2407bbad7ba5c6c9df;hb=c92af2a5fd6587a03f1a0e927fd734751032b3a1;hp=18d303cac9184cbd82ba0671c4b92e75b8eb91e0;hpb=cba45edad79e4812a8dcac583778e25509c5e13b;p=deliverable%2Flttng-tools.git diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index 18d303cac..b09aeccc6 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,15 +24,19 @@ #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" +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_kernel_channel_attributes(struct config_writer *writer, struct lttng_channel_attr *attr) @@ -44,12 +48,14 @@ int save_kernel_channel_attributes(struct config_writer *writer, attr->overwrite ? config_overwrite_mode_overwrite : config_overwrite_mode_discard); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } ret = config_writer_write_element_unsigned_int(writer, config_element_subbuf_size, attr->subbuf_size); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -57,6 +63,7 @@ int save_kernel_channel_attributes(struct config_writer *writer, config_element_num_subbuf, attr->num_subbuf); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -64,6 +71,7 @@ int save_kernel_channel_attributes(struct config_writer *writer, config_element_switch_timer_interval, attr->switch_timer_interval); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -71,6 +79,7 @@ int save_kernel_channel_attributes(struct config_writer *writer, config_element_read_timer_interval, attr->read_timer_interval); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -79,12 +88,14 @@ int save_kernel_channel_attributes(struct config_writer *writer, attr->output == LTTNG_EVENT_SPLICE ? config_output_type_splice : config_output_type_mmap); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } ret = config_writer_write_element_unsigned_int(writer, config_element_tracefile_size, attr->tracefile_size); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -92,6 +103,7 @@ int save_kernel_channel_attributes(struct config_writer *writer, config_element_tracefile_count, attr->tracefile_count); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -99,12 +111,14 @@ int save_kernel_channel_attributes(struct config_writer *writer, config_element_live_timer_interval, attr->live_timer_interval); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } end: - return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0; + return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_ust_channel_attributes(struct config_writer *writer, struct lttng_ust_channel_attr *attr) @@ -116,12 +130,14 @@ int save_ust_channel_attributes(struct config_writer *writer, attr->overwrite ? config_overwrite_mode_overwrite : config_overwrite_mode_discard); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } ret = config_writer_write_element_unsigned_int(writer, config_element_subbuf_size, attr->subbuf_size); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -129,6 +145,7 @@ int save_ust_channel_attributes(struct config_writer *writer, config_element_num_subbuf, attr->num_subbuf); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -136,6 +153,7 @@ int save_ust_channel_attributes(struct config_writer *writer, config_element_switch_timer_interval, attr->switch_timer_interval); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -143,6 +161,7 @@ int save_ust_channel_attributes(struct config_writer *writer, config_element_read_timer_interval, attr->read_timer_interval); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -151,10 +170,13 @@ int save_ust_channel_attributes(struct config_writer *writer, attr->output == LTTNG_UST_MMAP ? config_output_type_mmap : config_output_type_splice); if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: - return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0; + return ret; } static @@ -229,6 +251,18 @@ const char *get_kernel_context_type_string( case LTTNG_KERNEL_CONTEXT_HOSTNAME: context_type_string = config_event_context_hostname; break; + case LTTNG_KERNEL_CONTEXT_INTERRUPTIBLE: + context_type_string = config_event_context_interruptible; + break; + case LTTNG_KERNEL_CONTEXT_PREEMPTIBLE: + context_type_string = config_event_context_preemptible; + break; + case LTTNG_KERNEL_CONTEXT_NEED_RESCHEDULE: + context_type_string = config_event_context_need_reschedule; + break; + case LTTNG_KERNEL_CONTEXT_MIGRATABLE: + context_type_string = config_event_context_migratable; + break; default: context_type_string = NULL; } @@ -258,8 +292,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; @@ -311,6 +354,7 @@ const char *get_loglevel_type_string( return loglevel_type_string; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_kernel_event(struct config_writer *writer, struct ltt_kernel_event *event) @@ -354,6 +398,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 +420,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); @@ -475,13 +530,16 @@ int save_kernel_event(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ 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,9 +550,9 @@ 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) { + if (ret != LTTNG_OK) { goto end; } } @@ -505,10 +563,13 @@ int save_kernel_events(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_ust_event(struct config_writer *writer, struct ltt_ust_event *event) @@ -565,11 +626,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 +658,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; @@ -615,10 +680,13 @@ int save_ust_event(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_ust_events(struct config_writer *writer, struct lttng_ht *events) @@ -638,8 +706,12 @@ 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) { + if (ret != LTTNG_OK) { rcu_read_unlock(); goto end; } @@ -652,26 +724,120 @@ int save_ust_events(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ 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; + int ret; + enum lttng_ust_loglevel_type ust_loglevel_type; - if (!ctx) { + ust_event->enabled = agent_event->enabled; + ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT; + if (lttng_strncpy(ust_event->attr.name, agent_event->name, + LTTNG_SYMBOL_NAME_LEN)) { + ret = LTTNG_ERR_INVALID; + goto end; + } + 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 = LTTNG_ERR_INVALID; goto end; } - ret = config_writer_open_element(writer, config_element_contexts); + 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; + + ret = LTTNG_OK; +end: + return ret; +} + +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ +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 != LTTNG_OK) { + rcu_read_unlock(); + goto end; + } + ret = save_ust_event(writer, &fake_event); + if (ret != LTTNG_OK) { + 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; } + ret = LTTNG_OK; +end: + return ret; +} + +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ +static +int save_kernel_context(struct config_writer *writer, + struct lttng_kernel_context *ctx) +{ + int ret = LTTNG_OK; + + if (!ctx) { + goto end; + } + ret = config_writer_open_element(writer, config_element_context); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -679,7 +845,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; @@ -737,16 +904,177 @@ int save_kernel_context(struct config_writer *writer, goto end; } + ret = LTTNG_OK; +end: + return ret; +} + +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ +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 = LTTNG_OK; + 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 != LTTNG_OK) { + goto end; + } + } + /* /contexts */ ret = config_writer_close_element(writer); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ +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; + } + + ret = LTTNG_OK; +end: + return ret; +} + +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ +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; + } + + ret = LTTNG_OK; +end: + return ret; +} + +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ +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; + } + + ret = LTTNG_OK; +end: + return ret; +} + +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_ust_context(struct config_writer *writer, struct cds_list_head *ctx_list) @@ -764,15 +1092,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 +1099,18 @@ 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; + 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 != LTTNG_OK) { goto end; } @@ -801,10 +1128,13 @@ int save_ust_context(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_kernel_channel(struct config_writer *writer, struct ltt_kernel_channel *kchan) @@ -835,17 +1165,17 @@ int save_kernel_channel(struct config_writer *writer, } ret = save_kernel_channel_attributes(writer, &kchan->channel->attr); - if (ret) { + if (ret != LTTNG_OK) { goto end; } - ret = save_kernel_events(writer, &kchan->events_list); - if (ret) { + ret = save_kernel_events(writer, kchan); + if (ret != LTTNG_OK) { goto end; } - ret = save_kernel_context(writer, kchan->ctx); - if (ret) { + ret = save_kernel_contexts(writer, kchan); + if (ret != LTTNG_OK) { goto end; } @@ -855,10 +1185,13 @@ int save_kernel_channel(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_ust_channel(struct config_writer *writer, struct ltt_ust_channel *ust_chan, @@ -891,7 +1224,7 @@ int save_ust_channel(struct config_writer *writer, } ret = save_ust_channel_attributes(writer, &ust_chan->attr); - if (ret) { + if (ret != LTTNG_OK) { goto end; } @@ -917,14 +1250,35 @@ 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 != LTTNG_OK) { + 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 != LTTNG_OK) { + goto end; + } } ret = save_ust_context(writer, &ust_chan->ctx_list); - if (ret) { + if (ret != LTTNG_OK) { goto end; } @@ -934,10 +1288,13 @@ int save_ust_channel(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_kernel_session(struct config_writer *writer, struct ltt_session *session) @@ -972,7 +1329,7 @@ int save_kernel_session(struct config_writer *writer, cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head, list) { ret = save_kernel_channel(writer, kchan); - if (ret) { + if (ret != LTTNG_OK) { goto end; } } @@ -983,25 +1340,287 @@ int save_kernel_session(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; +end: + return ret; +} + +static +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; +} + +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ +static +int save_id_tracker(struct config_writer *writer, + struct ltt_session *sess, int domain, + enum lttng_tracker_type tracker_type) +{ + int ret = LTTNG_OK; + ssize_t nr_ids = 0, i; + struct lttng_tracker_id *ids = NULL; + const char *element_id_tracker, *element_target_id, *element_id; + + switch (tracker_type) { + case LTTNG_TRACKER_PID: + element_id_tracker = config_element_pid_tracker; + element_target_id = config_element_target_pid; + element_id = config_element_pid; + break; + case LTTNG_TRACKER_VPID: + element_id_tracker = config_element_vpid_tracker; + element_target_id = config_element_target_vpid; + element_id = config_element_id; + break; + case LTTNG_TRACKER_UID: + element_id_tracker = config_element_uid_tracker; + element_target_id = config_element_target_uid; + element_id = config_element_id; + break; + case LTTNG_TRACKER_VUID: + element_id_tracker = config_element_vuid_tracker; + element_target_id = config_element_target_vuid; + element_id = config_element_id; + break; + case LTTNG_TRACKER_GID: + element_id_tracker = config_element_gid_tracker; + element_target_id = config_element_target_gid; + element_id = config_element_id; + break; + case LTTNG_TRACKER_VGID: + element_id_tracker = config_element_vgid_tracker; + element_target_id = config_element_target_vgid; + element_id = config_element_id; + break; + default: + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + { + nr_ids = kernel_list_tracker_ids(tracker_type, sess->kernel_session, &ids); + if (nr_ids < 0) { + ret = LTTNG_ERR_KERN_LIST_FAIL; + goto end; + } + break; + } + case LTTNG_DOMAIN_UST: + { + nr_ids = trace_ust_list_tracker_ids(tracker_type, sess->ust_session, &ids); + if (nr_ids < 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; + } + + + if (nr_ids == 1 && ids[0].type == LTTNG_ID_ALL) { + /* Tracking all, nothing to output. */ + ret = LTTNG_OK; + goto end; + } + + ret = config_writer_open_element(writer, element_id_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; + } + + if (nr_ids == 0) { + /* Tracking none: empty list. */ + ret = config_writer_open_element(writer, + element_target_id); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + /* /$element_target_id */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + } else { + /* Tracking list. */ + for (i = 0; i < nr_ids; i++) { + switch (ids[i].type) { + case LTTNG_ID_VALUE: + ret = config_writer_open_element(writer, + element_target_id); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + ret = config_writer_write_element_unsigned_int(writer, + element_id, ids[i].value); + break; + case LTTNG_ID_STRING: + ret = config_writer_open_element(writer, + element_target_id); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + ret = config_writer_write_element_string(writer, + config_element_name, ids[i].string); + break; + default: + /* Unexpected. */ + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + /* /$element_target_id */ + 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; + } + + /* /$element_id_tracker */ + ret = config_writer_close_element(writer); + if (ret) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = LTTNG_OK; end: + free(ids); return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static -int save_ust_session(struct config_writer *writer, - struct ltt_session *session, int save_jul) +int save_id_trackers(struct config_writer *writer, + struct ltt_session *sess, int domain) +{ + int ret; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_PID); + if (ret != LTTNG_OK) + return ret; + ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VPID); + if (ret != LTTNG_OK) + return ret; + ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_UID); + if (ret != LTTNG_OK) + return ret; + ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VUID); + if (ret != LTTNG_OK) + return ret; + ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_GID); + if (ret != LTTNG_OK) + return ret; + ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VGID); + if (ret != LTTNG_OK) + return ret; + break; + case LTTNG_DOMAIN_UST: + ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VPID); + if (ret != LTTNG_OK) + return ret; + ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VUID); + if (ret != LTTNG_OK) + return ret; + ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VGID); + if (ret != LTTNG_OK) + return ret; + break; + default: + return LTTNG_ERR_INVALID; + } + return LTTNG_OK; +} + +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ +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,13 +1650,10 @@ 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) { + if (ret != LTTNG_OK) { rcu_read_unlock(); goto end; } @@ -1051,14 +1667,45 @@ 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_id_trackers(writer, session, LTTNG_DOMAIN_UST); + if (ret != LTTNG_OK) { + 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) { + ret = LTTNG_ERR_SAVE_IO_FAIL; + goto end; + } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_domains(struct config_writer *writer, struct ltt_session *session) { - int ret = 0; + int ret = LTTNG_OK; assert(writer); assert(session); @@ -1073,7 +1720,6 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) goto end; } - if (session->kernel_session) { ret = config_writer_open_element(writer, config_element_domain); @@ -1083,31 +1729,28 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) } ret = save_kernel_session(writer, session); - if (ret) { + if (ret != LTTNG_OK) { 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); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; + ret = save_id_trackers(writer, session, LTTNG_DOMAIN_KERNEL); + if (ret != LTTNG_OK) { 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 +1759,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 (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; + if (session->ust_session) { + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST); + if (ret != LTTNG_OK) { goto end; } - ret = save_ust_session(writer, session, 1); - if (ret) { + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL); + if (ret != LTTNG_OK) { goto end; } - /* /domain */ - ret = config_writer_close_element(writer); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J); + if (ret != LTTNG_OK) { + goto end; + } + + ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON); + if (ret != LTTNG_OK) { goto end; } } @@ -1144,10 +1787,13 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_consumer_output(struct config_writer *writer, struct consumer_output *output) @@ -1228,10 +1874,10 @@ int save_consumer_output(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end_net_output; } - + ret = LTTNG_OK; end_net_output: free(uri); - if (ret) { + if (ret != LTTNG_OK) { goto end; } } else { @@ -1268,10 +1914,13 @@ end_net_output: ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_snapshot_outputs(struct config_writer *writer, struct snapshot *snapshot) @@ -1314,7 +1963,7 @@ int save_snapshot_outputs(struct config_writer *writer, } ret = save_consumer_output(writer, output->consumer); - if (ret) { + if (ret != LTTNG_OK) { goto end_unlock; } @@ -1334,6 +1983,7 @@ int save_snapshot_outputs(struct config_writer *writer, goto end; } + ret = LTTNG_OK; end: return ret; end_unlock: @@ -1341,6 +1991,7 @@ end_unlock: return ret; } +/* Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_session_output(struct config_writer *writer, struct ltt_session *session) @@ -1353,7 +2004,7 @@ int save_session_output(struct config_writer *writer, if ((session->snapshot_mode && session->snapshot.nb_output == 0) || (!session->snapshot_mode && !session->consumer)) { /* Session is in no output mode */ - ret = 0; + ret = LTTNG_OK; goto end; } @@ -1365,13 +2016,13 @@ int save_session_output(struct config_writer *writer, if (session->snapshot_mode) { ret = save_snapshot_outputs(writer, &session->snapshot); - if (ret) { + if (ret != LTTNG_OK) { goto end; } } else { if (session->consumer) { ret = save_consumer_output(writer, session->consumer); - if (ret) { + if (ret != LTTNG_OK) { goto end; } } @@ -1383,6 +2034,7 @@ int save_session_output(struct config_writer *writer, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + ret = LTTNG_OK; end: return ret; } @@ -1390,7 +2042,7 @@ end: /* * Save the given session. * - * Return 0 on success else a LTTNG_ERR* code. + * Return LTTNG_OK on success else a LTTNG_ERR* code. */ static int save_session(struct ltt_session *session, @@ -1492,7 +2144,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,8 +2169,18 @@ 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) { + if (ret != LTTNG_OK) { goto end; } @@ -1544,7 +2206,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; @@ -1561,7 +2223,7 @@ int save_session(struct ltt_session *session, } ret = save_session_output(writer, session); - if (ret) { + if (ret != LTTNG_OK) { goto end; } @@ -1578,18 +2240,29 @@ int save_session(struct ltt_session *session, ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } + + ret = LTTNG_OK; end: if (writer && config_writer_destroy(writer)) { /* Preserve the original error code */ - ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL; + ret = ret != LTTNG_OK ? ret : LTTNG_ERR_SAVE_IO_FAIL; } - if (ret) { + if (ret != LTTNG_OK) { /* Delete file in case of error */ if (file_opened && unlink(config_file_path)) { PERROR("Unlinking XML session configuration."); } } + if (file_opened) { + int closeret; + + closeret = close(fd); + if (closeret) { + PERROR("Closing XML session configuration"); + } + } + return ret; } @@ -1613,7 +2286,7 @@ int cmd_save_sessions(struct lttng_save_session_attr *attr, session_lock(session); ret = save_session(session, attr, creds); session_unlock(session); - if (ret) { + if (ret != LTTNG_OK) { goto end; } } else { @@ -1625,7 +2298,7 @@ int cmd_save_sessions(struct lttng_save_session_attr *attr, session_unlock(session); /* Don't abort if we don't have the required permissions. */ - if (ret && ret != LTTNG_ERR_EPERM) { + if (ret != LTTNG_OK && ret != LTTNG_ERR_EPERM) { goto end; } }