#include <lttng-consumerd.h>
#include <lttng-sessiond-comm.h>
#include <lttng/lttng-consumer.h>
+
#include <lttngerr.h>
#include "channel.h"
#include "context.h"
#include "event.h"
#include "futex.h"
+#include "hashtable.h"
#include "kernel-ctl.h"
#include "ltt-sessiond.h"
#include "shm.h"
#include "ust-app.h"
#include "ust-ctl.h"
#include "utils.h"
-#include "ust-ctl.h"
struct consumer_data {
enum lttng_consumer_type type;
for (i = ARRAY_SIZE(kernel_modules_list) - 1; i >= 0; i--) {
ret = snprintf(modprobe, sizeof(modprobe),
- "/sbin/modprobe --remove --quiet %s",
+ "/sbin/modprobe -r -q %s",
kernel_modules_list[i].name);
if (ret < 0) {
- perror("snprintf modprobe --remove");
+ perror("snprintf modprobe -r");
goto error;
}
modprobe[sizeof(modprobe) - 1] = '\0';
ret = system(modprobe);
if (ret == -1) {
- ERR("Unable to launch modprobe --remove for module %s",
+ ERR("Unable to launch modprobe -r for module %s",
kernel_modules_list[i].name);
} else if (kernel_modules_list[i].required
&& WEXITSTATUS(ret) != 0) {
}
}
+/*
+ * Complete teardown of all UST sessions. This will free everything on his path
+ * and destroy the core essence of all ust sessions :)
+ */
+static void teardown_ust_session(struct ltt_session *session)
+{
+ DBG("Tearing down UST session(s)");
+
+ trace_ust_destroy_session(session->ust_session);
+}
+
/*
* Stop all threads by closing the thread quit pipe.
*/
cds_list_for_each_entry_safe(sess, stmp,
&session_list_ptr->head, list) {
teardown_kernel_session(sess);
- // TODO complete session cleanup (including UST)
+ teardown_ust_session(sess);
+ free(sess);
}
}
/*
* Send all stream fds of kernel channel to the consumer.
*/
-static int send_consumer_channel_streams(struct consumer_data *consumer_data,
+static int send_kconsumer_channel_streams(struct consumer_data *consumer_data,
int sock, struct ltt_kernel_channel *channel)
{
int ret;
- size_t nb_fd;
struct ltt_kernel_stream *stream;
struct lttcomm_consumer_msg lkm;
DBG("Sending streams of channel %s to kernel consumer",
channel->channel->name);
- nb_fd = channel->stream_count;
/* Send channel */
lkm.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
lkm.u.channel.channel_key = channel->fd;
lkm.u.channel.max_sb_size = channel->channel->attr.subbuf_size;
lkm.u.channel.mmap_len = 0; /* for kernel */
- DBG("Sending channel %d to consumer", lkm.u.stream.stream_key);
+ DBG("Sending channel %d to consumer", lkm.u.channel.channel_key);
ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
if (ret < 0) {
perror("send consumer channel");
/*
* Send all stream fds of the kernel session to the consumer.
*/
-static int send_consumer_session_streams(struct consumer_data *consumer_data,
+static int send_kconsumer_session_streams(struct consumer_data *consumer_data,
struct ltt_kernel_session *session)
{
int ret;
DBG("Sending metadata stream fd");
- /* Extra protection. It's NOT suppose to be set to 0 at this point */
+ /* Extra protection. It's NOT supposed to be set to 0 at this point */
if (session->consumer_fd == 0) {
session->consumer_fd = consumer_data->cmd_sock;
}
}
cds_list_for_each_entry(chan, &session->channel_list.head, list) {
- ret = send_consumer_channel_streams(consumer_data, sock, chan);
+ ret = send_kconsumer_channel_streams(consumer_data, sock, chan);
if (ret < 0) {
goto error;
}
*
* Useful for CPU hotplug feature.
*/
-static int update_stream(struct consumer_data *consumer_data, int fd)
+static int update_kernel_stream(struct consumer_data *consumer_data, int fd)
{
int ret = 0;
struct ltt_session *session;
* stream fds.
*/
if (session->kernel_session->consumer_fds_sent == 1) {
- ret = send_consumer_channel_streams(consumer_data,
+ ret = send_kconsumer_channel_streams(consumer_data,
session->kernel_session->consumer_fd, channel);
if (ret < 0) {
goto error;
* kernel session and updating the kernel consumer
*/
if (revents & LPOLLIN) {
- ret = update_stream(&kconsumer_data, pollfd);
+ ret = update_kernel_stream(&kconsumer_data, pollfd);
if (ret < 0) {
continue;
}
lttcomm_connect_unix_sock(consumer_data->cmd_unix_sock_path);
if (consumer_data->cmd_sock < 0) {
sem_post(&consumer_data->sem);
- perror("consumer connect");
+ PERROR("consumer connect");
goto error;
}
/* Signal condition to tell that the kconsumerd is ready */
DBG("[thread] Manage application started");
+ rcu_register_thread();
+ rcu_thread_online();
+
ret = create_thread_poll_set(&events, 2);
if (ret < 0) {
goto error;
lttng_poll_clean(&events);
+ rcu_thread_offline();
+ rcu_unregister_thread();
return NULL;
}
/* Setting up the consumer_data pid */
consumer_data->pid = ret;
- DBG2("consumer pid %d", consumer_data->pid);
+ DBG2("Consumer pid %d", consumer_data->pid);
pthread_mutex_unlock(&consumer_data->pid_mutex);
DBG2("Spawning consumer control thread");
for (i = 0; i < ARRAY_SIZE(kernel_modules_list); i++) {
ret = snprintf(modprobe, sizeof(modprobe),
"/sbin/modprobe %s%s",
- kernel_modules_list[i].required ? "" : "--quiet ",
+ kernel_modules_list[i].required ? "" : "-q ",
kernel_modules_list[i].name);
if (ret < 0) {
perror("snprintf modprobe");
session->consumer_fd = kconsumer_data.cmd_sock;
}
- ret = send_consumer_session_streams(&kconsumer_data, session);
+ ret = send_kconsumer_session_streams(&kconsumer_data, session);
if (ret < 0) {
ret = LTTCOMM_KERN_CONSUMER_FAIL;
goto error;
struct lttng_domain *domain)
{
int ret;
+ unsigned int uid;
struct ltt_ust_session *lus = NULL;
- struct ust_app *app;
switch (domain->type) {
- case LTTNG_DOMAIN_UST_PID:
- app = ust_app_get_by_pid(domain->attr.pid);
- if (app == NULL) {
- ret = LTTCOMM_APP_NOT_FOUND;
- goto error;
- }
+ case LTTNG_DOMAIN_UST:
break;
default:
ret = LTTCOMM_UNKNOWN_DOMAIN;
DBG("Creating UST session");
- lus = trace_ust_create_session(session->path, domain->attr.pid, domain);
+ session_lock_list();
+ uid = session_list_ptr->count;
+ session_unlock_list();
+
+ lus = trace_ust_create_session(session->path, uid, domain);
if (lus == NULL) {
ret = LTTCOMM_UST_SESS_FAIL;
goto error;
}
- ret = mkdir_recursive(lus->path, S_IRWXU | S_IRWXG,
+ ret = mkdir_recursive(lus->pathname, S_IRWXU | S_IRWXG,
geteuid(), allowed_group());
if (ret < 0) {
if (ret != -EEXIST) {
}
}
- /* Create session on the UST tracer */
- ret = ustctl_create_session(app->sock, lus);
- if (ret < 0) {
- ret = LTTCOMM_UST_SESS_FAIL;
+ /* The domain type dictate different actions on session creation */
+ switch (domain->type) {
+ case LTTNG_DOMAIN_UST:
+ /* No ustctl for the global UST domain */
+ break;
+ default:
goto error;
}
-
- cds_list_add(&lus->list, &session->ust_session_list.head);
- session->ust_session_list.count++;
+ session->ust_session = lus;
return LTTCOMM_OK;
/*
* Copy channel from attributes and set it in the application channel list.
*/
+/*
static int copy_ust_channel_to_app(struct ltt_ust_session *usess,
struct lttng_channel *attr, struct ust_app *app)
{
int ret;
struct ltt_ust_channel *uchan, *new_chan;
- uchan = trace_ust_get_channel_by_name(attr->name, usess);
+ uchan = trace_ust_get_channel_by_key(usess->channels, attr->name);
if (uchan == NULL) {
ret = LTTCOMM_FATAL;
goto error;
goto error;
}
- /* Add channel to the ust app channel list */
- cds_list_add(&new_chan->list, &app->channels.head);
- app->channels.count++;
-
error:
return ret;
}
+*/
/*
* Command LTTNG_ENABLE_CHANNEL processed by the client thread.
struct lttng_domain *domain, struct lttng_channel *attr)
{
int ret;
+ struct ltt_ust_session *usess = session->ust_session;
+
+ DBG("Enabling channel %s for session %s", session->name, attr->name);
switch (domain->type) {
case LTTNG_DOMAIN_KERNEL:
kernel_wait_quiescent(kernel_tracer_fd);
break;
}
+ case LTTNG_DOMAIN_UST:
+ {
+ struct ltt_ust_channel *uchan;
+
+ DBG2("Enabling channel for LTTNG_DOMAIN_UST");
+
+ /* Get channel in global UST domain HT */
+ uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
+ attr->name);
+ if (uchan == NULL) {
+ uchan = trace_ust_create_channel(attr, usess->pathname);
+ if (uchan == NULL) {
+ ret = LTTCOMM_UST_CHAN_FAIL;
+ goto error;
+ }
+ rcu_read_lock();
+ hashtable_add_unique(usess->domain_global.channels, &uchan->node);
+ rcu_read_unlock();
+ DBG2("UST channel %s added to global domain HT", attr->name);
+ } else {
+ ret = LTTCOMM_UST_CHAN_EXIST;
+ goto error;
+ }
+
+ ret = ust_app_add_channel(usess, uchan);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+
+ break;
+ }
case LTTNG_DOMAIN_UST_PID:
{
+ /*
int sock;
struct ltt_ust_channel *uchan;
struct ltt_ust_session *usess;
DBG("UST channel %s created for app sock %d with pid %d",
attr->name, app->sock, domain->attr.pid);
- break;
+ */
+ ret = LTTCOMM_NOT_IMPLEMENTED;
+ goto error;
}
default:
ret = LTTCOMM_UNKNOWN_DOMAIN;
char *channel_name, char *event_name)
{
int ret;
- struct ltt_kernel_channel *kchan;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
+
kchan = trace_kernel_get_channel_by_name(channel_name,
session->kernel_session);
if (kchan == NULL) {
kernel_wait_quiescent(kernel_tracer_fd);
break;
+ }
+ case LTTNG_DOMAIN_UST:
+ case LTTNG_DOMAIN_UST_EXEC_NAME:
+ case LTTNG_DOMAIN_UST_PID:
+ case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
default:
- /* TODO: Userspace tracing */
+ /* TODO: Other UST domains */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
if (ret != LTTCOMM_OK) {
goto error;
}
+ break;
+ case LTTNG_DOMAIN_UST:
+ {
+ /*
+ struct ltt_ust_session *usess;
+ cds_list_for_each_entry(usess, &session->ust_session_list.head, list) {
+ ret = context_ust_add(usess, ctx,
+ event_name, channel_name, domain);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ }
break;
+ */
+ }
default:
- /* TODO: Userspace tracing */
+ /* TODO: UST other domains */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
char *channel_name, struct lttng_event *event)
{
int ret;
- struct ltt_kernel_channel *kchan;
struct lttng_channel *attr;
+ struct ltt_ust_session *usess = session->ust_session;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
+
kchan = trace_kernel_get_channel_by_name(channel_name,
session->kernel_session);
if (kchan == NULL) {
goto error;
}
- ret = event_kernel_enable_tracepoint(session->kernel_session, kchan, event);
+ ret = event_kernel_enable_tracepoint(session->kernel_session, kchan,
+ event);
if (ret != LTTCOMM_OK) {
goto error;
}
kernel_wait_quiescent(kernel_tracer_fd);
break;
+ }
+ case LTTNG_DOMAIN_UST:
+ {
+ struct ltt_ust_channel *uchan;
+ struct ltt_ust_event *uevent;
+
+ uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
+ channel_name);
+ if (uchan == NULL) {
+ /* TODO: Create default channel */
+ ret = LTTCOMM_UST_CHAN_NOT_FOUND;
+ goto error;
+ }
+
+ uevent = trace_ust_find_event_by_name(uchan->events, event->name);
+ if (uevent == NULL) {
+ uevent = trace_ust_create_event(event);
+ if (uevent == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+ }
+
+ ret = ust_app_add_event(usess, uchan, uevent);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_ENABLE_FAIL;
+ goto error;
+ }
+ break;
+ }
+ case LTTNG_DOMAIN_UST_EXEC_NAME:
+ case LTTNG_DOMAIN_UST_PID:
+ case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
default:
- /* TODO: Userspace tracing */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
static int cmd_start_trace(struct ltt_session *session)
{
int ret;
- struct ltt_kernel_channel *kchan;
struct ltt_kernel_session *ksession;
+ struct ltt_ust_session *usess = session->ust_session;
/* Short cut */
ksession = session->kernel_session;
/* Kernel tracing */
if (ksession != NULL) {
+ struct ltt_kernel_channel *kchan;
+
/* Open kernel metadata */
if (ksession->metadata == NULL) {
ret = kernel_open_metadata(ksession, ksession->trace_path);
kernel_wait_quiescent(kernel_tracer_fd);
}
- /* TODO: Start all UST traces */
+ ret = ust_app_start_trace(usess);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_START_FAIL;
+ goto error;
+ }
ret = LTTCOMM_OK;
int ret;
struct ltt_kernel_channel *kchan;
struct ltt_kernel_session *ksession;
+ //struct ltt_ust_session *usess;
+ //struct ltt_ust_channel *ustchan;
/* Short cut */
ksession = session->kernel_session;
kernel_wait_quiescent(kernel_tracer_fd);
}
- /* TODO : User-space tracer */
+#ifdef DISABLE
+ /* Stop each UST session */
+ DBG("Stop UST tracing");
+ cds_list_for_each_entry(usess, &session->ust_session_list.head, list) {
+ /* Flush all buffers before stopping */
+ ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj);
+ if (ret < 0) {
+ ERR("UST metadata flush failed");
+ }
+
+ cds_list_for_each_entry(ustchan, &usess->channels.head, list) {
+ ret = ustctl_flush_buffer(usess->sock, ustchan->obj);
+ if (ret < 0) {
+ ERR("UST flush buffer error");
+ }
+ }
+
+ ret = ustctl_stop_session(usess->sock, usess->handle);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_STOP_FAIL;
+ goto error;
+ }
+
+ ustctl_wait_quiescent(usess->sock);
+ }
+#endif
ret = LTTCOMM_OK;
nb_dom++;
}
- nb_dom += session->ust_session_list.count;
+ /* TODO: User-space tracer domain support */
*domains = malloc(nb_dom * sizeof(struct lttng_domain));
if (*domains == NULL) {
(*domains)[0].type = LTTNG_DOMAIN_KERNEL;
- /* TODO: User-space tracer domain support */
-
return nb_dom;
error:
list_lttng_channels(session, *channels);
+ /* TODO UST support */
+
return nb_chan;
error:
pthread_mutex_unlock(&kconsumer_data.pid_mutex);
}
break;
- case LTTNG_DOMAIN_UST_PID:
+ case LTTNG_DOMAIN_UST:
{
- struct ltt_ust_session *usess;
-
if (need_tracing_session) {
- usess = trace_ust_get_session_by_pid(
- &cmd_ctx->session->ust_session_list,
- cmd_ctx->lsm->domain.attr.pid);
- if (usess == NULL) {
+ if (cmd_ctx->session->ust_session == NULL) {
ret = create_ust_session(cmd_ctx->session,
&cmd_ctx->lsm->domain);
if (ret != LTTCOMM_OK) {
goto error;
}
}
+ /* Start the kernel consumer daemon */
+ pthread_mutex_lock(&ustconsumer_data.pid_mutex);
+ if (ustconsumer_data.pid == 0 &&
+ cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
+ pthread_mutex_unlock(&ustconsumer_data.pid_mutex);
+ ret = start_consumerd(&ustconsumer_data);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_CONSUMER_FAIL;
+ goto error;
+ }
+
+ cmd_ctx->session->ust_session->consumer_fd =
+ ustconsumer_data.cmd_sock;
+ }
+ pthread_mutex_unlock(&ustconsumer_data.pid_mutex);
}
break;
}
default:
- /* TODO Userspace tracer */
break;
}
}
case LTTNG_DISABLE_ALL_EVENT:
{
- DBG("Disabling all kernel event");
+ DBG("Disabling all events");
ret = cmd_disable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type,
cmd_ctx->lsm->u.disable.channel_name);
}
case LTTNG_ENABLE_ALL_EVENT:
{
- DBG("Enabling all kernel event");
+ DBG("Enabling all events");
ret = cmd_enable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type,
cmd_ctx->lsm->u.enable.channel_name,
DBG("[thread] Manage client started");
+ rcu_register_thread();
+
ret = lttcomm_listen_unix_sock(client_sock);
if (ret < 0) {
goto error;
// TODO: Validate cmd_ctx including sanity check for
// security purpose.
+ rcu_thread_online();
/*
* This function dispatch the work to the kernel or userspace tracer
* libs and fill the lttcomm_lttng_msg data structure of all the needed
* everything this function may needs.
*/
ret = process_client_msg(cmd_ctx);
+ rcu_thread_offline();
if (ret < 0) {
/*
* TODO: Inform client somehow of the fatal error. At
lttng_poll_clean(&events);
clean_command_ctx(&cmd_ctx);
+
+ rcu_unregister_thread();
return NULL;
}
void *status;
const char *home_path;
+ rcu_register_thread();
+
/* Create thread quit pipe */
if ((ret = init_thread_quit_pipe()) < 0) {
goto error;
if (ret < 0) {
goto exit;
}
+
ret = set_consumer_sockets(&ustconsumer_data);
if (ret < 0) {
goto exit;
/* Init UST command queue. */
cds_wfq_init(&ust_cmd_queue.queue);
+ /* Init UST app hash table */
+ ust_app_ht_alloc();
+
/*
* Get session list pointer. This pointer MUST NOT be free(). This list is
* statically declared in session.c
/*
* cleanup() is called when no other thread is running.
*/
+ rcu_thread_online();
cleanup();
+ rcu_thread_offline();
+ rcu_unregister_thread();
if (!ret)
exit(EXIT_SUCCESS);
error: