X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=4fcd6a4feafdf2eae0b1e4393dd69ecfd6716d5e;hp=d36966322fc7278617109b9df471bda8196ea5cc;hb=36b588eddce05ef840bd247f6a58316925b9a0a2;hpb=2f77fc4b3720dc8f75847130498c2d4aad7c03ec diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index d36966322..4fcd6a4fe 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -28,6 +28,7 @@ #include "channel.h" #include "consumer.h" #include "event.h" +#include "health.h" #include "kernel.h" #include "kernel-consumer.h" #include "lttng-sessiond.h" @@ -38,12 +39,11 @@ /* * Used to keep a unique index for each relayd socket created where this value * is associated with streams on the consumer so it can match the right relayd - * to send to. - * - * This value should be incremented atomically for safety purposes and future - * possible concurrent access. + * to send to. It must be accessed with the relayd_net_seq_idx_lock + * held. */ -static unsigned int relayd_net_seq_idx; +static pthread_mutex_t relayd_net_seq_idx_lock = PTHREAD_MUTEX_INITIALIZER; +static uint64_t relayd_net_seq_idx; /* * Create a session path used by list_lttng_sessions for the case that the @@ -101,11 +101,22 @@ static int build_network_session_path(char *dst, size_t size, goto error; } - if (strlen(tmp_uurl) > 0) { + /* + * Do we have a UST url set. If yes, this means we have both kernel and UST + * to print. + */ + if (*tmp_uurl != '\0') { ret = snprintf(dst, size, "[K]: %s [data: %d] -- [U]: %s [data: %d]", tmp_urls, kdata_port, tmp_uurl, udata_port); } else { - ret = snprintf(dst, size, "%s [data: %d]", tmp_urls, kdata_port); + int dport; + if (kuri) { + dport = kdata_port; + } else { + /* No kernel URI, use the UST port. */ + dport = udata_port; + } + ret = snprintf(dst, size, "%s [data: %d]", tmp_urls, dport); } error: @@ -141,6 +152,7 @@ static void list_lttng_channels(int domain, struct ltt_session *session, struct lttng_ht_iter iter; struct ltt_ust_channel *uchan; + rcu_read_lock(); cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, &iter.iter, uchan, node.node) { strncpy(channels[i].name, uchan->name, LTTNG_SYMBOL_NAME_LEN); @@ -160,6 +172,7 @@ static void list_lttng_channels(int domain, struct ltt_session *session, } i++; } + rcu_read_unlock(); break; } default: @@ -188,7 +201,7 @@ static int list_lttng_ust_global_events(char *channel_name, lttng_ht_lookup(ust_global->channels, (void *)channel_name, &iter); node = lttng_ht_iter_get_node_str(&iter); if (node == NULL) { - ret = -LTTCOMM_UST_CHAN_NOT_FOUND; + ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; goto error; } @@ -205,7 +218,7 @@ static int list_lttng_ust_global_events(char *channel_name, tmp = zmalloc(nb_event * sizeof(struct lttng_event)); if (tmp == NULL) { - ret = -LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } @@ -265,7 +278,7 @@ static int list_lttng_kernel_events(char *channel_name, kchan = trace_kernel_get_channel_by_name(channel_name, kernel_session); if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND; goto error; } @@ -274,13 +287,12 @@ static int list_lttng_kernel_events(char *channel_name, DBG("Listing events for channel %s", kchan->channel->name); if (nb_event == 0) { - ret = nb_event; - goto error; + goto end; } *events = zmalloc(nb_event * sizeof(struct lttng_event)); if (*events == NULL) { - ret = LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } @@ -294,8 +306,12 @@ static int list_lttng_kernel_events(char *channel_name, case LTTNG_KERNEL_TRACEPOINT: (*events)[i].type = LTTNG_EVENT_TRACEPOINT; break; - case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_KRETPROBE: + (*events)[i].type = LTTNG_EVENT_FUNCTION; + memcpy(&(*events)[i].attr.probe, &event->event->u.kprobe, + sizeof(struct lttng_kernel_kprobe)); + break; + case LTTNG_KERNEL_KPROBE: (*events)[i].type = LTTNG_EVENT_PROBE; memcpy(&(*events)[i].attr.probe, &event->event->u.kprobe, sizeof(struct lttng_kernel_kprobe)); @@ -318,10 +334,12 @@ static int list_lttng_kernel_events(char *channel_name, i++; } +end: return nb_event; error: - return ret; + /* Negate the error code to differentiate the size from an error */ + return -ret; } /* @@ -331,14 +349,14 @@ error: static int add_uri_to_consumer(struct consumer_output *consumer, struct lttng_uri *uri, int domain, const char *session_name) { - int ret = LTTCOMM_OK; + int ret = LTTNG_OK; const char *default_trace_dir; assert(uri); if (consumer == NULL) { DBG("No consumer detected. Don't add URI. Stopping."); - ret = LTTCOMM_NO_CONSUMER; + ret = LTTNG_ERR_NO_CONSUMER; goto error; } @@ -362,10 +380,24 @@ static int add_uri_to_consumer(struct consumer_output *consumer, case LTTNG_DST_IPV6: DBG2("Setting network URI to consumer"); + if (consumer->type == CONSUMER_DST_NET) { + if ((uri->stype == LTTNG_STREAM_CONTROL && + consumer->dst.net.control_isset) || + (uri->stype == LTTNG_STREAM_DATA && + consumer->dst.net.data_isset)) { + ret = LTTNG_ERR_URL_EXIST; + goto error; + } + } else { + memset(&consumer->dst.net, 0, sizeof(consumer->dst.net)); + } + + consumer->type = CONSUMER_DST_NET; + /* Set URI into consumer output object */ ret = consumer_set_network_uri(consumer, uri); if (ret < 0) { - ret = LTTCOMM_FATAL; + ret = -ret; goto error; } else if (ret == 1) { /* @@ -378,14 +410,15 @@ static int add_uri_to_consumer(struct consumer_output *consumer, if (uri->stype == LTTNG_STREAM_CONTROL && strlen(uri->subdir) == 0) { ret = consumer_set_subdir(consumer, session_name); if (ret < 0) { - ret = LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } } if (uri->stype == LTTNG_STREAM_CONTROL) { /* On a new subdir, reappend the default trace dir. */ - strncat(consumer->subdir, default_trace_dir, sizeof(consumer->subdir)); + strncat(consumer->subdir, default_trace_dir, + sizeof(consumer->subdir) - strlen(consumer->subdir) - 1); DBG3("Append domain trace name to subdir %s", consumer->subdir); } @@ -398,12 +431,15 @@ static int add_uri_to_consumer(struct consumer_output *consumer, sizeof(consumer->dst.trace_path)); /* Append default trace dir */ strncat(consumer->dst.trace_path, default_trace_dir, - sizeof(consumer->dst.trace_path)); + sizeof(consumer->dst.trace_path) - + strlen(consumer->dst.trace_path) - 1); /* Flag consumer as local. */ consumer->type = CONSUMER_DST_LOCAL; break; } + ret = LTTNG_OK; + error: return ret; } @@ -419,6 +455,8 @@ static int init_kernel_tracing(struct ltt_kernel_session *session) assert(session); + rcu_read_lock(); + if (session->consumer_fds_sent == 0 && session->consumer != NULL) { cds_lfht_for_each_entry(session->consumer->socks->ht, &iter.iter, socket, node.node) { @@ -426,16 +464,17 @@ static int init_kernel_tracing(struct ltt_kernel_session *session) assert(socket->fd >= 0); pthread_mutex_lock(socket->lock); - ret = kernel_consumer_send_session(socket->fd, session); + ret = kernel_consumer_send_session(socket, session); pthread_mutex_unlock(socket->lock); if (ret < 0) { - ret = LTTCOMM_KERN_CONSUMER_FAIL; + ret = LTTNG_ERR_KERN_CONSUMER_FAIL; goto error; } } } error: + rcu_read_unlock(); return ret; } @@ -445,31 +484,30 @@ error: * On success, the relayd_sock pointer is set to the created socket. * Else, it's stays untouched and a lttcomm error code is returned. */ -static int create_connect_relayd(struct consumer_output *output, - const char *session_name, struct lttng_uri *uri, - struct lttcomm_sock **relayd_sock) +static int create_connect_relayd(struct lttng_uri *uri, + struct lttcomm_relayd_sock **relayd_sock) { int ret; - struct lttcomm_sock *sock; + struct lttcomm_relayd_sock *rsock; - /* Create socket object from URI */ - sock = lttcomm_alloc_sock_from_uri(uri); - if (sock == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - - ret = lttcomm_create_sock(sock); - if (ret < 0) { - ret = LTTCOMM_FATAL; + rsock = lttcomm_alloc_relayd_sock(uri, RELAYD_VERSION_COMM_MAJOR, + RELAYD_VERSION_COMM_MINOR); + if (!rsock) { + ret = LTTNG_ERR_FATAL; goto error; } - /* Connect to relayd so we can proceed with a session creation. */ - ret = relayd_connect(sock); + /* + * Connect to relayd so we can proceed with a session creation. This call + * can possibly block for an arbitrary amount of time to set the health + * state to be in poll execution. + */ + health_poll_entry(); + ret = relayd_connect(rsock); + health_poll_exit(); if (ret < 0) { ERR("Unable to reach lttng-relayd"); - ret = LTTCOMM_RELAYD_SESSION_FAIL; + ret = LTTNG_ERR_RELAYD_CONNECT_FAIL; goto free_sock; } @@ -478,10 +516,9 @@ static int create_connect_relayd(struct consumer_output *output, DBG3("Creating relayd stream socket from URI"); /* Check relayd version */ - ret = relayd_version_check(sock, RELAYD_VERSION_COMM_MAJOR, - RELAYD_VERSION_COMM_MINOR); + ret = relayd_version_check(rsock); if (ret < 0) { - ret = LTTCOMM_RELAYD_VERSION_FAIL; + ret = LTTNG_ERR_RELAYD_VERSION_FAIL; goto close_sock; } } else if (uri->stype == LTTNG_STREAM_DATA) { @@ -489,22 +526,19 @@ static int create_connect_relayd(struct consumer_output *output, } else { /* Command is not valid */ ERR("Relayd invalid stream type: %d", uri->stype); - ret = LTTCOMM_INVALID; + ret = LTTNG_ERR_INVALID; goto close_sock; } - *relayd_sock = sock; + *relayd_sock = rsock; - return LTTCOMM_OK; + return LTTNG_OK; close_sock: - if (sock) { - (void) relayd_close(sock); - } + /* The returned value is not useful since we are on an error path. */ + (void) relayd_close(rsock); free_sock: - if (sock) { - lttcomm_destroy_sock(sock); - } + free(rsock); error: return ret; } @@ -514,43 +548,51 @@ error: */ static int send_consumer_relayd_socket(int domain, struct ltt_session *session, struct lttng_uri *relayd_uri, struct consumer_output *consumer, - int consumer_fd) + struct consumer_socket *consumer_sock) { int ret; - struct lttcomm_sock *sock = NULL; - - /* Set the network sequence index if not set. */ - if (consumer->net_seq_index == -1) { - /* - * Increment net_seq_idx because we are about to transfer the - * new relayd socket to the consumer. - */ - uatomic_inc(&relayd_net_seq_idx); - /* Assign unique key so the consumer can match streams */ - uatomic_set(&consumer->net_seq_index, - uatomic_read(&relayd_net_seq_idx)); - } + struct lttcomm_relayd_sock *rsock = NULL; /* Connect to relayd and make version check if uri is the control. */ - ret = create_connect_relayd(consumer, session->name, relayd_uri, &sock); - if (ret != LTTCOMM_OK) { - goto close_sock; + ret = create_connect_relayd(relayd_uri, &rsock); + if (ret != LTTNG_OK) { + goto error; } + assert(rsock); /* If the control socket is connected, network session is ready */ if (relayd_uri->stype == LTTNG_STREAM_CONTROL) { session->net_handle = 1; } + /* Set the network sequence index if not set. */ + if (consumer->net_seq_index == (uint64_t) -1ULL) { + pthread_mutex_lock(&relayd_net_seq_idx_lock); + /* + * Increment net_seq_idx because we are about to transfer the + * new relayd socket to the consumer. + * Assign unique key so the consumer can match streams. + */ + consumer->net_seq_index = ++relayd_net_seq_idx; + pthread_mutex_unlock(&relayd_net_seq_idx_lock); + } + /* Send relayd socket to consumer. */ - ret = consumer_send_relayd_socket(consumer_fd, sock, - consumer, relayd_uri->stype); + ret = consumer_send_relayd_socket(consumer_sock, rsock, consumer, + relayd_uri->stype, session->id); if (ret < 0) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; + ret = LTTNG_ERR_ENABLE_CONSUMER_FAIL; goto close_sock; } - ret = LTTCOMM_OK; + /* Flag that the corresponding socket was sent. */ + if (relayd_uri->stype == LTTNG_STREAM_CONTROL) { + consumer_sock->control_sock_sent = 1; + } else if (relayd_uri->stype == LTTNG_STREAM_DATA) { + consumer_sock->data_sock_sent = 1; + } + + ret = LTTNG_OK; /* * Close socket which was dup on the consumer side. The session daemon does @@ -558,11 +600,17 @@ static int send_consumer_relayd_socket(int domain, struct ltt_session *session, */ close_sock: - if (sock) { - (void) relayd_close(sock); - lttcomm_destroy_sock(sock); - } + (void) relayd_close(rsock); + free(rsock); +error: + if (ret != LTTNG_OK) { + /* + * On error, nullify the consumer sequence index so streams are not + * associated with it once sent to the consumer. + */ + uatomic_set(&consumer->net_seq_index, -1); + } return ret; } @@ -572,36 +620,32 @@ close_sock: * session. */ static int send_consumer_relayd_sockets(int domain, - struct ltt_session *session, struct consumer_output *consumer, int fd) + struct ltt_session *session, struct consumer_output *consumer, + struct consumer_socket *sock) { - int ret; + int ret = LTTNG_OK; assert(session); assert(consumer); - /* Don't resend the sockets to the consumer. */ - if (consumer->dst.net.relayd_socks_sent) { - ret = LTTCOMM_OK; - goto error; - } - /* Sending control relayd socket. */ - ret = send_consumer_relayd_socket(domain, session, - &consumer->dst.net.control, consumer, fd); - if (ret != LTTCOMM_OK) { - goto error; + if (!sock->control_sock_sent) { + ret = send_consumer_relayd_socket(domain, session, + &consumer->dst.net.control, consumer, sock); + if (ret != LTTNG_OK) { + goto error; + } } /* Sending data relayd socket. */ - ret = send_consumer_relayd_socket(domain, session, - &consumer->dst.net.data, consumer, fd); - if (ret != LTTCOMM_OK) { - goto error; + if (!sock->data_sock_sent) { + ret = send_consumer_relayd_socket(domain, session, + &consumer->dst.net.data, consumer, sock); + if (ret != LTTNG_OK) { + goto error; + } } - /* Flag that all relayd sockets were sent to the consumer. */ - consumer->dst.net.relayd_socks_sent = 1; - error: return ret; } @@ -611,9 +655,9 @@ error: * the relayd and send them to the right domain consumer. Consumer type MUST be * network. */ -static int setup_relayd(struct ltt_session *session) +int cmd_setup_relayd(struct ltt_session *session) { - int ret = LTTCOMM_OK; + int ret = LTTNG_OK; struct ltt_ust_session *usess; struct ltt_kernel_session *ksess; struct consumer_socket *socket; @@ -624,7 +668,9 @@ static int setup_relayd(struct ltt_session *session) usess = session->ust_session; ksess = session->kernel_session; - DBG2("Setting relayd for session %s", session->name); + DBG("Setting relayd for session %s", session->name); + + rcu_read_lock(); if (usess && usess->consumer && usess->consumer->type == CONSUMER_DST_NET && usess->consumer->enabled) { @@ -635,10 +681,10 @@ static int setup_relayd(struct ltt_session *session) assert(socket->fd >= 0); pthread_mutex_lock(socket->lock); - send_consumer_relayd_sockets(LTTNG_DOMAIN_UST, session, - usess->consumer, socket->fd); + ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_UST, session, + usess->consumer, socket); pthread_mutex_unlock(socket->lock); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto error; } } @@ -652,15 +698,81 @@ static int setup_relayd(struct ltt_session *session) assert(socket->fd >= 0); pthread_mutex_lock(socket->lock); - send_consumer_relayd_sockets(LTTNG_DOMAIN_KERNEL, session, - ksess->consumer, socket->fd); + ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_KERNEL, session, + ksess->consumer, socket); pthread_mutex_unlock(socket->lock); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto error; } } } +error: + rcu_read_unlock(); + return ret; +} + +/* + * Start a kernel session by opening all necessary streams. + */ +static int start_kernel_session(struct ltt_kernel_session *ksess, int wpipe) +{ + int ret; + struct ltt_kernel_channel *kchan; + + /* Open kernel metadata */ + if (ksess->metadata == NULL) { + ret = kernel_open_metadata(ksess); + if (ret < 0) { + ret = LTTNG_ERR_KERN_META_FAIL; + goto error; + } + } + + /* Open kernel metadata stream */ + if (ksess->metadata_stream_fd < 0) { + ret = kernel_open_metadata_stream(ksess); + if (ret < 0) { + ERR("Kernel create metadata stream failed"); + ret = LTTNG_ERR_KERN_STREAM_FAIL; + goto error; + } + } + + /* For each channel */ + cds_list_for_each_entry(kchan, &ksess->channel_list.head, list) { + if (kchan->stream_count == 0) { + ret = kernel_open_channel_stream(kchan); + if (ret < 0) { + ret = LTTNG_ERR_KERN_STREAM_FAIL; + goto error; + } + /* Update the stream global counter */ + ksess->stream_count_global += ret; + } + } + + /* Setup kernel consumer socket and send fds to it */ + ret = init_kernel_tracing(ksess); + if (ret < 0) { + ret = LTTNG_ERR_KERN_START_FAIL; + goto error; + } + + /* This start the kernel tracing */ + ret = kernel_start_session(ksess); + if (ret < 0) { + ret = LTTNG_ERR_KERN_START_FAIL; + goto error; + } + + /* Quiescent wait after starting trace */ + kernel_wait_quiescent(kernel_tracer_fd); + + ksess->started = 1; + + ret = LTTNG_OK; + error: return ret; } @@ -676,12 +788,14 @@ int cmd_disable_channel(struct ltt_session *session, int domain, usess = session->ust_session; + rcu_read_lock(); + switch (domain) { case LTTNG_DOMAIN_KERNEL: { ret = channel_kernel_disable(session->kernel_session, channel_name); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto error; } @@ -697,12 +811,12 @@ int cmd_disable_channel(struct ltt_session *session, int domain, uchan = trace_ust_find_channel_by_name(chan_ht, channel_name); if (uchan == NULL) { - ret = LTTCOMM_UST_CHAN_NOT_FOUND; + ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; goto error; } - ret = channel_ust_disable(usess, domain, uchan); - if (ret != LTTCOMM_OK) { + ret = channel_ust_disable(usess, uchan); + if (ret != LTTNG_OK) { goto error; } break; @@ -713,13 +827,14 @@ int cmd_disable_channel(struct ltt_session *session, int domain, case LTTNG_DOMAIN_UST_PID: #endif default: - ret = LTTCOMM_UNKNOWN_DOMAIN; + ret = LTTNG_ERR_UNKNOWN_DOMAIN; goto error; } - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: + rcu_read_unlock(); return ret; } @@ -729,7 +844,7 @@ error: * The wpipe arguments is used as a notifier for the kernel thread. */ int cmd_enable_channel(struct ltt_session *session, - int domain, struct lttng_channel *attr, int wpipe) + struct lttng_domain *domain, struct lttng_channel *attr, int wpipe) { int ret; struct ltt_ust_session *usess = session->ust_session; @@ -737,17 +852,17 @@ int cmd_enable_channel(struct ltt_session *session, assert(session); assert(attr); + assert(domain); DBG("Enabling channel %s for session %s", attr->name, session->name); - switch (domain) { + rcu_read_lock(); + + switch (domain->type) { case LTTNG_DOMAIN_KERNEL: { struct ltt_kernel_channel *kchan; - /* Mandatory for a kernel channel. */ - assert(wpipe > 0); - kchan = trace_kernel_get_channel_by_name(attr->name, session->kernel_session); if (kchan == NULL) { @@ -756,11 +871,23 @@ int cmd_enable_channel(struct ltt_session *session, ret = channel_kernel_enable(session->kernel_session, kchan); } - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto error; } kernel_wait_quiescent(kernel_tracer_fd); + + /* + * If the session was previously started, start as well this newly + * created kernel session so the events/channels enabled *after* the + * start actually work. + */ + if (session->started && !session->kernel_session->started) { + ret = start_kernel_session(session->kernel_session, wpipe); + if (ret != LTTNG_OK) { + goto error; + } + } break; } case LTTNG_DOMAIN_UST: @@ -771,23 +898,30 @@ int cmd_enable_channel(struct ltt_session *session, uchan = trace_ust_find_channel_by_name(chan_ht, attr->name); if (uchan == NULL) { - ret = channel_ust_create(usess, domain, attr); + ret = channel_ust_create(usess, attr, domain->buf_type); } else { - ret = channel_ust_enable(usess, domain, uchan); + ret = channel_ust_enable(usess, uchan); + } + + /* Start the UST session if the session was already started. */ + if (session->started && !usess->start_trace) { + ret = ust_app_start_trace_all(usess); + if (ret < 0) { + ret = LTTNG_ERR_UST_START_FAIL; + goto error; + } + ret = LTTNG_OK; + usess->start_trace = 1; } break; } -#if 0 - case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: - case LTTNG_DOMAIN_UST_EXEC_NAME: - case LTTNG_DOMAIN_UST_PID: -#endif default: - ret = LTTCOMM_UNKNOWN_DOMAIN; + ret = LTTNG_ERR_UNKNOWN_DOMAIN; goto error; } error: + rcu_read_unlock(); return ret; } @@ -800,6 +934,8 @@ int cmd_disable_event(struct ltt_session *session, int domain, { int ret; + rcu_read_lock(); + switch (domain) { case LTTNG_DOMAIN_KERNEL: { @@ -810,12 +946,12 @@ int cmd_disable_event(struct ltt_session *session, int domain, kchan = trace_kernel_get_channel_by_name(channel_name, ksess); if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND; goto error; } - ret = event_kernel_disable_tracepoint(ksess, kchan, event_name); - if (ret != LTTCOMM_OK) { + ret = event_kernel_disable_tracepoint(kchan, event_name); + if (ret != LTTNG_OK) { goto error; } @@ -832,12 +968,12 @@ int cmd_disable_event(struct ltt_session *session, int domain, uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, channel_name); if (uchan == NULL) { - ret = LTTCOMM_UST_CHAN_NOT_FOUND; + ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; goto error; } - ret = event_ust_disable_tracepoint(usess, domain, uchan, event_name); - if (ret != LTTCOMM_OK) { + ret = event_ust_disable_tracepoint(usess, uchan, event_name); + if (ret != LTTNG_OK) { goto error; } @@ -851,13 +987,14 @@ int cmd_disable_event(struct ltt_session *session, int domain, case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: #endif default: - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: + rcu_read_unlock(); return ret; } @@ -869,6 +1006,8 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, { int ret; + rcu_read_lock(); + switch (domain) { case LTTNG_DOMAIN_KERNEL: { @@ -879,12 +1018,12 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, kchan = trace_kernel_get_channel_by_name(channel_name, ksess); if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND; goto error; } - ret = event_kernel_disable_all(ksess, kchan); - if (ret != LTTCOMM_OK) { + ret = event_kernel_disable_all(kchan); + if (ret != LTTNG_OK) { goto error; } @@ -901,11 +1040,11 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, uchan = trace_ust_find_channel_by_name(usess->domain_global.channels, channel_name); if (uchan == NULL) { - ret = LTTCOMM_UST_CHAN_NOT_FOUND; + ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; goto error; } - ret = event_ust_disable_all_tracepoints(usess, domain, uchan); + ret = event_ust_disable_all_tracepoints(usess, uchan); if (ret != 0) { goto error; } @@ -920,13 +1059,14 @@ int cmd_disable_event_all(struct ltt_session *session, int domain, case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: #endif default: - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: + rcu_read_unlock(); return ret; } @@ -934,66 +1074,54 @@ error: * Command LTTNG_ADD_CONTEXT processed by the client thread. */ int cmd_add_context(struct ltt_session *session, int domain, - char *channel_name, char *event_name, struct lttng_event_context *ctx) + char *channel_name, struct lttng_event_context *ctx, int kwpipe) { int ret; switch (domain) { case LTTNG_DOMAIN_KERNEL: + assert(session->kernel_session); + + if (session->kernel_session->channel_count == 0) { + /* Create default channel */ + ret = channel_kernel_create(session->kernel_session, NULL, kwpipe); + if (ret != LTTNG_OK) { + goto error; + } + } + /* Add kernel context to kernel tracer */ - ret = context_kernel_add(session->kernel_session, ctx, - event_name, channel_name); - if (ret != LTTCOMM_OK) { + ret = context_kernel_add(session->kernel_session, ctx, channel_name); + if (ret != LTTNG_OK) { goto error; } break; case LTTNG_DOMAIN_UST: { struct ltt_ust_session *usess = session->ust_session; - assert(usess); - ret = context_ust_add(usess, domain, ctx, event_name, channel_name); - if (ret != LTTCOMM_OK) { - 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 = LTTCOMM_UND; - goto error; - } - - ret = LTTCOMM_OK; - -error: - return ret; -} - -/* - * Command LTTNG_SET_FILTER processed by the client thread. - */ -int cmd_set_filter(struct ltt_session *session, int domain, - char *channel_name, char *event_name, - struct lttng_filter_bytecode *bytecode) -{ - int ret; + unsigned int chan_count = + lttng_ht_get_count(usess->domain_global.channels); + if (chan_count == 0) { + struct lttng_channel *attr; + /* Create default channel */ + attr = channel_new_default_attr(domain); + if (attr == NULL) { + ret = LTTNG_ERR_FATAL; + goto error; + } - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - ret = LTTCOMM_FATAL; - break; - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_session *usess = session->ust_session; + ret = channel_ust_create(usess, attr, usess->buffer_type); + if (ret != LTTNG_OK) { + free(attr); + goto error; + } + free(attr); + } - ret = filter_ust_set(usess, domain, bytecode, event_name, channel_name); - if (ret != LTTCOMM_OK) { + ret = context_ust_add(usess, domain, ctx, channel_name); + if (ret != LTTNG_OK) { goto error; } break; @@ -1004,32 +1132,33 @@ int cmd_set_filter(struct ltt_session *session, int domain, case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: #endif default: - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: return ret; - } - /* * Command LTTNG_ENABLE_EVENT processed by the client thread. */ -int cmd_enable_event(struct ltt_session *session, int domain, - char *channel_name, struct lttng_event *event, int wpipe) +int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain, + char *channel_name, struct lttng_event *event, + struct lttng_filter_bytecode *filter, int wpipe) { - int ret; + int ret, channel_created = 0; struct lttng_channel *attr; assert(session); assert(event); assert(channel_name); - switch (domain) { + rcu_read_lock(); + + switch (domain->type) { case LTTNG_DOMAIN_KERNEL: { struct ltt_kernel_channel *kchan; @@ -1037,19 +1166,21 @@ int cmd_enable_event(struct ltt_session *session, int domain, kchan = trace_kernel_get_channel_by_name(channel_name, session->kernel_session); if (kchan == NULL) { - attr = channel_new_default_attr(domain); + attr = channel_new_default_attr(LTTNG_DOMAIN_KERNEL); if (attr == NULL) { - ret = LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } strncpy(attr->name, channel_name, sizeof(attr->name)); ret = cmd_enable_channel(session, domain, attr, wpipe); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { free(attr); goto error; } free(attr); + + channel_created = 1; } /* Get the newly created kernel channel pointer */ @@ -1057,13 +1188,16 @@ int cmd_enable_event(struct ltt_session *session, int domain, session->kernel_session); if (kchan == NULL) { /* This sould not happen... */ - ret = LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } - ret = event_kernel_enable_tracepoint(session->kernel_session, kchan, - event); - if (ret != LTTCOMM_OK) { + ret = event_kernel_enable_tracepoint(kchan, event); + if (ret != LTTNG_OK) { + if (channel_created) { + /* Let's not leak a useless channel. */ + kernel_destroy_channel(kchan); + } goto error; } @@ -1082,15 +1216,15 @@ int cmd_enable_event(struct ltt_session *session, int domain, channel_name); if (uchan == NULL) { /* Create default channel */ - attr = channel_new_default_attr(domain); + attr = channel_new_default_attr(LTTNG_DOMAIN_UST); if (attr == NULL) { - ret = LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } strncpy(attr->name, channel_name, sizeof(attr->name)); ret = cmd_enable_channel(session, domain, attr, wpipe); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { free(attr); goto error; } @@ -1103,8 +1237,8 @@ int cmd_enable_event(struct ltt_session *session, int domain, } /* At this point, the session and channel exist on the tracer */ - ret = event_ust_enable_tracepoint(usess, domain, uchan, event); - if (ret != LTTCOMM_OK) { + ret = event_ust_enable_tracepoint(usess, uchan, event, filter); + if (ret != LTTNG_OK) { goto error; } break; @@ -1115,21 +1249,23 @@ int cmd_enable_event(struct ltt_session *session, int domain, case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: #endif default: - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: + rcu_read_unlock(); return ret; } /* * Command LTTNG_ENABLE_ALL_EVENT processed by the client thread. */ -int cmd_enable_event_all(struct ltt_session *session, int domain, - char *channel_name, int event_type, int wpipe) +int cmd_enable_event_all(struct ltt_session *session, + struct lttng_domain *domain, char *channel_name, int event_type, + struct lttng_filter_bytecode *filter, int wpipe) { int ret; struct lttng_channel *attr; @@ -1137,7 +1273,9 @@ int cmd_enable_event_all(struct ltt_session *session, int domain, assert(session); assert(channel_name); - switch (domain) { + rcu_read_lock(); + + switch (domain->type) { case LTTNG_DOMAIN_KERNEL: { struct ltt_kernel_channel *kchan; @@ -1148,15 +1286,15 @@ int cmd_enable_event_all(struct ltt_session *session, int domain, session->kernel_session); if (kchan == NULL) { /* Create default channel */ - attr = channel_new_default_attr(domain); + attr = channel_new_default_attr(LTTNG_DOMAIN_KERNEL); if (attr == NULL) { - ret = LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } strncpy(attr->name, channel_name, sizeof(attr->name)); ret = cmd_enable_channel(session, domain, attr, wpipe); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { free(attr); goto error; } @@ -1170,29 +1308,30 @@ int cmd_enable_event_all(struct ltt_session *session, int domain, switch (event_type) { case LTTNG_EVENT_SYSCALL: - ret = event_kernel_enable_all_syscalls(session->kernel_session, - kchan, kernel_tracer_fd); + ret = event_kernel_enable_all_syscalls(kchan, kernel_tracer_fd); break; case LTTNG_EVENT_TRACEPOINT: /* * This call enables all LTTNG_KERNEL_TRACEPOINTS and * events already registered to the channel. */ - ret = event_kernel_enable_all_tracepoints(session->kernel_session, - kchan, kernel_tracer_fd); + ret = event_kernel_enable_all_tracepoints(kchan, kernel_tracer_fd); break; case LTTNG_EVENT_ALL: /* Enable syscalls and tracepoints */ - ret = event_kernel_enable_all(session->kernel_session, - kchan, kernel_tracer_fd); + ret = event_kernel_enable_all(kchan, kernel_tracer_fd); break; default: - ret = LTTCOMM_KERN_ENABLE_FAIL; + ret = LTTNG_ERR_KERN_ENABLE_FAIL; goto error; } /* Manage return value */ - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { + /* + * On error, cmd_enable_channel call will take care of destroying + * the created channel if it was needed. + */ goto error; } @@ -1211,15 +1350,15 @@ int cmd_enable_event_all(struct ltt_session *session, int domain, channel_name); if (uchan == NULL) { /* Create default channel */ - attr = channel_new_default_attr(domain); + attr = channel_new_default_attr(LTTNG_DOMAIN_UST); if (attr == NULL) { - ret = LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } strncpy(attr->name, channel_name, sizeof(attr->name)); ret = cmd_enable_channel(session, domain, attr, wpipe); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { free(attr); goto error; } @@ -1236,18 +1375,18 @@ int cmd_enable_event_all(struct ltt_session *session, int domain, switch (event_type) { case LTTNG_EVENT_ALL: case LTTNG_EVENT_TRACEPOINT: - ret = event_ust_enable_all_tracepoints(usess, domain, uchan); - if (ret != LTTCOMM_OK) { + ret = event_ust_enable_all_tracepoints(usess, uchan, filter); + if (ret != LTTNG_OK) { goto error; } break; default: - ret = LTTCOMM_UST_ENABLE_FAIL; + ret = LTTNG_ERR_UST_ENABLE_FAIL; goto error; } /* Manage return value */ - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto error; } @@ -1259,13 +1398,14 @@ int cmd_enable_event_all(struct ltt_session *session, int domain, case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: #endif default: - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: + rcu_read_unlock(); return ret; } @@ -1282,19 +1422,19 @@ ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events) case LTTNG_DOMAIN_KERNEL: nb_events = kernel_list_events(kernel_tracer_fd, events); if (nb_events < 0) { - ret = LTTCOMM_KERN_LIST_FAIL; + ret = LTTNG_ERR_KERN_LIST_FAIL; goto error; } break; case LTTNG_DOMAIN_UST: nb_events = ust_app_list_events(events); if (nb_events < 0) { - ret = LTTCOMM_UST_LIST_FAIL; + ret = LTTNG_ERR_UST_LIST_FAIL; goto error; } break; default: - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } @@ -1318,13 +1458,13 @@ ssize_t cmd_list_tracepoint_fields(int domain, case LTTNG_DOMAIN_UST: nb_fields = ust_app_list_event_fields(fields); if (nb_fields < 0) { - ret = LTTCOMM_UST_LIST_FAIL; + ret = LTTNG_ERR_UST_LIST_FAIL; goto error; } break; case LTTNG_DOMAIN_KERNEL: default: /* fall-through */ - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } @@ -1343,7 +1483,6 @@ int cmd_start_trace(struct ltt_session *session) int ret; struct ltt_kernel_session *ksession; struct ltt_ust_session *usess; - struct ltt_kernel_channel *kchan; assert(session); @@ -1353,68 +1492,18 @@ int cmd_start_trace(struct ltt_session *session) if (session->enabled) { /* Already started. */ - ret = LTTCOMM_TRACE_ALREADY_STARTED; + ret = LTTNG_ERR_TRACE_ALREADY_STARTED; goto error; } session->enabled = 1; - ret = setup_relayd(session); - if (ret != LTTCOMM_OK) { - ERR("Error setting up relayd for session %s", session->name); - goto error; - } - /* Kernel tracing */ if (ksession != NULL) { - /* Open kernel metadata */ - if (ksession->metadata == NULL) { - ret = kernel_open_metadata(ksession); - if (ret < 0) { - ret = LTTCOMM_KERN_META_FAIL; - goto error; - } - } - - /* Open kernel metadata stream */ - if (ksession->metadata_stream_fd < 0) { - ret = kernel_open_metadata_stream(ksession); - if (ret < 0) { - ERR("Kernel create metadata stream failed"); - ret = LTTCOMM_KERN_STREAM_FAIL; - goto error; - } - } - - /* For each channel */ - cds_list_for_each_entry(kchan, &ksession->channel_list.head, list) { - if (kchan->stream_count == 0) { - ret = kernel_open_channel_stream(kchan); - if (ret < 0) { - ret = LTTCOMM_KERN_STREAM_FAIL; - goto error; - } - /* Update the stream global counter */ - ksession->stream_count_global += ret; - } - } - - /* Setup kernel consumer socket and send fds to it */ - ret = init_kernel_tracing(ksession); - if (ret < 0) { - ret = LTTCOMM_KERN_START_FAIL; + ret = start_kernel_session(ksession, kernel_tracer_fd); + if (ret != LTTNG_OK) { goto error; } - - /* This start the kernel tracing */ - ret = kernel_start_session(ksession); - if (ret < 0) { - ret = LTTCOMM_KERN_START_FAIL; - goto error; - } - - /* Quiescent wait after starting trace */ - kernel_wait_quiescent(kernel_tracer_fd); } /* Flag session that trace should start automatically */ @@ -1423,12 +1512,14 @@ int cmd_start_trace(struct ltt_session *session) ret = ust_app_start_trace_all(usess); if (ret < 0) { - ret = LTTCOMM_UST_START_FAIL; + ret = LTTNG_ERR_UST_START_FAIL; goto error; } } - ret = LTTCOMM_OK; + session->started = 1; + + ret = LTTNG_OK; error: return ret; @@ -1451,7 +1542,7 @@ int cmd_stop_trace(struct ltt_session *session) usess = session->ust_session; if (!session->enabled) { - ret = LTTCOMM_TRACE_ALREADY_STOPPED; + ret = LTTNG_ERR_TRACE_ALREADY_STOPPED; goto error; } @@ -1479,11 +1570,13 @@ int cmd_stop_trace(struct ltt_session *session) ret = kernel_stop_session(ksession); if (ret < 0) { - ret = LTTCOMM_KERN_STOP_FAIL; + ret = LTTNG_ERR_KERN_STOP_FAIL; goto error; } kernel_wait_quiescent(kernel_tracer_fd); + + ksession->started = 0; } if (usess) { @@ -1491,12 +1584,14 @@ int cmd_stop_trace(struct ltt_session *session) ret = ust_app_stop_trace_all(usess); if (ret < 0) { - ret = LTTCOMM_UST_STOP_FAIL; + ret = LTTNG_ERR_UST_STOP_FAIL; goto error; } } - ret = LTTCOMM_OK; + session->started = 0; + + ret = LTTNG_OK; error: return ret; @@ -1519,12 +1614,7 @@ int cmd_set_consumer_uri(int domain, struct ltt_session *session, /* Can't enable consumer after session started. */ if (session->enabled) { - ret = LTTCOMM_TRACE_ALREADY_STARTED; - goto error; - } - - if (!session->start_consumer) { - ret = LTTCOMM_NO_CONSUMER; + ret = LTTNG_ERR_TRACE_ALREADY_STARTED; goto error; } @@ -1545,81 +1635,26 @@ int cmd_set_consumer_uri(int domain, struct ltt_session *session, case LTTNG_DOMAIN_KERNEL: /* Code flow error if we don't have a kernel session here. */ assert(ksess); - - /* Create consumer output if none exists */ - consumer = ksess->tmp_consumer; - if (consumer == NULL) { - consumer = consumer_copy_output(ksess->consumer); - if (consumer == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - /* Trash the consumer subdir, we are about to set a new one. */ - memset(consumer->subdir, 0, sizeof(consumer->subdir)); - ksess->tmp_consumer = consumer; - } - + assert(ksess->consumer); + consumer = ksess->consumer; break; case LTTNG_DOMAIN_UST: /* Code flow error if we don't have a kernel session here. */ assert(usess); - - /* Create consumer output if none exists */ - consumer = usess->tmp_consumer; - if (consumer == NULL) { - consumer = consumer_copy_output(usess->consumer); - if (consumer == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } - /* Trash the consumer subdir, we are about to set a new one. */ - memset(consumer->subdir, 0, sizeof(consumer->subdir)); - usess->tmp_consumer = consumer; - } - + assert(usess->consumer); + consumer = usess->consumer; break; } for (i = 0; i < nb_uri; i++) { - struct consumer_socket *socket; - struct lttng_ht_iter iter; - ret = add_uri_to_consumer(consumer, &uris[i], domain, session->name); - if (ret < 0) { + if (ret != LTTNG_OK) { goto error; } - - /* - * Don't send relayd socket if URI is NOT remote or if the relayd - * sockets for the session are already sent. - */ - if (uris[i].dtype == LTTNG_DST_PATH || - consumer->dst.net.relayd_socks_sent) { - continue; - } - - /* Try to send relayd URI to the consumer if exist. */ - rcu_read_lock(); - cds_lfht_for_each_entry(consumer->socks->ht, &iter.iter, - socket, node.node) { - - /* A socket in the HT should never have a negative fd */ - assert(socket->fd >= 0); - - pthread_mutex_lock(socket->lock); - ret = send_consumer_relayd_socket(domain, session, &uris[i], - consumer, socket->fd); - pthread_mutex_unlock(socket->lock); - if (ret != LTTCOMM_OK) { - rcu_read_unlock(); - goto error; - } - } - rcu_read_unlock(); } /* All good! */ - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: return ret; @@ -1632,11 +1667,16 @@ int cmd_create_session_uri(char *name, struct lttng_uri *uris, size_t nb_uri, lttng_sock_cred *creds) { int ret; - char *path = NULL; struct ltt_session *session; assert(name); + /* No URIs is not possible. */ + if (uris == NULL) { + ret = LTTNG_ERR_SESSION_FAIL; + goto session_error; + } + /* * Verify if the session already exist * @@ -1646,14 +1686,14 @@ int cmd_create_session_uri(char *name, struct lttng_uri *uris, */ session = session_find_by_name(name); if (session != NULL) { - ret = LTTCOMM_EXIST_SESS; + ret = LTTNG_ERR_EXIST_SESS; goto find_error; } /* Create tracing session in the registry */ - ret = session_create(name, path, LTTNG_SOCK_GET_UID_CRED(creds), + ret = session_create(name, LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds)); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto session_error; } @@ -1670,35 +1710,18 @@ int cmd_create_session_uri(char *name, struct lttng_uri *uris, /* Create default consumer output for the session not yet created. */ session->consumer = consumer_create_output(CONSUMER_DST_LOCAL); if (session->consumer == NULL) { - ret = LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto consumer_error; } - /* - * This means that the lttng_create_session call was called with the _path_ - * argument set to NULL. - */ - if (uris == NULL) { - /* - * At this point, we'll skip the consumer URI setup and create a - * session with a NULL path which will flag the session to NOT spawn a - * consumer. - */ - DBG("Create session %s with NO uri, skipping consumer setup", name); - goto end; - } - - session->start_consumer = 1; - ret = cmd_set_consumer_uri(0, session, nb_uri, uris); - if (ret != LTTCOMM_OK) { + if (ret != LTTNG_OK) { goto consumer_error; } session->consumer->enabled = 1; -end: - return LTTCOMM_OK; + return LTTNG_OK; consumer_error: session_destroy(session); @@ -1769,7 +1792,7 @@ int cmd_calibrate(int domain, struct lttng_calibrate *calibrate) kcalibrate.type = calibrate->type; ret = kernel_calibrate(kernel_tracer_fd, &kcalibrate); if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; + ret = LTTNG_ERR_KERN_ENABLE_FAIL; goto error; } break; @@ -1781,17 +1804,17 @@ int cmd_calibrate(int domain, struct lttng_calibrate *calibrate) ucalibrate.type = calibrate->type; ret = ust_app_calibrate_glb(&ucalibrate); if (ret < 0) { - ret = LTTCOMM_UST_CALIBRATE_FAIL; + ret = LTTNG_ERR_UST_CALIBRATE_FAIL; goto error; } break; } default: - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: return ret; @@ -1819,27 +1842,30 @@ int cmd_register_consumer(struct ltt_session *session, int domain, /* Can't register a consumer if there is already one */ if (ksess->consumer_fds_sent != 0) { - ret = LTTCOMM_KERN_CONSUMER_FAIL; + ret = LTTNG_ERR_KERN_CONSUMER_FAIL; goto error; } sock = lttcomm_connect_unix_sock(sock_path); if (sock < 0) { - ret = LTTCOMM_CONNECT_FAIL; + ret = LTTNG_ERR_CONNECT_FAIL; goto error; } socket = consumer_allocate_socket(sock); if (socket == NULL) { - ret = LTTCOMM_FATAL; - close(sock); + ret = close(sock); + if (ret < 0) { + PERROR("close register consumer"); + } + ret = LTTNG_ERR_FATAL; goto error; } socket->lock = zmalloc(sizeof(pthread_mutex_t)); if (socket->lock == NULL) { PERROR("zmalloc pthread mutex"); - ret = LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } pthread_mutex_init(socket->lock, NULL); @@ -1857,11 +1883,11 @@ int cmd_register_consumer(struct ltt_session *session, int domain, } default: /* TODO: Userspace tracing */ - ret = LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } - ret = LTTCOMM_OK; + ret = LTTNG_OK; error: return ret; @@ -1888,7 +1914,7 @@ ssize_t cmd_list_domains(struct ltt_session *session, *domains = zmalloc(nb_dom * sizeof(struct lttng_domain)); if (*domains == NULL) { - ret = -LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } @@ -1899,13 +1925,15 @@ ssize_t cmd_list_domains(struct ltt_session *session, if (session->ust_session != NULL) { (*domains)[index].type = LTTNG_DOMAIN_UST; + (*domains)[index].buf_type = session->ust_session->buffer_type; index++; } return nb_dom; error: - return ret; + /* Return negative value to differentiate return code */ + return -ret; } @@ -1924,6 +1952,9 @@ ssize_t cmd_list_channels(int domain, struct ltt_session *session, nb_chan = session->kernel_session->channel_count; } DBG3("Number of kernel channels %zd", nb_chan); + if (nb_chan <= 0) { + ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND; + } break; case LTTNG_DOMAIN_UST: if (session->ust_session != NULL) { @@ -1931,29 +1962,35 @@ ssize_t cmd_list_channels(int domain, struct ltt_session *session, session->ust_session->domain_global.channels); } DBG3("Number of UST global channels %zd", nb_chan); + if (nb_chan <= 0) { + ret = LTTNG_ERR_UST_CHAN_NOT_FOUND; + } break; default: *channels = NULL; - ret = -LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } if (nb_chan > 0) { *channels = zmalloc(nb_chan * sizeof(struct lttng_channel)); if (*channels == NULL) { - ret = -LTTCOMM_FATAL; + ret = LTTNG_ERR_FATAL; goto error; } list_lttng_channels(domain, session, *channels); } else { *channels = NULL; + /* Ret value was set in the domain switch case */ + goto error; } return nb_chan; error: - return ret; + /* Return negative value to differentiate return code */ + return -ret; } /* @@ -1981,14 +2018,15 @@ ssize_t cmd_list_events(int domain, struct ltt_session *session, break; } default: - ret = -LTTCOMM_UND; + ret = LTTNG_ERR_UND; goto error; } - ret = nb_event; + return nb_event; error: - return ret; + /* Return negative value to differentiate return code */ + return -ret; } /* @@ -2027,9 +2065,9 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, uid_t uid, (ksess && ksess->consumer->type == CONSUMER_DST_NET) || (usess && usess->consumer->type == CONSUMER_DST_NET)) { ret = build_network_session_path(sessions[i].path, - sizeof(session[i].path), session); + sizeof(sessions[i].path), session); } else { - ret = snprintf(sessions[i].path, sizeof(session[i].path), "%s", + ret = snprintf(sessions[i].path, sizeof(sessions[i].path), "%s", session->consumer->dst.trace_path); } if (ret < 0) { @@ -2045,269 +2083,41 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, uid_t uid, } /* - * Command LTTNG_DISABLE_CONSUMER processed by the client thread. - */ -int cmd_disable_consumer(int domain, struct ltt_session *session) -{ - int ret; - struct ltt_kernel_session *ksess = session->kernel_session; - struct ltt_ust_session *usess = session->ust_session; - struct consumer_output *consumer; - - assert(session); - - if (session->enabled) { - /* Can't disable consumer on an already started session */ - ret = LTTCOMM_TRACE_ALREADY_STARTED; - goto error; - } - - if (!session->start_consumer) { - ret = LTTCOMM_NO_CONSUMER; - goto error; - } - - switch (domain) { - case 0: - DBG("Disable tracing session %s consumer", session->name); - consumer = session->consumer; - break; - case LTTNG_DOMAIN_KERNEL: - /* Code flow error if we don't have a kernel session here. */ - assert(ksess); - - DBG("Disabling kernel consumer"); - consumer = ksess->consumer; - - break; - case LTTNG_DOMAIN_UST: - /* Code flow error if we don't have a UST session here. */ - assert(usess); - - DBG("Disabling UST consumer"); - consumer = usess->consumer; - - break; - default: - ret = LTTCOMM_UNKNOWN_DOMAIN; - goto error; - } - - if (consumer) { - consumer->enabled = 0; - /* Success at this point */ - ret = LTTCOMM_OK; - } else { - ret = LTTCOMM_NO_CONSUMER; - } - -error: - return ret; -} - -/* - * Command LTTNG_ENABLE_CONSUMER processed by the client thread. + * Command LTTNG_DATA_PENDING returning 0 if the data is NOT pending meaning + * ready for trace analysis (or anykind of reader) or else 1 for pending data. */ -int cmd_enable_consumer(int domain, struct ltt_session *session) +int cmd_data_pending(struct ltt_session *session) { int ret; struct ltt_kernel_session *ksess = session->kernel_session; struct ltt_ust_session *usess = session->ust_session; - struct consumer_output *consumer = NULL; assert(session); - /* Can't enable consumer after session started. */ + /* Session MUST be stopped to ask for data availability. */ if (session->enabled) { - ret = LTTCOMM_TRACE_ALREADY_STARTED; - goto error; - } - - if (!session->start_consumer) { - ret = LTTCOMM_NO_CONSUMER; + ret = LTTNG_ERR_SESSION_STARTED; goto error; } - switch (domain) { - case 0: - assert(session->consumer); - consumer = session->consumer; - break; - case LTTNG_DOMAIN_KERNEL: - /* Code flow error if we don't have a kernel session here. */ - assert(ksess); - - /* - * Check if we have already sent fds to the consumer. In that case, - * the enable-consumer command can't be used because a start trace - * had previously occured. - */ - if (ksess->consumer_fds_sent) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - goto error; - } - - consumer = ksess->tmp_consumer; - if (consumer == NULL) { - ret = LTTCOMM_OK; - /* No temp. consumer output exists. Using the current one. */ - DBG3("No temporary consumer. Using default"); - consumer = ksess->consumer; - goto error; - } - - switch (consumer->type) { - case CONSUMER_DST_LOCAL: - DBG2("Consumer output is local. Creating directory(ies)"); - - /* Create directory(ies) */ - ret = run_as_mkdir_recursive(consumer->dst.trace_path, - S_IRWXU | S_IRWXG, session->uid, session->gid); - if (ret < 0) { - if (ret != -EEXIST) { - ERR("Trace directory creation error"); - ret = LTTCOMM_FATAL; - goto error; - } - } - break; - case CONSUMER_DST_NET: - DBG2("Consumer output is network. Validating URIs"); - /* Validate if we have both control and data path set. */ - if (!consumer->dst.net.control_isset) { - ret = LTTCOMM_URL_CTRL_MISS; - goto error; - } - - if (!consumer->dst.net.data_isset) { - ret = LTTCOMM_URL_DATA_MISS; - goto error; - } - - /* Check established network session state */ - if (session->net_handle == 0) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - ERR("Session network handle is not set on enable-consumer"); - goto error; - } - - break; - } - - /* Append default kernel trace dir to subdir */ - strncat(ksess->consumer->subdir, DEFAULT_KERNEL_TRACE_DIR, - sizeof(ksess->consumer->subdir)); - - /* - * @session-lock - * This is race free for now since the session lock is acquired before - * ending up in this function. No other threads can access this kernel - * session without this lock hence freeing the consumer output object - * is valid. - */ - rcu_read_lock(); - consumer_destroy_output(ksess->consumer); - rcu_read_unlock(); - ksess->consumer = consumer; - ksess->tmp_consumer = NULL; - - break; - case LTTNG_DOMAIN_UST: - /* Code flow error if we don't have a UST session here. */ - assert(usess); - - /* - * Check if we have already sent fds to the consumer. In that case, - * the enable-consumer command can't be used because a start trace - * had previously occured. - */ - if (usess->start_trace) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; + if (ksess && ksess->consumer) { + ret = consumer_is_data_pending(ksess->id, ksess->consumer); + if (ret == 1) { + /* Data is still being extracted for the kernel. */ goto error; } + } - consumer = usess->tmp_consumer; - if (consumer == NULL) { - ret = LTTCOMM_OK; - /* No temp. consumer output exists. Using the current one. */ - DBG3("No temporary consumer. Using default"); - consumer = usess->consumer; + if (usess && usess->consumer) { + ret = consumer_is_data_pending(usess->id, usess->consumer); + if (ret == 1) { + /* Data is still being extracted for the kernel. */ goto error; } - - switch (consumer->type) { - case CONSUMER_DST_LOCAL: - DBG2("Consumer output is local. Creating directory(ies)"); - - /* Create directory(ies) */ - ret = run_as_mkdir_recursive(consumer->dst.trace_path, - S_IRWXU | S_IRWXG, session->uid, session->gid); - if (ret < 0) { - if (ret != -EEXIST) { - ERR("Trace directory creation error"); - ret = LTTCOMM_FATAL; - goto error; - } - } - break; - case CONSUMER_DST_NET: - DBG2("Consumer output is network. Validating URIs"); - /* Validate if we have both control and data path set. */ - if (!consumer->dst.net.control_isset) { - ret = LTTCOMM_URL_CTRL_MISS; - goto error; - } - - if (!consumer->dst.net.data_isset) { - ret = LTTCOMM_URL_DATA_MISS; - goto error; - } - - /* Check established network session state */ - if (session->net_handle == 0) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - DBG2("Session network handle is not set on enable-consumer"); - goto error; - } - - if (consumer->net_seq_index == -1) { - ret = LTTCOMM_ENABLE_CONSUMER_FAIL; - DBG2("Network index is not set on the consumer"); - goto error; - } - - break; - } - - /* Append default kernel trace dir to subdir */ - strncat(usess->consumer->subdir, DEFAULT_UST_TRACE_DIR, - sizeof(usess->consumer->subdir)); - - /* - * @session-lock - * This is race free for now since the session lock is acquired before - * ending up in this function. No other threads can access this kernel - * session without this lock hence freeing the consumer output object - * is valid. - */ - rcu_read_lock(); - consumer_destroy_output(usess->consumer); - rcu_read_unlock(); - usess->consumer = consumer; - usess->tmp_consumer = NULL; - - break; } - /* Enable it */ - if (consumer) { - consumer->enabled = 1; - /* Success at this point */ - ret = LTTCOMM_OK; - } else { - /* Should not really happend... */ - ret = LTTCOMM_NO_CONSUMER; - } + /* Data is ready to be read by a viewer */ + ret = 0; error: return ret; @@ -2319,10 +2129,12 @@ error: void cmd_init(void) { /* - * Set network sequence index to 1 for streams to match a relayd socket on - * the consumer side. + * Set network sequence index to 1 for streams to match a relayd + * socket on the consumer side. */ - uatomic_set(&relayd_net_seq_idx, 1); + pthread_mutex_lock(&relayd_net_seq_idx_lock); + relayd_net_seq_idx = 1; + pthread_mutex_unlock(&relayd_net_seq_idx_lock); DBG("Command subsystem initialized"); }