X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=696e650debb70e6c0f9724b506a1b1413f0bd3a7;hp=872a6cea160940c59e7a0d2bf6699dd7208a8ce3;hb=6bad3253d952934f18be50e032b3d495e7a54613;hpb=6e911cad03751b6814fddd65b19a592acdc2b7b7 diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 872a6cea1..696e650de 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -16,6 +16,7 @@ */ #define _GNU_SOURCE +#define _LGPL_SOURCE #include #include #include @@ -35,6 +36,7 @@ #include "kernel-consumer.h" #include "lttng-sessiond.h" #include "utils.h" +#include "syscall.h" #include "cmd.h" @@ -47,6 +49,21 @@ static pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER; static uint64_t relayd_net_seq_idx; +/* + * Both functions below are special case for the Kernel domain when + * enabling/disabling all events. + */ +static +int enable_kevent_all(struct ltt_session *session, + struct lttng_domain *domain, char *channel_name, + struct lttng_event *event, + char *filter_expression, + struct lttng_filter_bytecode *filter, int wpipe); +static +int disable_kevent_all(struct ltt_session *session, int domain, + char *channel_name, + struct lttng_event *event); + /* * Create a session path used by list_lttng_sessions for the case that the * session consumer is on the network. @@ -203,7 +220,9 @@ static int list_lttng_agent_events(struct agent *agt, DBG3("Listing agent events"); + rcu_read_lock(); nb_event = lttng_ht_get_count(agt->events); + rcu_read_unlock(); if (nb_event == 0) { ret = nb_event; goto error; @@ -345,7 +364,8 @@ static int list_lttng_kernel_events(char *channel_name, DBG("Listing events for channel %s", kchan->channel->name); if (nb_event == 0) { - goto end; + *events = NULL; + goto syscall; } *events = zmalloc(nb_event * sizeof(struct lttng_event)); @@ -392,7 +412,19 @@ static int list_lttng_kernel_events(char *channel_name, i++; } -end: +syscall: + if (syscall_table) { + ssize_t new_size; + + new_size = syscall_list_channel(kchan, events, nb_event); + if (new_size < 0) { + free(events); + ret = -new_size; + goto error; + } + nb_event = new_size; + } + return nb_event; error: @@ -1006,12 +1038,19 @@ int cmd_disable_event(struct ltt_session *session, int domain, int ret; char *event_name; + DBG("Disable event command for event \'%s\'", event->name); + event_name = event->name; - if (event->loglevel_type || event->loglevel || event->enabled + /* Error out on unhandled search criteria */ + if (event->loglevel_type || event->loglevel != -1 || event->enabled || event->pid || event->filter || event->exclusion) { return LTTNG_ERR_UNK; } + /* Special handling for kernel domain all events. */ + if (domain == LTTNG_DOMAIN_KERNEL && !strcmp(event_name, "*")) { + return disable_kevent_all(session, domain, channel_name, event); + } rcu_read_lock(); @@ -1049,6 +1088,9 @@ int cmd_disable_event(struct ltt_session *session, int domain, break; case LTTNG_EVENT_SYSCALL: ret = event_kernel_disable_syscall(kchan, event_name); + if (ret != LTTNG_OK) { + goto error; + } break; default: ret = LTTNG_ERR_UNK; @@ -1100,6 +1142,7 @@ int cmd_disable_event(struct ltt_session *session, int domain, } case LTTNG_DOMAIN_LOG4J: case LTTNG_DOMAIN_JUL: + case LTTNG_DOMAIN_PYTHON: { struct agent *agt; struct ltt_ust_session *usess = session->ust_session; @@ -1119,8 +1162,12 @@ int cmd_disable_event(struct ltt_session *session, int domain, ret = -LTTNG_ERR_UST_EVENT_NOT_FOUND; goto error; } - - ret = event_agent_disable(usess, agt, event_name); + /* The wild card * means that everything should be disabled. */ + if (strncmp(event->name, "*", 1) == 0 && strlen(event->name) == 1) { + ret = event_agent_disable_all(usess, agt); + } else { + ret = event_agent_disable(usess, agt, event_name); + } if (ret != LTTNG_OK) { goto error; } @@ -1145,16 +1192,14 @@ error: } /* - * Command LTTNG_DISABLE_ALL_EVENT processed by the client thread. + * Command LTTNG_DISABLE_EVENT for event "*" processed by the client thread. */ -int cmd_disable_event_all(struct ltt_session *session, int domain, +static +int disable_kevent_all(struct ltt_session *session, int domain, char *channel_name, struct lttng_event *event) { int ret; - char *event_name; - - event_name = event->name; rcu_read_lock(); @@ -1190,44 +1235,8 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, } break; case LTTNG_EVENT_SYSCALL: - ret = event_kernel_disable_syscall(kchan, event_name); - break; - default: - ret = LTTNG_ERR_UNK; - goto error; - } - - kernel_wait_quiescent(kernel_tracer_fd); - break; - } - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_session *usess; - struct ltt_ust_channel *uchan; - - usess = session->ust_session; - - /* - * If a non-default channel has been created in the - * session, explicitely require that -c chan_name needs - * to be provided. - */ - if (usess->has_non_default_channel && channel_name[0] == '\0') { - ret = LTTNG_ERR_NEED_CHANNEL_NAME; - goto error; - } - - uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, - channel_name); - if (uchan == NULL) { - ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; - goto error; - } - - switch (event->type) { - case LTTNG_EVENT_ALL: - ret = event_ust_disable_all_tracepoints(usess, uchan); - if (ret != 0) { + ret = event_kernel_disable_syscall(kchan, ""); + if (ret != LTTNG_OK) { goto error; } break; @@ -1236,44 +1245,9 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, goto error; } - DBG3("Disable all UST events in channel %s completed", channel_name); - - break; - } - case LTTNG_DOMAIN_LOG4J: - case LTTNG_DOMAIN_JUL: - { - struct agent *agt; - struct ltt_ust_session *usess = session->ust_session; - - assert(usess); - - switch (event->type) { - case LTTNG_EVENT_ALL: - break; - default: - ret = LTTNG_ERR_UNK; - goto error; - } - - agt = trace_ust_find_agent(usess, domain); - if (!agt) { - ret = -LTTNG_ERR_UST_EVENT_NOT_FOUND; - goto error; - } - - ret = event_agent_disable_all(usess, agt); - if (ret != LTTNG_OK) { - goto error; - } - + kernel_wait_quiescent(kernel_tracer_fd); break; } -#if 0 - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: -#endif default: ret = LTTNG_ERR_UND; goto error; @@ -1415,6 +1389,7 @@ end: /* * Command LTTNG_ENABLE_EVENT processed by the client thread. + * We own filter, exclusion, and filter_expression. */ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, char *channel_name, struct lttng_event *event, @@ -1430,6 +1405,14 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, assert(event); assert(channel_name); + DBG("Enable event command for event \'%s\'", event->name); + + /* Special handling for kernel domain all events. */ + if (domain->type == LTTNG_DOMAIN_KERNEL && !strcmp(event->name, "*")) { + return enable_kevent_all(session, domain, channel_name, event, + filter_expression, filter, wpipe); + } + ret = validate_event_name(event->name); if (ret) { goto error; @@ -1485,6 +1468,9 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, switch (event->type) { case LTTNG_EVENT_ALL: + case LTTNG_EVENT_PROBE: + case LTTNG_EVENT_FUNCTION: + case LTTNG_EVENT_FUNCTION_ENTRY: case LTTNG_EVENT_TRACEPOINT: ret = event_kernel_enable_tracepoint(kchan, event); if (ret != LTTNG_OK) { @@ -1497,6 +1483,9 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, break; case LTTNG_EVENT_SYSCALL: ret = event_kernel_enable_syscall(kchan, event->name); + if (ret != LTTNG_OK) { + goto error; + } break; default: ret = LTTNG_ERR_UNK; @@ -1552,6 +1541,10 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, /* At this point, the session and channel exist on the tracer */ ret = event_ust_enable_tracepoint(usess, uchan, event, filter_expression, filter, exclusion); + /* We have passed ownership */ + filter_expression = NULL; + filter = NULL; + exclusion = NULL; if (ret != LTTNG_OK) { goto error; } @@ -1559,6 +1552,7 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, } case LTTNG_DOMAIN_LOG4J: case LTTNG_DOMAIN_JUL: + case LTTNG_DOMAIN_PYTHON: { const char *default_event_name, *default_chan_name; struct agent *agt; @@ -1598,14 +1592,45 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, memcpy(&tmp_dom, domain, sizeof(tmp_dom)); tmp_dom.type = LTTNG_DOMAIN_UST; - if (domain->type == LTTNG_DOMAIN_LOG4J) { + switch (domain->type) { + case LTTNG_DOMAIN_LOG4J: default_chan_name = DEFAULT_LOG4J_CHANNEL_NAME; - } else { + break; + case LTTNG_DOMAIN_JUL: default_chan_name = DEFAULT_JUL_CHANNEL_NAME; + break; + case LTTNG_DOMAIN_PYTHON: + default_chan_name = DEFAULT_PYTHON_CHANNEL_NAME; + break; + default: + /* The switch/case we are in should avoid this else big problem */ + assert(0); + } + + { + struct lttng_filter_bytecode *filter_copy = NULL; + + if (filter) { + filter_copy = zmalloc( + sizeof(struct lttng_filter_bytecode) + + filter->len); + if (!filter_copy) { + goto error; + } + + memcpy(filter_copy, filter, + sizeof(struct lttng_filter_bytecode) + + filter->len); + } + + ret = cmd_enable_event(session, &tmp_dom, + (char *) default_chan_name, + &uevent, filter_expression, filter_copy, + NULL, wpipe); + /* We have passed ownership */ + filter_expression = NULL; } - ret = cmd_enable_event(session, &tmp_dom, (char *) default_chan_name, - &uevent, filter_expression, filter, NULL, wpipe); if (ret != LTTNG_OK && ret != LTTNG_ERR_UST_EVENT_ENABLED) { goto error; } @@ -1613,8 +1638,10 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, /* The wild card * means that everything should be enabled. */ if (strncmp(event->name, "*", 1) == 0 && strlen(event->name) == 1) { ret = event_agent_enable_all(usess, agt, event, filter); + filter = NULL; } else { ret = event_agent_enable(usess, agt, event, filter); + filter = NULL; } if (ret != LTTNG_OK) { goto error; @@ -1635,15 +1662,20 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, ret = LTTNG_OK; error: + free(filter_expression); + free(filter); + free(exclusion); rcu_read_unlock(); return ret; } /* - * Command LTTNG_ENABLE_ALL_EVENT processed by the client thread. + * Command LTTNG_ENABLE_EVENT for event "*" processed by the client thread. */ -int cmd_enable_event_all(struct ltt_session *session, - struct lttng_domain *domain, char *channel_name, int event_type, +static +int enable_kevent_all(struct ltt_session *session, + struct lttng_domain *domain, char *channel_name, + struct lttng_event *event, char *filter_expression, struct lttng_filter_bytecode *filter, int wpipe) { @@ -1698,9 +1730,12 @@ int cmd_enable_event_all(struct ltt_session *session, assert(kchan); } - switch (event_type) { + switch (event->type) { case LTTNG_EVENT_SYSCALL: ret = event_kernel_enable_syscall(kchan, ""); + if (ret != LTTNG_OK) { + goto error; + } break; case LTTNG_EVENT_TRACEPOINT: /* @@ -1730,98 +1765,6 @@ int cmd_enable_event_all(struct ltt_session *session, kernel_wait_quiescent(kernel_tracer_fd); break; } - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_channel *uchan; - struct ltt_ust_session *usess = session->ust_session; - - assert(usess); - - /* - * If a non-default channel has been created in the - * session, explicitely require that -c chan_name needs - * to be provided. - */ - if (usess->has_non_default_channel && channel_name[0] == '\0') { - ret = LTTNG_ERR_NEED_CHANNEL_NAME; - goto error; - } - - /* Get channel from global UST domain */ - uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, - channel_name); - if (uchan == NULL) { - /* Create default channel */ - attr = channel_new_default_attr(LTTNG_DOMAIN_UST, - usess->buffer_type); - if (attr == NULL) { - ret = LTTNG_ERR_FATAL; - goto error; - } - strncpy(attr->name, channel_name, sizeof(attr->name)); - - ret = cmd_enable_channel(session, domain, attr, wpipe); - if (ret != LTTNG_OK) { - free(attr); - goto error; - } - free(attr); - - /* Get the newly created channel reference back */ - uchan = trace_ust_find_channel_by_name( - usess->domain_global.channels, channel_name); - assert(uchan); - } - - /* At this point, the session and channel exist on the tracer */ - - switch (event_type) { - case LTTNG_EVENT_ALL: - case LTTNG_EVENT_TRACEPOINT: - ret = event_ust_enable_all_tracepoints(usess, uchan, - filter_expression, filter); - if (ret != LTTNG_OK) { - goto error; - } - break; - default: - ret = LTTNG_ERR_UST_ENABLE_FAIL; - goto error; - } - - /* Manage return value */ - if (ret != LTTNG_OK) { - goto error; - } - - break; - } - case LTTNG_DOMAIN_LOG4J: - case LTTNG_DOMAIN_JUL: - { - struct lttng_event event; - struct ltt_ust_session *usess = session->ust_session; - - assert(usess); - - event.loglevel = LTTNG_LOGLEVEL_JUL_ALL; - event.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; - strncpy(event.name, "*", sizeof(event.name)); - event.name[sizeof(event.name) - 1] = '\0'; - - ret = cmd_enable_event(session, domain, NULL, &event, - filter_expression, filter, NULL, wpipe); - if (ret != LTTNG_OK && ret != LTTNG_ERR_UST_EVENT_ENABLED) { - goto error; - } - - break; - } -#if 0 - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: -#endif default: ret = LTTNG_ERR_UND; goto error; @@ -1860,6 +1803,7 @@ ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events) break; case LTTNG_DOMAIN_LOG4J: case LTTNG_DOMAIN_JUL: + case LTTNG_DOMAIN_PYTHON: nb_events = agent_list_events(events, domain); if (nb_events < 0) { ret = LTTNG_ERR_UST_LIST_FAIL; @@ -1908,6 +1852,11 @@ error: return -ret; } +ssize_t cmd_list_syscalls(struct lttng_event **events) +{ + return syscall_table_list(events); +} + /* * Command LTTNG_START_TRACE processed by the client thread. */ @@ -1935,7 +1884,9 @@ int cmd_start_trace(struct ltt_session *session) * possible to enable channel thus inform the client. */ if (usess && usess->domain_global.channels) { + rcu_read_lock(); nb_chan += lttng_ht_get_count(usess->domain_global.channels); + rcu_read_unlock(); } if (ksession) { nb_chan += ksession->channel_count; @@ -2467,12 +2418,18 @@ ssize_t cmd_list_domains(struct ltt_session *session, DBG3("Listing domains found UST global domain"); nb_dom++; + rcu_read_lock(); cds_lfht_for_each_entry(session->ust_session->agents->ht, &iter.iter, agt, node.node) { if (agt->being_used) { nb_dom++; } } + rcu_read_unlock(); + } + + if (!nb_dom) { + goto end; } *domains = zmalloc(nb_dom * sizeof(struct lttng_domain)); @@ -2491,6 +2448,7 @@ ssize_t cmd_list_domains(struct ltt_session *session, (*domains)[index].buf_type = session->ust_session->buffer_type; index++; + rcu_read_lock(); cds_lfht_for_each_entry(session->ust_session->agents->ht, &iter.iter, agt, node.node) { if (agt->being_used) { @@ -2499,8 +2457,9 @@ ssize_t cmd_list_domains(struct ltt_session *session, index++; } } + rcu_read_unlock(); } - +end: return nb_dom; error: @@ -2530,16 +2489,18 @@ ssize_t cmd_list_channels(int domain, struct ltt_session *session, break; case LTTNG_DOMAIN_UST: if (session->ust_session != NULL) { + rcu_read_lock(); nb_chan = lttng_ht_get_count( - session->ust_session->domain_global.channels); + session->ust_session->domain_global.channels); + rcu_read_unlock(); } DBG3("Number of UST global channels %zd", nb_chan); - if (nb_chan <= 0) { + if (nb_chan < 0) { ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; + goto error; } break; default: - *channels = NULL; ret = LTTNG_ERR_UND; goto error; } @@ -2552,10 +2513,6 @@ ssize_t cmd_list_channels(int domain, struct ltt_session *session, } list_lttng_channels(domain, session, *channels); - } else { - *channels = NULL; - /* Ret value was set in the domain switch case */ - goto error; } return nb_chan; @@ -2591,14 +2548,17 @@ ssize_t cmd_list_events(int domain, struct ltt_session *session, } case LTTNG_DOMAIN_LOG4J: case LTTNG_DOMAIN_JUL: + case LTTNG_DOMAIN_PYTHON: if (session->ust_session) { struct lttng_ht_iter iter; struct agent *agt; + rcu_read_lock(); cds_lfht_for_each_entry(session->ust_session->agents->ht, &iter.iter, agt, node.node) { nb_event = list_lttng_agent_events(agt, events); } + rcu_read_unlock(); } break; default: @@ -2847,7 +2807,7 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, struct lttng_snapshot_output **outputs) { int ret, idx = 0; - struct lttng_snapshot_output *list; + struct lttng_snapshot_output *list = NULL; struct lttng_ht_iter iter; struct snapshot_output *output; @@ -2861,7 +2821,7 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, * set in no output mode. */ if (session->output_traces) { - ret = LTTNG_ERR_EPERM; + ret = -LTTNG_ERR_EPERM; goto error; } @@ -2872,11 +2832,12 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, list = zmalloc(session->snapshot.nb_output * sizeof(*list)); if (!list) { - ret = LTTNG_ERR_NOMEM; + ret = -LTTNG_ERR_NOMEM; goto error; } /* Copy list from session to the new list object. */ + rcu_read_lock(); cds_lfht_for_each_entry(session->snapshot.output_ht->ht, &iter.iter, output, node.node) { assert(output->consumer); @@ -2891,28 +2852,28 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, ret = uri_to_str_url(&output->consumer->dst.net.control, list[idx].ctrl_url, sizeof(list[idx].ctrl_url)); if (ret < 0) { - ret = LTTNG_ERR_NOMEM; - goto free_error; + ret = -LTTNG_ERR_NOMEM; + goto error; } /* Data URI. */ ret = uri_to_str_url(&output->consumer->dst.net.data, list[idx].data_url, sizeof(list[idx].data_url)); if (ret < 0) { - ret = LTTNG_ERR_NOMEM; - goto free_error; + ret = -LTTNG_ERR_NOMEM; + goto error; } } idx++; } *outputs = list; - return session->snapshot.nb_output; - -free_error: - free(list); + list = NULL; + ret = session->snapshot.nb_output; error: - return -ret; + free(list); + rcu_read_unlock(); + return ret; } /* @@ -3105,12 +3066,14 @@ static uint64_t get_session_max_subbuf_size(struct ltt_session *session) struct ltt_ust_channel *uchan; struct ltt_ust_session *usess = session->ust_session; + rcu_read_lock(); cds_lfht_for_each_entry(usess->domain_global.channels->ht, &iter.iter, uchan, node.node) { if (uchan->attr.subbuf_size > max_size) { max_size = uchan->attr.subbuf_size; } } + rcu_read_unlock(); } return max_size; @@ -3157,6 +3120,7 @@ int cmd_snapshot_record(struct ltt_session *session, uint64_t session_max_size = 0, max_stream_size = 0; assert(session); + assert(output); DBG("Cmd snapshot record for session %s", session->name); @@ -3176,7 +3140,7 @@ int cmd_snapshot_record(struct ltt_session *session, } /* Use temporary output for the session. */ - if (output && *output->ctrl_url != '\0') { + if (*output->ctrl_url != '\0') { ret = snapshot_output_init(output->max_size, output->name, output->ctrl_url, output->data_url, session->consumer, &tmp_output, NULL);