From 54d01ffb43587b221dc50ec42b6070fad89bd255 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Thu, 15 Sep 2011 19:24:23 -0400 Subject: [PATCH] Major code cleanup Cleanup main.c of the session daemon. The main switch case to handle client command is made more modular and clearer. Each command has a function associated with it beginning by 'cmd_*'. Also adds channel.c/.h and event.c/.h containing helper function to execute client commands. The reste of the modified code is simple cleanup. Some minor bugs were fixed also by this cleanup. All and for all, this makes easier to maintain the session daeamon code base. Signed-off-by: David Goulet --- ltt-sessiond/Makefile.am | 2 + ltt-sessiond/channel.c | 156 ++++ ltt-sessiond/channel.h | 32 + ltt-sessiond/context.c | 21 +- ltt-sessiond/context.h | 7 +- ltt-sessiond/event.c | 155 ++++ ltt-sessiond/event.h | 34 + ltt-sessiond/kernel-ctl.c | 16 +- ltt-sessiond/main.c | 1639 ++++++++++++++++++----------------- ltt-sessiond/session.c | 51 +- ltt-sessiond/session.h | 20 +- ltt-sessiond/trace-kernel.c | 2 + ltt-sessiond/utils.c | 15 + ltt-sessiond/utils.h | 12 +- tests/test_sessions.c | 37 +- 15 files changed, 1320 insertions(+), 879 deletions(-) create mode 100644 ltt-sessiond/channel.c create mode 100644 ltt-sessiond/channel.h create mode 100644 ltt-sessiond/event.c create mode 100644 ltt-sessiond/event.h diff --git a/ltt-sessiond/Makefile.am b/ltt-sessiond/Makefile.am index fad0cd576..6f27963c3 100644 --- a/ltt-sessiond/Makefile.am +++ b/ltt-sessiond/Makefile.am @@ -20,6 +20,8 @@ ltt_sessiond_SOURCES = utils.c utils.h \ ust-ctl.c ust-ctl.h \ kernel-ctl.c kernel-ctl.h \ context.c context.h \ + channel.c channel.h \ + event.c event.h \ futex.c futex.h \ shm.c shm.h \ session.c session.h \ diff --git a/ltt-sessiond/channel.c b/ltt-sessiond/channel.c new file mode 100644 index 000000000..ab9bf6c6d --- /dev/null +++ b/ltt-sessiond/channel.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; only version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include +#include +#include + +#include "channel.h" +#include "kernel-ctl.h" +#include "utils.h" + +/* + * Return allocated channel attributes. + */ +static struct lttng_channel *init_default_attr(int dom, char *name) +{ + struct lttng_channel *chan; + + chan = zmalloc(sizeof(struct lttng_channel)); + if (chan == NULL) { + perror("malloc channel init"); + goto error_alloc; + } + + if (snprintf(chan->name, sizeof(chan->name), "%s", name) < 0) { + perror("snprintf channel name"); + goto error; + } + + chan->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE; + chan->attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; + chan->attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; + + switch (dom) { + case LTTNG_DOMAIN_KERNEL: + chan->attr.subbuf_size = DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE; + chan->attr.num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM; + chan->attr.output = DEFAULT_KERNEL_CHANNEL_OUTPUT; + break; + /* TODO: add UST */ + default: + goto error; /* Not implemented */ + } + + return chan; + +error: + free(chan); +error_alloc: + return NULL; +} + +/* + * Disable kernel channel of the kernel session. + */ +int channel_kernel_disable(struct ltt_kernel_session *ksession, + char *channel_name) +{ + int ret; + struct ltt_kernel_channel *kchan; + + kchan = trace_kernel_get_channel_by_name(channel_name, ksession); + if (kchan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } else if (kchan->enabled == 1) { + ret = kernel_disable_channel(kchan); + if (ret < 0) { + if (ret != EEXIST) { + ret = LTTCOMM_KERN_CHAN_DISABLE_FAIL; + } + goto error; + } + } + + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Enable kernel channel of the kernel session. + */ +int channel_kernel_enable(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan) +{ + int ret; + + if (kchan->enabled == 0) { + ret = kernel_enable_channel(kchan); + if (ret < 0) { + ret = LTTCOMM_KERN_CHAN_ENABLE_FAIL; + goto error; + } + } + + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Create kernel channel of the kernel session and notify kernel thread. + */ +int channel_kernel_create(struct ltt_kernel_session *ksession, + char *channel_name, struct lttng_channel *chan, int kernel_pipe) +{ + int ret; + struct lttng_channel *attr = chan; + + /* Creating channel attributes if needed */ + if (attr == NULL) { + attr = init_default_attr(LTTNG_DOMAIN_KERNEL, channel_name); + if (attr == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + } + + /* Channel not found, creating it */ + ret = kernel_create_channel(ksession, attr, ksession->trace_path); + if (ret < 0) { + ret = LTTCOMM_KERN_CHAN_FAIL; + goto error; + } + + /* Notify kernel thread that there is a new channel */ + ret = notify_thread_pipe(kernel_pipe); + if (ret < 0) { + ret = LTTCOMM_FATAL; + goto error; + } + + ret = LTTCOMM_OK; + +error: + return ret; +} diff --git a/ltt-sessiond/channel.h b/ltt-sessiond/channel.h new file mode 100644 index 000000000..271721a97 --- /dev/null +++ b/ltt-sessiond/channel.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; only version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _LTT_CHANNEL_H +#define _LTT_CHANNEL_H + +#include + +#include "trace-kernel.h" + +int channel_kernel_disable(struct ltt_kernel_session *ksession, + char *channel_name); +int channel_kernel_enable(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan); +int channel_kernel_create(struct ltt_kernel_session *ksession, + char *channel_name, struct lttng_channel *chan, int kernel_pipe); + +#endif /* _LTT_CHANNEL_H */ diff --git a/ltt-sessiond/context.c b/ltt-sessiond/context.c index aebee0607..35cb50b7b 100644 --- a/ltt-sessiond/context.c +++ b/ltt-sessiond/context.c @@ -20,11 +20,11 @@ #include #include #include +#include #include -#include +#include -#include "lttngerr.h" #include "context.h" #include "kernel-ctl.h" @@ -151,15 +151,24 @@ error: /* * Add kernel context to tracer. */ -int add_kernel_context(struct ltt_kernel_session *ksession, - struct lttng_kernel_context *kctx, char *event_name, +int context_kernel_add(struct ltt_kernel_session *ksession, + struct lttng_event_context *ctx, char *event_name, char *channel_name) { int ret; struct ltt_kernel_channel *kchan; + struct lttng_kernel_context kctx; + + /* Setup kernel context structure */ + kctx.ctx = ctx->ctx; + kctx.u.perf_counter.type = ctx->u.perf_counter.type; + kctx.u.perf_counter.config = ctx->u.perf_counter.config; + strncpy(kctx.u.perf_counter.name, ctx->u.perf_counter.name, + LTTNG_SYMBOL_NAME_LEN); + kctx.u.perf_counter.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; if (strlen(channel_name) == 0) { - ret = add_kctx_all_channels(ksession, kctx, event_name); + ret = add_kctx_all_channels(ksession, &kctx, event_name); if (ret != LTTCOMM_OK) { goto error; } @@ -171,7 +180,7 @@ int add_kernel_context(struct ltt_kernel_session *ksession, goto error; } - ret = add_kctx_to_channel(kctx, kchan, event_name); + ret = add_kctx_to_channel(&kctx, kchan, event_name); if (ret != LTTCOMM_OK) { goto error; } diff --git a/ltt-sessiond/context.h b/ltt-sessiond/context.h index a3d82e0b7..38d39d94f 100644 --- a/ltt-sessiond/context.h +++ b/ltt-sessiond/context.h @@ -18,12 +18,11 @@ #ifndef _LTT_CONTEXT_H #define _LTT_CONTEXT_H -#include +#include #include "trace-kernel.h" -int add_kernel_context(struct ltt_kernel_session *ksession, - struct lttng_kernel_context *kctx, char *event_name, - char *channel_name); +int context_kernel_add(struct ltt_kernel_session *ksession, + struct lttng_event_context *ctx, char *event_name, char *channel_name); #endif /* _LTT_CONTEXT_H */ diff --git a/ltt-sessiond/event.c b/ltt-sessiond/event.c new file mode 100644 index 000000000..3e3ecd320 --- /dev/null +++ b/ltt-sessiond/event.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; only version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include +#include +#include + +#include "channel.h" +#include "event.h" +#include "kernel-ctl.h" + +/* + * Disable kernel event for a channel from the kernel session. + */ +int event_kernel_disable(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan, char *event_name) +{ + int ret; + struct ltt_kernel_event *kevent; + + kevent = trace_kernel_get_event_by_name(event_name, kchan); + if (kevent == NULL) { + ret = LTTCOMM_NO_EVENT; + goto error; + } + + ret = kernel_disable_event(kevent); + if (ret < 0) { + ret = LTTCOMM_KERN_DISABLE_FAIL; + goto error; + } + + DBG("Kernel event %s disable for channel %s.", + kevent->event->name, kchan->channel->name); + + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Disable all kernel event for a channel from the kernel session. + */ +int event_kernel_disable_all(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan) +{ + int ret; + struct ltt_kernel_event *kevent; + + /* For each event in the kernel session */ + cds_list_for_each_entry(kevent, &kchan->events_list.head, list) { + ret = kernel_disable_event(kevent); + if (ret < 0) { + /* We continue disabling the rest */ + continue; + } + } + + ret = LTTCOMM_OK; + + return ret; +} + +/* + * Enable kernel event for a channel from the kernel session. + */ +int event_kernel_enable(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan, struct lttng_event *event) +{ + int ret; + struct ltt_kernel_event *kevent; + + kevent = trace_kernel_get_event_by_name(event->name, kchan); + if (kevent == NULL) { + ret = kernel_create_event(event, kchan); + if (ret < 0) { + ret = LTTCOMM_KERN_ENABLE_FAIL; + goto error; + } + } else if (kevent->enabled == 0) { + ret = kernel_enable_event(kevent); + if (ret < 0) { + ret = LTTCOMM_KERN_ENABLE_FAIL; + goto error; + } + } + + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Enable all kernel event of a channel of the kernel session. + */ +int event_kernel_enable_all(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan, int kernel_tracer_fd) +{ + int size, i, ret; + struct ltt_kernel_event *kevent; + struct lttng_event *event_list; + + /* For each event in the kernel session */ + cds_list_for_each_entry(kevent, &kchan->events_list.head, list) { + ret = kernel_enable_event(kevent); + if (ret < 0) { + /* Enable failed but still continue */ + continue; + } + } + + size = kernel_list_events(kernel_tracer_fd, &event_list); + if (size < 0) { + ret = LTTCOMM_KERN_LIST_FAIL; + goto error; + } + + for (i = 0; i < size; i++) { + kevent = trace_kernel_get_event_by_name(event_list[i].name, kchan); + if (kevent == NULL) { + /* Default event type for enable all */ + event_list[i].type = LTTNG_EVENT_TRACEPOINT; + /* Enable each single tracepoint event */ + ret = kernel_create_event(&event_list[i], kchan); + if (ret < 0) { + /* Ignore error here and continue */ + } + } + } + + free(event_list); + + ret = LTTCOMM_OK; + +error: + return ret; +} diff --git a/ltt-sessiond/event.h b/ltt-sessiond/event.h new file mode 100644 index 000000000..3399466cf --- /dev/null +++ b/ltt-sessiond/event.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; only version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _LTT_EVENT_H +#define _LTT_EVENT_H + +#include + +#include "trace-kernel.h" + +int event_kernel_disable(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan, char *event_name); +int event_kernel_disable_all(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan); +int event_kernel_enable(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan, struct lttng_event *event); +int event_kernel_enable_all(struct ltt_kernel_session *ksession, + struct ltt_kernel_channel *kchan, int kernel_tracer_fd); + +#endif /* _LTT_EVENT_H */ diff --git a/ltt-sessiond/kernel-ctl.c b/ltt-sessiond/kernel-ctl.c index 3014620ba..b66f08cb3 100644 --- a/ltt-sessiond/kernel-ctl.c +++ b/ltt-sessiond/kernel-ctl.c @@ -250,9 +250,8 @@ int kernel_enable_channel(struct ltt_kernel_channel *chan) int ret; ret = kernctl_enable(chan->fd); - if (ret < 0) { - perror("enable chan ioctl"); - ret = errno; + if (ret < 0 && errno != EEXIST) { + perror("Enable kernel chan"); goto error; } @@ -273,11 +272,8 @@ int kernel_enable_event(struct ltt_kernel_event *event) int ret; ret = kernctl_enable(event->fd); - if (ret < 0) { - perror("enable event ioctl"); - if (errno == EEXIST) { - ret = -EEXIST; - } + if (ret < 0 && errno != EEXIST) { + perror("enable kernel event"); goto error; } @@ -298,8 +294,8 @@ int kernel_disable_event(struct ltt_kernel_event *event) int ret; ret = kernctl_disable(event->fd); - if (ret < 0) { - perror("disable event ioctl"); + if (ret < 0 && errno != EEXIST) { + perror("disable kernel event"); goto error; } diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index d2240d9dd..97569f6d1 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -2,19 +2,18 @@ * Copyright (C) 2011 - David Goulet * Mathieu Desnoyers * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; only version 2 - * of the License. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; only version 2 of the License. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. */ #define _GNU_SOURCE @@ -43,8 +42,10 @@ #include #include +#include "channel.h" #include "compat/poll.h" #include "context.h" +#include "event.h" #include "futex.h" #include "kernel-ctl.h" #include "ltt-sessiond.h" @@ -74,11 +75,15 @@ static pid_t ppid; /* Parent PID for --sig-parent option */ static pid_t kconsumerd_pid; static int dispatch_thread_exit; -static char apps_unix_sock_path[PATH_MAX]; /* Global application Unix socket path */ -static char client_unix_sock_path[PATH_MAX]; /* Global client Unix socket path */ -static char kconsumerd_err_unix_sock_path[PATH_MAX]; /* kconsumerd error Unix socket path */ -static char kconsumerd_cmd_unix_sock_path[PATH_MAX]; /* kconsumerd command Unix socket path */ -static char wait_shm_path[PATH_MAX]; /* global wait shm path for UST */ +/* Global application Unix socket path */ +static char apps_unix_sock_path[PATH_MAX]; +/* Global client Unix socket path */ +static char client_unix_sock_path[PATH_MAX]; +/* kconsumerd error and command Unix socket path */ +static char kconsumerd_err_unix_sock_path[PATH_MAX]; +static char kconsumerd_cmd_unix_sock_path[PATH_MAX]; +/* global wait shm path for UST */ +static char wait_shm_path[PATH_MAX]; /* Sockets and FDs */ static int client_sock; @@ -130,7 +135,7 @@ static struct ust_cmd_queue ust_cmd_queue; * MUST NOT be taken if you call a public function in session.c. * * The lock is nested inside the structure: session_list_ptr->lock. Please use - * lock_session_list and unlock_session_list for lock acquisition. + * session_lock_list and session_unlock_list for lock acquisition. */ static struct ltt_session_list *session_list_ptr; @@ -283,7 +288,7 @@ static void stop_threads(void) /* Stopping all threads */ DBG("Terminating all threads"); - ret = write(thread_quit_pipe[1], "!", 1); + ret = notify_thread_pipe(thread_quit_pipe[1]); if (ret < 0) { ERR("write error on thread quit pipe"); } @@ -331,7 +336,8 @@ static void cleanup(void) pthread_mutex_destroy(&session_list_ptr->lock); /* Cleanup ALL session */ - cds_list_for_each_entry_safe(sess, stmp, &session_list_ptr->head, list) { + cds_list_for_each_entry_safe(sess, stmp, + &session_list_ptr->head, list) { teardown_kernel_session(sess); // TODO complete session cleanup (including UST) } @@ -390,7 +396,8 @@ static void clean_command_ctx(struct command_ctx **cmd_ctx) /* * Send all stream fds of kernel channel to the consumer. */ -static int send_kconsumerd_channel_fds(int sock, struct ltt_kernel_channel *channel) +static int send_kconsumerd_channel_fds(int sock, + struct ltt_kernel_channel *channel) { int ret; size_t nb_fd; @@ -398,7 +405,8 @@ static int send_kconsumerd_channel_fds(int sock, struct ltt_kernel_channel *chan struct lttcomm_kconsumerd_header lkh; struct lttcomm_kconsumerd_msg lkm; - DBG("Sending fds of channel %s to kernel consumer", channel->channel->name); + DBG("Sending fds of channel %s to kernel consumer", + channel->channel->name); nb_fd = channel->stream_count; @@ -408,7 +416,8 @@ static int send_kconsumerd_channel_fds(int sock, struct ltt_kernel_channel *chan DBG("Sending kconsumerd header"); - ret = lttcomm_send_unix_sock(sock, &lkh, sizeof(struct lttcomm_kconsumerd_header)); + ret = lttcomm_send_unix_sock(sock, &lkh, + sizeof(struct lttcomm_kconsumerd_header)); if (ret < 0) { perror("send kconsumerd header"); goto error; @@ -425,7 +434,8 @@ static int send_kconsumerd_channel_fds(int sock, struct ltt_kernel_channel *chan DBG("Sending fd %d to kconsumerd", lkm.fd); - ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm)); + ret = lttcomm_send_fds_unix_sock(sock, &lkm, + &lkm.fd, 1, sizeof(lkm)); if (ret < 0) { perror("send kconsumerd fd"); goto error; @@ -457,7 +467,8 @@ static int send_kconsumerd_fds(struct ltt_kernel_session *session) DBG("Sending kconsumerd header for metadata"); - ret = lttcomm_send_unix_sock(session->consumer_fd, &lkh, sizeof(struct lttcomm_kconsumerd_header)); + ret = lttcomm_send_unix_sock(session->consumer_fd, &lkh, + sizeof(struct lttcomm_kconsumerd_header)); if (ret < 0) { perror("send kconsumerd header"); goto error; @@ -479,7 +490,8 @@ static int send_kconsumerd_fds(struct ltt_kernel_session *session) strncpy(lkm.path_name, session->metadata->pathname, PATH_MAX); lkm.path_name[PATH_MAX - 1] = '\0'; - ret = lttcomm_send_fds_unix_sock(session->consumer_fd, &lkm, &lkm.fd, 1, sizeof(lkm)); + ret = lttcomm_send_fds_unix_sock(session->consumer_fd, &lkm, + &lkm.fd, 1, sizeof(lkm)); if (ret < 0) { perror("send kconsumerd fd"); goto error; @@ -571,36 +583,37 @@ static int update_kernel_poll(struct lttng_poll_event *events) DBG("Updating kernel poll set"); - lock_session_list(); + session_lock_list(); cds_list_for_each_entry(session, &session_list_ptr->head, list) { - lock_session(session); + session_lock(session); if (session->kernel_session == NULL) { - unlock_session(session); + session_unlock(session); continue; } - cds_list_for_each_entry(channel, &session->kernel_session->channel_list.head, list) { + cds_list_for_each_entry(channel, + &session->kernel_session->channel_list.head, list) { /* Add channel fd to the kernel poll set */ ret = lttng_poll_add(events, channel->fd, LPOLLIN | LPOLLRDNORM); if (ret < 0) { - unlock_session(session); + session_unlock(session); goto error; } DBG("Channel fd %d added to kernel set", channel->fd); } - unlock_session(session); + session_unlock(session); } - unlock_session_list(); + session_unlock_list(); return 0; error: - unlock_session_list(); + session_unlock_list(); return -1; } /* - * Find the channel fd from 'fd' over all tracing session. When found, check + * Find the channel fd from 'fd' over all tracing session. When found, check * for new channel stream and send those stream fds to the kernel consumer. * * Useful for CPU hotplug feature. @@ -613,11 +626,11 @@ static int update_kernel_stream(int fd) DBG("Updating kernel streams for channel fd %d", fd); - lock_session_list(); + session_lock_list(); cds_list_for_each_entry(session, &session_list_ptr->head, list) { - lock_session(session); + session_lock(session); if (session->kernel_session == NULL) { - unlock_session(session); + session_unlock(session); continue; } @@ -650,14 +663,14 @@ static int update_kernel_stream(int fd) goto error; } } - unlock_session(session); + session_unlock(session); } - unlock_session_list(); + session_unlock_list(); return ret; error: - unlock_session(session); - unlock_session_list(); + session_unlock(session); + session_unlock_list(); return ret; } @@ -824,13 +837,15 @@ static void *thread_manage_kconsumerd(void *data) } /* Getting status code from kconsumerd */ - ret = lttcomm_recv_unix_sock(sock, &code, sizeof(enum lttcomm_return_code)); + ret = lttcomm_recv_unix_sock(sock, &code, + sizeof(enum lttcomm_return_code)); if (ret <= 0) { goto error; } if (code == KCONSUMERD_COMMAND_SOCK_READY) { - kconsumerd_cmd_sock = lttcomm_connect_unix_sock(kconsumerd_cmd_unix_sock_path); + kconsumerd_cmd_sock = + lttcomm_connect_unix_sock(kconsumerd_cmd_unix_sock_path); if (kconsumerd_cmd_sock < 0) { sem_post(&kconsumerd_sem); perror("kconsumerd connect"); @@ -845,7 +860,7 @@ static void *thread_manage_kconsumerd(void *data) goto error; } - /* Remove the kconsumerd error socket since we have established a connexion */ + /* Remove the kconsumerd error sock since we've established a connexion */ ret = lttng_poll_del(&events, kconsumerd_err_sock); if (ret < 0) { goto error; @@ -886,7 +901,8 @@ static void *thread_manage_kconsumerd(void *data) } /* Wait for any kconsumerd error */ - ret = lttcomm_recv_unix_sock(sock, &code, sizeof(enum lttcomm_return_code)); + ret = lttcomm_recv_unix_sock(sock, &code, + sizeof(enum lttcomm_return_code)); if (ret <= 0) { ERR("Kconsumerd closed the command socket"); goto error; @@ -970,7 +986,8 @@ static void *thread_manage_apps(void *data) } /* Register applicaton to the session daemon */ - ret = register_traceable_app(&ust_cmd.reg_msg, ust_cmd.sock); + ret = register_traceable_app(&ust_cmd.reg_msg, + ust_cmd.sock); if (ret < 0) { /* Only critical ENOMEM error can be returned here */ goto error; @@ -993,14 +1010,15 @@ static void *thread_manage_apps(void *data) goto error; } - DBG("Apps with sock %d added to poll set", ust_cmd.sock); + DBG("Apps with sock %d added to poll set", + ust_cmd.sock); } break; } } else { /* - * At this point, we know that a registered application made the - * event at poll_wait. + * At this point, we know that a registered application made + * the event at poll_wait. */ if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { /* Removing from the poll set */ @@ -1131,8 +1149,8 @@ static void *thread_registration_apps(void *data) ret = notify_ust_apps(1); if (ret < 0) { ERR("Failed to notify applications or create the wait shared memory.\n" - "Execution continues but there might be problem for already running\n" - "applications that wishes to register."); + "Execution continues but there might be problem for already\n" + "running applications that wishes to register."); } while (1) { @@ -1200,9 +1218,10 @@ static void *thread_registration_apps(void *data) ust_cmd->reg_msg.uid, ust_cmd->reg_msg.gid, ust_cmd->sock, ust_cmd->reg_msg.name, ust_cmd->reg_msg.major, ust_cmd->reg_msg.minor); + /* * Lock free enqueue the registration request. The red pill - * has been taken! This apps will be part of the *system* :) + * has been taken! This apps will be part of the *system*. */ cds_wfq_enqueue(&ust_cmd_queue.queue, &ust_cmd->node); @@ -1242,7 +1261,8 @@ static int spawn_kconsumerd_thread(void) /* Setup semaphore */ sem_init(&kconsumerd_sem, 0, 0); - ret = pthread_create(&kconsumerd_thread, NULL, thread_manage_kconsumerd, (void *) NULL); + ret = pthread_create(&kconsumerd_thread, NULL, + thread_manage_kconsumerd, (void *) NULL); if (ret != 0) { perror("pthread_create kconsumerd"); goto error; @@ -1306,7 +1326,8 @@ static pid_t spawn_kconsumerd(void) } else { verbosity = "--quiet"; } - execl(INSTALL_BIN_PATH "/ltt-kconsumerd", "ltt-kconsumerd", verbosity, NULL); + execl(INSTALL_BIN_PATH "/ltt-kconsumerd", + "ltt-kconsumerd", verbosity, NULL); if (errno != 0) { perror("kernel start consumer exec"); } @@ -1508,18 +1529,17 @@ error: } /* - * Start tracing by creating trace directory and sending FDs to the kernel - * consumer. + * Init tracing by creating trace directory and sending fds kernel consumer. */ -static int start_kernel_trace(struct ltt_kernel_session *session) +static int init_kernel_tracing(struct ltt_kernel_session *session) { int ret = 0; if (session->kconsumer_fds_sent == 0) { /* - * Assign default kernel consumer if no consumer assigned to the kernel - * session. At this point, it's NOT suppose to be 0 but this is an extra - * security check. + * Assign default kernel consumer socket if no consumer assigned to the + * kernel session. At this point, it's NOT suppose to be 0 but this is + * an extra security check. */ if (session->consumer_fd == 0) { session->consumer_fd = kconsumerd_cmd_sock; @@ -1527,7 +1547,6 @@ static int start_kernel_trace(struct ltt_kernel_session *session) ret = send_kconsumerd_fds(session); if (ret < 0) { - ERR("Send kconsumerd fds failed"); ret = LTTCOMM_KERN_CONSUMER_FAIL; goto error; } @@ -1539,63 +1558,6 @@ error: return ret; } -/* - * Notify kernel thread to update it's poll set. - */ -static int notify_kernel_channels_update(void) -{ - int ret; - - /* Inform kernel thread of the new kernel channel */ - ret = write(kernel_poll_pipe[1], "!", 1); - if (ret < 0) { - perror("write kernel poll pipe"); - } - - return ret; -} - -/* - * Allocate a channel structure and fill it. - */ -static struct lttng_channel *init_default_channel(enum lttng_domain_type domain_type, - char *name) -{ - struct lttng_channel *chan; - - chan = malloc(sizeof(struct lttng_channel)); - if (chan == NULL) { - perror("init channel malloc"); - goto error; - } - - if (snprintf(chan->name, NAME_MAX, "%s", name) < 0) { - perror("snprintf channel name"); - goto error; - } - - chan->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE; - chan->attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; - chan->attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; - - switch (domain_type) { - case LTTNG_DOMAIN_KERNEL: - chan->attr.subbuf_size = DEFAULT_KERNEL_CHANNEL_SUBBUF_SIZE; - chan->attr.num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM; - chan->attr.output = DEFAULT_KERNEL_CHANNEL_OUTPUT; - break; - /* TODO: add UST */ - default: - goto error; /* Not implemented */ - } - - return chan; - -error: - free(chan); - return NULL; -} - /* * Create an UST session and add it to the session ust list. */ @@ -1671,7 +1633,7 @@ error: * client for session listing. * * The session list lock MUST be acquired before calling this function. Use - * lock_session_list() and unlock_session_list(). + * session_lock_list() and session_unlock_list(). */ static void list_lttng_sessions(struct lttng_session *sessions) { @@ -1705,7 +1667,8 @@ static void list_lttng_channels(struct ltt_session *session, /* Kernel channels */ if (session->kernel_session != NULL) { - cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head, list) { + cds_list_for_each_entry(kchan, + &session->kernel_session->channel_list.head, list) { /* Copy lttng_channel struct to array */ memcpy(&channels[i], kchan->channel, sizeof(struct lttng_channel)); channels[i].enabled = kchan->enabled; @@ -1756,503 +1719,794 @@ static void list_lttng_events(struct ltt_kernel_channel *kchan, } /* - * Process the command requested by the lttng client within the command - * context structure. This function make sure that the return structure (llm) - * is set and ready for transmission before returning. - * - * Return any error encountered or 0 for success. + * Command LTTNG_DISABLE_CHANNEL processed by the client thread. */ -static int process_client_msg(struct command_ctx *cmd_ctx) +static int cmd_disable_channel(struct ltt_session *session, + int domain, char *channel_name) { - int ret = LTTCOMM_OK; - - DBG("Processing client command %d", cmd_ctx->lsm->cmd_type); - - /* - * Commands that DO NOT need a session. - */ - switch (cmd_ctx->lsm->cmd_type) { - case LTTNG_CREATE_SESSION: - case LTTNG_LIST_SESSIONS: - case LTTNG_LIST_TRACEPOINTS: - case LTTNG_CALIBRATE: - break; - default: - DBG("Getting session %s by name", cmd_ctx->lsm->session.name); - cmd_ctx->session = find_session_by_name(cmd_ctx->lsm->session.name); - if (cmd_ctx->session == NULL) { - /* If session name not found */ - if (cmd_ctx->lsm->session.name != NULL) { - ret = LTTCOMM_SESS_NOT_FOUND; - } else { /* If no session name specified */ - ret = LTTCOMM_SELECT_SESS; - } - goto error; - } else { - /* Acquire lock for the session */ - lock_session(cmd_ctx->session); - } - break; - } + int ret; - /* - * Check domain type for specific "pre-action". - */ - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - /* Kernel tracer check */ - if (kernel_tracer_fd == 0) { - init_kernel_tracer(); - if (kernel_tracer_fd == 0) { - ret = LTTCOMM_KERN_NA; + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + ret = channel_kernel_disable(session->kernel_session, + channel_name); + if (ret != LTTCOMM_OK) { goto error; } - } - /* Need a session for kernel command */ - switch (cmd_ctx->lsm->cmd_type) { - case LTTNG_CALIBRATE: - case LTTNG_CREATE_SESSION: - case LTTNG_LIST_SESSIONS: - case LTTNG_LIST_TRACEPOINTS: + + kernel_wait_quiescent(kernel_tracer_fd); break; default: - if (cmd_ctx->session->kernel_session == NULL) { - ret = create_kernel_session(cmd_ctx->session); - if (ret < 0) { - ret = LTTCOMM_KERN_SESS_FAIL; - goto error; - } - /* Start the kernel consumer daemon */ - if (kconsumerd_pid == 0 && - cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { - ret = start_kconsumerd(); - if (ret < 0) { - goto error; - } - } - } - } - break; - case LTTNG_DOMAIN_UST_PID: - break; - default: - break; + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } - /* Process by command type */ - switch (cmd_ctx->lsm->cmd_type) { - case LTTNG_ADD_CONTEXT: - { - struct lttng_kernel_context kctx; + ret = LTTCOMM_OK; - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } +error: + return ret; +} + +/* + * Command LTTNG_ENABLE_CHANNEL processed by the client thread. + */ +static int cmd_enable_channel(struct ltt_session *session, int domain, + char *channel_name, struct lttng_channel *attr) +{ + int ret; + struct ltt_kernel_channel *kchan; - switch (cmd_ctx->lsm->domain.type) { + switch (domain) { case LTTNG_DOMAIN_KERNEL: - /* Create Kernel context */ - kctx.ctx = cmd_ctx->lsm->u.context.ctx.ctx; - kctx.u.perf_counter.type = cmd_ctx->lsm->u.context.ctx.u.perf_counter.type; - kctx.u.perf_counter.config = cmd_ctx->lsm->u.context.ctx.u.perf_counter.config; - strncpy(kctx.u.perf_counter.name, - cmd_ctx->lsm->u.context.ctx.u.perf_counter.name, - LTTNG_SYMBOL_NAME_LEN); - kctx.u.perf_counter.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; - - /* Add kernel context to kernel tracer. See context.c */ - ret = add_kernel_context(cmd_ctx->session->kernel_session, &kctx, - cmd_ctx->lsm->u.context.event_name, - cmd_ctx->lsm->u.context.channel_name); + kchan = trace_kernel_get_channel_by_name(channel_name, + session->kernel_session); + if (kchan == NULL) { + ret = channel_kernel_create(session->kernel_session, + channel_name, attr, kernel_poll_pipe[1]); + } else { + ret = channel_kernel_enable(session->kernel_session, kchan); + } + if (ret != LTTCOMM_OK) { goto error; } + + kernel_wait_quiescent(kernel_tracer_fd); break; default: /* TODO: Userspace tracing */ ret = LTTCOMM_NOT_IMPLEMENTED; goto error; + } + + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Command LTTNG_DISABLE_EVENT processed by the client thread. + */ +static int cmd_disable_event(struct ltt_session *session, int domain, + char *channel_name, char *event_name) +{ + int ret; + struct ltt_kernel_channel *kchan; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + kchan = trace_kernel_get_channel_by_name(channel_name, + session->kernel_session); + if (kchan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; } - ret = LTTCOMM_OK; + ret = event_kernel_disable(session->kernel_session, kchan, event_name); + if (ret != LTTCOMM_OK) { + goto error; + } + + kernel_wait_quiescent(kernel_tracer_fd); break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } - case LTTNG_DISABLE_CHANNEL: - { - struct ltt_kernel_channel *kchan; - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Command LTTNG_DISABLE_ALL_EVENT processed by the client thread. + */ +static int cmd_disable_event_all(struct ltt_session *session, int domain, + char *channel_name) +{ + int ret; + struct ltt_kernel_channel *kchan; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + kchan = trace_kernel_get_channel_by_name(channel_name, + session->kernel_session); + if (kchan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; } - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - kchan = trace_kernel_get_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; - } else if (kchan->enabled == 1) { - ret = kernel_disable_channel(kchan); - if (ret < 0) { - if (ret != EEXIST) { - ret = LTTCOMM_KERN_CHAN_DISABLE_FAIL; - } - goto error; - } - } - kernel_wait_quiescent(kernel_tracer_fd); - break; - default: - /* TODO: Userspace tracing */ - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = event_kernel_disable_all(session->kernel_session, kchan); + if (ret != LTTCOMM_OK) { goto error; } - ret = LTTCOMM_OK; + kernel_wait_quiescent(kernel_tracer_fd); break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } - case LTTNG_DISABLE_EVENT: - { - struct ltt_kernel_channel *kchan; - struct ltt_kernel_event *kevent; - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } + ret = LTTCOMM_OK; - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - kchan = trace_kernel_get_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; - } +error: + return ret; +} - kevent = trace_kernel_get_event_by_name(cmd_ctx->lsm->u.disable.name, kchan); - if (kevent != NULL) { - DBG("Disabling kernel event %s for channel %s.", kevent->event->name, - kchan->channel->name); - ret = kernel_disable_event(kevent); - if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; - goto error; - } - } +/* + * Command LTTNG_ADD_CONTEXT processed by the client thread. + */ +static int cmd_add_context(struct ltt_session *session, int domain, + char *channel_name, char *event_name, struct lttng_event_context *ctx) +{ + int ret; - kernel_wait_quiescent(kernel_tracer_fd); - break; - default: - /* TODO: Userspace tracing */ - ret = LTTCOMM_NOT_IMPLEMENTED; + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + /* Add kernel context to kernel tracer */ + ret = context_kernel_add(session->kernel_session, ctx, + event_name, channel_name); + if (ret != LTTCOMM_OK) { goto error; } - ret = LTTCOMM_OK; break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } - case LTTNG_DISABLE_ALL_EVENT: - { - struct ltt_kernel_channel *kchan; - struct ltt_kernel_event *kevent; - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } + ret = LTTCOMM_OK; - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - DBG("Disabling all enabled kernel events"); - kchan = trace_kernel_get_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; +error: + return ret; +} + +/* + * Command LTTNG_ENABLE_EVENT processed by the client thread. + */ +static int cmd_enable_event(struct ltt_session *session, int domain, + char *channel_name, struct lttng_event *event) +{ + int ret; + struct ltt_kernel_channel *kchan; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + kchan = trace_kernel_get_channel_by_name(channel_name, + session->kernel_session); + if (kchan == NULL) { + /* This call will notify the kernel thread */ + ret = channel_kernel_create(session->kernel_session, channel_name, + NULL, kernel_poll_pipe[1]); + if (ret != LTTCOMM_OK) { goto error; } + } - /* For each event in the kernel session */ - cds_list_for_each_entry(kevent, &kchan->events_list.head, list) { - DBG("Disabling kernel event %s for channel %s.", - kevent->event->name, kchan->channel->name); - ret = kernel_disable_event(kevent); - if (ret < 0) { - continue; - } - } + /* Get the newly created kernel channel pointer */ + kchan = trace_kernel_get_channel_by_name(channel_name, + session->kernel_session); + if (kchan == NULL) { + /* This sould not happen... */ + ret = LTTCOMM_FATAL; + goto error; + } - /* Quiescent wait after event disable */ - kernel_wait_quiescent(kernel_tracer_fd); - break; - default: - /* TODO: Userspace tracing */ - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = event_kernel_enable(session->kernel_session, kchan, event); + if (ret != LTTCOMM_OK) { goto error; } - ret = LTTCOMM_OK; + kernel_wait_quiescent(kernel_tracer_fd); break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } - case LTTNG_ENABLE_CHANNEL: - { - struct ltt_kernel_channel *kchan; - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } + ret = LTTCOMM_OK; - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - kchan = trace_kernel_get_channel_by_name( - cmd_ctx->lsm->u.enable.channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - /* Channel not found, creating it */ - DBG("Creating kernel channel %s", - cmd_ctx->lsm->u.enable.channel_name); +error: + return ret; +} - ret = kernel_create_channel(cmd_ctx->session->kernel_session, - &cmd_ctx->lsm->u.channel.chan, - cmd_ctx->session->kernel_session->trace_path); - if (ret < 0) { - ret = LTTCOMM_KERN_CHAN_FAIL; - goto error; - } +/* + * Command LTTNG_ENABLE_ALL_EVENT processed by the client thread. + */ +static int cmd_enable_event_all(struct ltt_session *session, int domain, + char *channel_name) +{ + int ret; + struct ltt_kernel_channel *kchan; - /* Notify kernel thread that there is a new channel */ - ret = notify_kernel_channels_update(); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - } else if (kchan->enabled == 0) { - ret = kernel_enable_channel(kchan); - if (ret < 0) { - if (ret != EEXIST) { - ret = LTTCOMM_KERN_CHAN_ENABLE_FAIL; - } - goto error; - } + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + kchan = trace_kernel_get_channel_by_name(channel_name, + session->kernel_session); + if (kchan == NULL) { + /* This call will notify the kernel thread */ + ret = channel_kernel_create(session->kernel_session, channel_name, + NULL, kernel_poll_pipe[1]); + if (ret != LTTCOMM_OK) { + goto error; } + } - kernel_wait_quiescent(kernel_tracer_fd); - break; - case LTTNG_DOMAIN_UST_PID: + /* Get the newly created kernel channel pointer */ + kchan = trace_kernel_get_channel_by_name(channel_name, + session->kernel_session); + if (kchan == NULL) { + /* This sould not happen... */ + ret = LTTCOMM_FATAL; + goto error; + } - break; - default: - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = event_kernel_enable_all(session->kernel_session, + kchan, kernel_tracer_fd); + if (ret != LTTCOMM_OK) { goto error; } - ret = LTTCOMM_OK; + kernel_wait_quiescent(kernel_tracer_fd); break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } - case LTTNG_ENABLE_EVENT: - { - char *channel_name; - struct ltt_kernel_channel *kchan; - struct ltt_kernel_event *kevent; - struct lttng_channel *chan; - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Command LTTNG_LIST_TRACEPOINTS processed by the client thread. + */ +static ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events) +{ + int ret; + ssize_t nb_events = 0; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + nb_events = kernel_list_events(kernel_tracer_fd, events); + if (nb_events < 0) { + ret = LTTCOMM_KERN_LIST_FAIL; + goto error; } + break; + default: + /* TODO: Userspace listing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; + } - channel_name = cmd_ctx->lsm->u.enable.channel_name; + return nb_events; - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - kchan = trace_kernel_get_channel_by_name(channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - DBG("Channel not found. Creating channel %s", channel_name); +error: + /* Return negative value to differentiate return code */ + return -ret; +} - chan = init_default_channel(cmd_ctx->lsm->domain.type, channel_name); - if (chan == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } +/* + * Command LTTNG_START_TRACE processed by the client thread. + */ +static int cmd_start_trace(struct ltt_session *session) +{ + int ret; + struct ltt_kernel_channel *kchan; + struct ltt_kernel_session *ksession; - ret = kernel_create_channel(cmd_ctx->session->kernel_session, - chan, cmd_ctx->session->kernel_session->trace_path); - if (ret < 0) { - ret = LTTCOMM_KERN_CHAN_FAIL; - goto error; - } - kchan = trace_kernel_get_channel_by_name(channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - ERR("Channel %s not found after creation. Internal error, giving up.", - channel_name); - ret = LTTCOMM_FATAL; - goto error; - } + /* Short cut */ + ksession = session->kernel_session; - ret = notify_kernel_channels_update(); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } + /* Kernel tracing */ + if (ksession != NULL) { + /* Open kernel metadata */ + if (ksession->metadata == NULL) { + ret = kernel_open_metadata(ksession, ksession->trace_path); + if (ret < 0) { + ret = LTTCOMM_KERN_META_FAIL; + goto error; } + } - kevent = trace_kernel_get_event_by_name(cmd_ctx->lsm->u.enable.event.name, kchan); - if (kevent == NULL) { - DBG("Creating kernel event %s for channel %s.", - cmd_ctx->lsm->u.enable.event.name, channel_name); - ret = kernel_create_event(&cmd_ctx->lsm->u.enable.event, kchan); - } else { - DBG("Enabling kernel event %s for channel %s.", - kevent->event->name, channel_name); - ret = kernel_enable_event(kevent); - if (ret == -EEXIST) { - ret = LTTCOMM_KERN_EVENT_EXIST; + /* 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; + 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); + } + + /* TODO: Start all UST traces */ + + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Command LTTNG_STOP_TRACE processed by the client thread. + */ +static int cmd_stop_trace(struct ltt_session *session) +{ + int ret; + struct ltt_kernel_channel *kchan; + struct ltt_kernel_session *ksession; + + /* Short cut */ + ksession = session->kernel_session; + + /* Kernel tracer */ + if (ksession != NULL) { + DBG("Stop kernel tracing"); + + /* Flush all buffers before stopping */ + ret = kernel_metadata_flush_buffer(ksession->metadata_stream_fd); + if (ret < 0) { + ERR("Kernel metadata flush failed"); + } + cds_list_for_each_entry(kchan, &ksession->channel_list.head, list) { + ret = kernel_flush_buffer(kchan); if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; - goto error; + ERR("Kernel flush buffer error"); } + } - kernel_wait_quiescent(kernel_tracer_fd); - break; - default: - /* TODO: Userspace tracing */ - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = kernel_stop_session(ksession); + if (ret < 0) { + ret = LTTCOMM_KERN_STOP_FAIL; goto error; } - ret = LTTCOMM_OK; - break; + + kernel_wait_quiescent(kernel_tracer_fd); } - case LTTNG_ENABLE_ALL_EVENT: + + /* TODO : User-space tracer */ + + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Command LTTNG_CREATE_SESSION processed by the client thread. + */ +static int cmd_create_session(char *name, char *path) +{ + int ret; + + ret = session_create(name, path); + if (ret != LTTCOMM_OK) { + goto error; + } + + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Command LTTNG_DESTROY_SESSION processed by the client thread. + */ +static int cmd_destroy_session(struct ltt_session *session, char *name) +{ + int ret; + + /* Clean kernel session teardown */ + teardown_kernel_session(session); + + /* + * Must notify the kernel thread here to update it's poll setin order + * to remove the channel(s)' fd just destroyed. + */ + ret = notify_thread_pipe(kernel_poll_pipe[1]); + if (ret < 0) { + perror("write kernel poll pipe"); + } + + ret = session_destroy(name); + + return ret; +} + +/* + * Command LTTNG_CALIBRATE processed by the client thread. + */ +static int cmd_calibrate(int domain, struct lttng_calibrate *calibrate) +{ + int ret; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: { - int size, i; - char *channel_name; - struct ltt_kernel_channel *kchan; - struct ltt_kernel_event *kevent; - struct lttng_event *event_list; - struct lttng_channel *chan; + struct lttng_kernel_calibrate kcalibrate; - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); + kcalibrate.type = calibrate->type; + ret = kernel_calibrate(kernel_tracer_fd, &kcalibrate); if (ret < 0) { - goto setup_error; + ret = LTTCOMM_KERN_ENABLE_FAIL; + goto error; } + break; + } + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; + } - DBG("Enabling all kernel event"); + ret = LTTCOMM_OK; - channel_name = cmd_ctx->lsm->u.enable.channel_name; +error: + return ret; +} - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - kchan = trace_kernel_get_channel_by_name(channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - DBG("Channel not found. Creating channel %s", channel_name); +/* + * Command LTTNG_REGISTER_CONSUMER processed by the client thread. + */ +static int cmd_register_consumer(struct ltt_session *session, int domain, + char *sock_path) +{ + int ret, sock; - chan = init_default_channel(cmd_ctx->lsm->domain.type, channel_name); - if (chan == NULL) { - ret = LTTCOMM_FATAL; - goto error; - } + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + /* Can't register a consumer if there is already one */ + if (session->kernel_session->consumer_fd != 0) { + ret = LTTCOMM_KERN_CONSUMER_FAIL; + goto error; + } + + sock = lttcomm_connect_unix_sock(sock_path); + if (sock < 0) { + ret = LTTCOMM_CONNECT_FAIL; + goto error; + } + + session->kernel_session->consumer_fd = sock; + break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; + } + + ret = LTTCOMM_OK; + +error: + return ret; +} + +/* + * Command LTTNG_LIST_DOMAINS processed by the client thread. + */ +static ssize_t cmd_list_domains(struct ltt_session *session, + struct lttng_domain **domains) +{ + int ret; + ssize_t nb_dom = 0; + + if (session->kernel_session != NULL) { + nb_dom++; + } + + nb_dom += session->ust_session_list.count; + + *domains = malloc(nb_dom * sizeof(struct lttng_domain)); + if (*domains == NULL) { + ret = -LTTCOMM_FATAL; + goto error; + } + + (*domains)[0].type = LTTNG_DOMAIN_KERNEL; + + /* TODO: User-space tracer domain support */ + + return nb_dom; + +error: + return ret; +} + +/* + * Command LTTNG_LIST_CHANNELS processed by the client thread. + */ +static ssize_t cmd_list_channels(struct ltt_session *session, + struct lttng_channel **channels) +{ + int ret; + ssize_t nb_chan = 0; + + if (session->kernel_session != NULL) { + nb_chan += session->kernel_session->channel_count; + } + + *channels = malloc(nb_chan * sizeof(struct lttng_channel)); + if (*channels == NULL) { + ret = -LTTCOMM_FATAL; + goto error; + } + + list_lttng_channels(session, *channels); + + return nb_chan; + +error: + return ret; +} + +/* + * Command LTTNG_LIST_EVENTS processed by the client thread. + */ +static ssize_t cmd_list_events(struct ltt_session *session, + char *channel_name, struct lttng_event **events) +{ + int ret; + ssize_t nb_event = 0; + struct ltt_kernel_channel *kchan = NULL; + + if (session->kernel_session != NULL) { + kchan = trace_kernel_get_channel_by_name(channel_name, + session->kernel_session); + if (kchan == NULL) { + ret = -LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } + nb_event += kchan->event_count; + } + + *events = malloc(nb_event * sizeof(struct lttng_event)); + if (*events == NULL) { + ret = -LTTCOMM_FATAL; + goto error; + } + + list_lttng_events(kchan, *events); + + /* TODO: User-space tracer support */ + + return nb_event; + +error: + return ret; +} + +/* + * Process the command requested by the lttng client within the command + * context structure. This function make sure that the return structure (llm) + * is set and ready for transmission before returning. + * + * Return any error encountered or 0 for success. + */ +static int process_client_msg(struct command_ctx *cmd_ctx) +{ + int ret = LTTCOMM_OK; + int need_kernel_session = 1; + + DBG("Processing client command %d", cmd_ctx->lsm->cmd_type); + + /* + * Check for command that don't needs to allocate a returned payload. We do + * this here so we don't have to make the call for no payload" at each + * command. + */ + switch(cmd_ctx->lsm->cmd_type) { + case LTTNG_LIST_SESSIONS: + case LTTNG_LIST_TRACEPOINTS: + case LTTNG_LIST_DOMAINS: + case LTTNG_LIST_CHANNELS: + case LTTNG_LIST_EVENTS: + break; + default: + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + /* This label does not try to unlock the session */ + goto init_setup_error; + } + } + + /* Commands that DO NOT need a session. */ + switch (cmd_ctx->lsm->cmd_type) { + case LTTNG_CALIBRATE: + case LTTNG_CREATE_SESSION: + case LTTNG_LIST_SESSIONS: + case LTTNG_LIST_TRACEPOINTS: + need_kernel_session = 0; + break; + default: + DBG("Getting session %s by name", cmd_ctx->lsm->session.name); + cmd_ctx->session = session_find_by_name(cmd_ctx->lsm->session.name); + if (cmd_ctx->session == NULL) { + if (cmd_ctx->lsm->session.name != NULL) { + ret = LTTCOMM_SESS_NOT_FOUND; + } else { + /* If no session name specified */ + ret = LTTCOMM_SELECT_SESS; + } + goto error; + } else { + /* Acquire lock for the session */ + session_lock(cmd_ctx->session); + } + break; + } - ret = kernel_create_channel(cmd_ctx->session->kernel_session, - chan, cmd_ctx->session->kernel_session->trace_path); - if (ret < 0) { - ret = LTTCOMM_KERN_CHAN_FAIL; - goto error; - } - kchan = trace_kernel_get_channel_by_name(channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - ERR("Channel %s not found after creation. Internal error, giving up.", - channel_name); - ret = LTTCOMM_FATAL; - goto error; - } + /* + * Check domain type for specific "pre-action". + */ + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: + /* Kernel tracer check */ + if (kernel_tracer_fd == 0) { + /* Basically, load kernel tracer modules */ + init_kernel_tracer(); + if (kernel_tracer_fd == 0) { + ret = LTTCOMM_KERN_NA; + goto error; + } + } - ret = notify_kernel_channels_update(); + /* Need a session for kernel command */ + if (need_kernel_session) { + if (cmd_ctx->session->kernel_session == NULL) { + ret = create_kernel_session(cmd_ctx->session); if (ret < 0) { - ret = LTTCOMM_FATAL; + ret = LTTCOMM_KERN_SESS_FAIL; goto error; } } - /* For each event in the kernel session */ - cds_list_for_each_entry(kevent, &kchan->events_list.head, list) { - DBG("Enabling kernel event %s for channel %s.", - kevent->event->name, channel_name); - ret = kernel_enable_event(kevent); + /* Start the kernel consumer daemon */ + if (kconsumerd_pid == 0 && + cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { + ret = start_kconsumerd(); if (ret < 0) { - continue; - } - } - - size = kernel_list_events(kernel_tracer_fd, &event_list); - if (size < 0) { - ret = LTTCOMM_KERN_LIST_FAIL; - goto error; - } - - for (i = 0; i < size; i++) { - kevent = trace_kernel_get_event_by_name(event_list[i].name, kchan); - if (kevent == NULL) { - /* Default event type for enable all */ - event_list[i].type = LTTNG_EVENT_TRACEPOINT; - /* Enable each single tracepoint event */ - ret = kernel_create_event(&event_list[i], kchan); - if (ret < 0) { - /* Ignore error here and continue */ - } + ret = LTTCOMM_KERN_CONSUMER_FAIL; + goto error; } } - - free(event_list); - - /* Quiescent wait after event enable */ - kernel_wait_quiescent(kernel_tracer_fd); - break; - default: - /* TODO: Userspace tracing */ - ret = LTTCOMM_NOT_IMPLEMENTED; - goto error; } + break; + default: + /* TODO Userspace tracer */ + break; + } + /* Process by command type */ + switch (cmd_ctx->lsm->cmd_type) { + case LTTNG_ADD_CONTEXT: + { + ret = cmd_add_context(cmd_ctx->session, cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.context.channel_name, + cmd_ctx->lsm->u.context.event_name, + &cmd_ctx->lsm->u.context.ctx); + break; + } + case LTTNG_DISABLE_CHANNEL: + { + ret = cmd_disable_channel(cmd_ctx->session, cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.disable.channel_name); + break; + } + case LTTNG_DISABLE_EVENT: + { + ret = cmd_disable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.disable.channel_name, + cmd_ctx->lsm->u.disable.name); ret = LTTCOMM_OK; break; } + case LTTNG_DISABLE_ALL_EVENT: + { + DBG("Disabling all kernel event"); + + ret = cmd_disable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.disable.channel_name); + break; + } + case LTTNG_ENABLE_CHANNEL: + { + ret = cmd_enable_channel(cmd_ctx->session, cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.enable.channel_name, + &cmd_ctx->lsm->u.channel.chan); + break; + } + case LTTNG_ENABLE_EVENT: + { + ret = cmd_enable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.enable.channel_name, + &cmd_ctx->lsm->u.enable.event); + break; + } + case LTTNG_ENABLE_ALL_EVENT: + { + DBG("Enabling all kernel event"); + + ret = cmd_enable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.enable.channel_name); + break; + } case LTTNG_LIST_TRACEPOINTS: { struct lttng_event *events; - ssize_t nb_events = 0; + ssize_t nb_events; - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - DBG("Listing kernel events"); - nb_events = kernel_list_events(kernel_tracer_fd, &events); - if (nb_events < 0) { - ret = LTTCOMM_KERN_LIST_FAIL; - goto error; - } - break; - default: - /* TODO: Userspace listing */ - ret = LTTCOMM_NOT_IMPLEMENTED; - break; + nb_events = cmd_list_tracepoints(cmd_ctx->lsm->domain.type, &events); + if (nb_events < 0) { + ret = -nb_events; + goto error; } /* @@ -2276,358 +2530,144 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } case LTTNG_START_TRACE: { - struct ltt_kernel_channel *chan; - - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - - /* Kernel tracing */ - if (cmd_ctx->session->kernel_session != NULL) { - if (cmd_ctx->session->kernel_session->metadata == NULL) { - DBG("Open kernel metadata"); - ret = kernel_open_metadata(cmd_ctx->session->kernel_session, - cmd_ctx->session->kernel_session->trace_path); - if (ret < 0) { - ret = LTTCOMM_KERN_META_FAIL; - goto error; - } - } - - if (cmd_ctx->session->kernel_session->metadata_stream_fd == 0) { - DBG("Opening kernel metadata stream"); - if (cmd_ctx->session->kernel_session->metadata_stream_fd == 0) { - ret = kernel_open_metadata_stream(cmd_ctx->session->kernel_session); - if (ret < 0) { - ERR("Kernel create metadata stream failed"); - ret = LTTCOMM_KERN_STREAM_FAIL; - goto error; - } - } - } - - /* For each channel */ - cds_list_for_each_entry(chan, - &cmd_ctx->session->kernel_session->channel_list.head, list) { - if (chan->stream_count == 0) { - ret = kernel_open_channel_stream(chan); - if (ret < 0) { - ERR("Kernel create channel stream failed"); - ret = LTTCOMM_KERN_STREAM_FAIL; - goto error; - } - /* Update the stream global counter */ - cmd_ctx->session->kernel_session->stream_count_global += ret; - } - } - - ret = start_kernel_trace(cmd_ctx->session->kernel_session); - if (ret < 0) { - ret = LTTCOMM_KERN_START_FAIL; - goto error; - } - - DBG("Start kernel tracing"); - ret = kernel_start_session(cmd_ctx->session->kernel_session); - if (ret < 0) { - ERR("Kernel start session failed"); - ret = LTTCOMM_KERN_START_FAIL; - goto error; - } - - /* Quiescent wait after starting trace */ - kernel_wait_quiescent(kernel_tracer_fd); - } - - /* TODO: Start all UST traces */ - - ret = LTTCOMM_OK; + ret = cmd_start_trace(cmd_ctx->session); break; } case LTTNG_STOP_TRACE: { - struct ltt_kernel_channel *chan; - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - - /* Kernel tracer */ - if (cmd_ctx->session->kernel_session != NULL) { - DBG("Stop kernel tracing"); - - ret = kernel_metadata_flush_buffer(cmd_ctx->session->kernel_session->metadata_stream_fd); - if (ret < 0) { - ERR("Kernel metadata flush failed"); - } - - cds_list_for_each_entry(chan, &cmd_ctx->session->kernel_session->channel_list.head, list) { - ret = kernel_flush_buffer(chan); - if (ret < 0) { - ERR("Kernel flush buffer error"); - } - } - - ret = kernel_stop_session(cmd_ctx->session->kernel_session); - if (ret < 0) { - ERR("Kernel stop session failed"); - ret = LTTCOMM_KERN_STOP_FAIL; - goto error; - } - - /* Quiescent wait after stopping trace */ - kernel_wait_quiescent(kernel_tracer_fd); - } - - /* TODO : User-space tracer */ - - ret = LTTCOMM_OK; + ret = cmd_stop_trace(cmd_ctx->session); break; } case LTTNG_CREATE_SESSION: { - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - - ret = create_session(cmd_ctx->lsm->session.name, cmd_ctx->lsm->session.path); - if (ret < 0) { - if (ret == -EEXIST) { - ret = LTTCOMM_EXIST_SESS; - } else { - ret = LTTCOMM_FATAL; - } - goto error; - } - - ret = LTTCOMM_OK; + ret = cmd_create_session(cmd_ctx->lsm->session.name, + cmd_ctx->lsm->session.path); break; } case LTTNG_DESTROY_SESSION: { - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - - /* Clean kernel session teardown */ - teardown_kernel_session(cmd_ctx->session); - - ret = destroy_session(cmd_ctx->lsm->session.name); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - - /* - * Must notify the kernel thread here to update it's poll setin order - * to remove the channel(s)' fd just destroyed. - */ - ret = notify_kernel_channels_update(); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - - ret = LTTCOMM_OK; + ret = cmd_destroy_session(cmd_ctx->session, + cmd_ctx->lsm->session.name); break; } case LTTNG_LIST_DOMAINS: { - size_t nb_dom = 0; + ssize_t nb_dom; + struct lttng_domain *domains; - if (cmd_ctx->session->kernel_session != NULL) { - nb_dom++; + nb_dom = cmd_list_domains(cmd_ctx->session, &domains); + if (nb_dom < 0) { + ret = -nb_dom; + goto error; } - nb_dom += cmd_ctx->session->ust_session_list.count; - - ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_domain) * nb_dom); + ret = setup_lttng_msg(cmd_ctx, nb_dom * sizeof(struct lttng_domain)); if (ret < 0) { goto setup_error; } - ((struct lttng_domain *)(cmd_ctx->llm->payload))[0].type = - LTTNG_DOMAIN_KERNEL; + /* Copy event list into message payload */ + memcpy(cmd_ctx->llm->payload, domains, + nb_dom * sizeof(struct lttng_domain)); + + free(domains); - /* TODO: User-space tracer domain support */ ret = LTTCOMM_OK; break; } case LTTNG_LIST_CHANNELS: { - /* - * TODO: Only kernel channels are listed here. UST listing - * is needed on lttng-ust 2.0 release. - */ - size_t nb_chan = 0; - if (cmd_ctx->session->kernel_session != NULL) { - nb_chan += cmd_ctx->session->kernel_session->channel_count; + size_t nb_chan; + struct lttng_channel *channels; + + nb_chan = cmd_list_channels(cmd_ctx->session, &channels); + if (nb_chan < 0) { + ret = -nb_chan; + goto error; } - ret = setup_lttng_msg(cmd_ctx, - sizeof(struct lttng_channel) * nb_chan); + ret = setup_lttng_msg(cmd_ctx, nb_chan * sizeof(struct lttng_channel)); if (ret < 0) { goto setup_error; } - list_lttng_channels(cmd_ctx->session, - (struct lttng_channel *)(cmd_ctx->llm->payload)); + /* Copy event list into message payload */ + memcpy(cmd_ctx->llm->payload, channels, + nb_chan * sizeof(struct lttng_channel)); + + free(channels); ret = LTTCOMM_OK; break; } case LTTNG_LIST_EVENTS: { - /* - * TODO: Only kernel events are listed here. UST listing - * is needed on lttng-ust 2.0 release. - */ - size_t nb_event = 0; - struct ltt_kernel_channel *kchan = NULL; + size_t nb_event; + struct lttng_event *events; - if (cmd_ctx->session->kernel_session != NULL) { - kchan = trace_kernel_get_channel_by_name(cmd_ctx->lsm->u.list.channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; - } - nb_event += kchan->event_count; + nb_event = cmd_list_events(cmd_ctx->session, + cmd_ctx->lsm->u.list.channel_name, &events); + if (nb_event < 0) { + ret = -nb_event; + goto error; } - ret = setup_lttng_msg(cmd_ctx, - sizeof(struct lttng_event) * nb_event); + ret = setup_lttng_msg(cmd_ctx, nb_event * sizeof(struct lttng_event)); if (ret < 0) { goto setup_error; } - DBG("Listing events (%zu events)", nb_event); + /* Copy event list into message payload */ + memcpy(cmd_ctx->llm->payload, events, + nb_event * sizeof(struct lttng_event)); - list_lttng_events(kchan, - (struct lttng_event *)(cmd_ctx->llm->payload)); + free(events); ret = LTTCOMM_OK; break; } case LTTNG_LIST_SESSIONS: { - lock_session_list(); + session_lock_list(); if (session_list_ptr->count == 0) { ret = LTTCOMM_NO_SESSION; - unlock_session_list(); + session_unlock_list(); goto error; } ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_session) * session_list_ptr->count); if (ret < 0) { - unlock_session_list(); + session_unlock_list(); goto setup_error; } /* Filled the session array */ list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload)); - unlock_session_list(); + session_unlock_list(); ret = LTTCOMM_OK; break; } case LTTNG_CALIBRATE: { - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - { - struct lttng_kernel_calibrate kcalibrate; - - kcalibrate.type = cmd_ctx->lsm->u.calibrate.type; - ret = kernel_calibrate(kernel_tracer_fd, &kcalibrate); - if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; - goto error; - } - break; - } - default: - /* TODO: Userspace tracing */ - ret = LTTCOMM_NOT_IMPLEMENTED; - goto error; - } - ret = LTTCOMM_OK; + ret = cmd_calibrate(cmd_ctx->lsm->domain.type, + &cmd_ctx->lsm->u.calibrate); break; } case LTTNG_REGISTER_CONSUMER: { - int sock; - - /* Setup lttng message with no payload */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - - switch (cmd_ctx->lsm->domain.type) { - case LTTNG_DOMAIN_KERNEL: - { - /* Can't register a consumer if there is already one */ - if (cmd_ctx->session->kernel_session->consumer_fd != 0) { - ret = LTTCOMM_CONNECT_FAIL; - goto error; - } - - sock = lttcomm_connect_unix_sock(cmd_ctx->lsm->u.reg.path); - if (sock < 0) { - ret = LTTCOMM_CONNECT_FAIL; - goto error; - } - - cmd_ctx->session->kernel_session->consumer_fd = sock; - break; - } - default: - /* TODO: Userspace tracing */ - ret = LTTCOMM_NOT_IMPLEMENTED; - goto error; - } - - ret = LTTCOMM_OK; + ret = cmd_register_consumer(cmd_ctx->session, cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.reg.path); break; } - default: - /* Undefined command */ - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - ret = LTTCOMM_UND; break; } - /* Set return code */ - cmd_ctx->llm->ret_code = ret; - - if (cmd_ctx->session) { - unlock_session(cmd_ctx->session); - } - - return ret; - error: if (cmd_ctx->llm == NULL) { DBG("Missing llm structure. Allocating one."); @@ -2635,13 +2675,13 @@ error: goto setup_error; } } - /* Notify client of error */ + /* Set return code */ cmd_ctx->llm->ret_code = ret; - setup_error: if (cmd_ctx->session) { - unlock_session(cmd_ctx->session); + session_unlock(cmd_ctx->session); } +init_setup_error: return ret; } @@ -2775,10 +2815,10 @@ static void *thread_manage_clients(void *data) continue; } - DBG("Sending response (size: %d, retcode: %d)", - cmd_ctx->lttng_msg_size, cmd_ctx->llm->ret_code); - ret = send_unix_sock(sock, cmd_ctx->llm, - cmd_ctx->lttng_msg_size); + DBG("Sending response (size: %d, retcode: %s)", + cmd_ctx->lttng_msg_size, + lttng_get_readable_code(cmd_ctx->llm->ret_code)); + ret = send_unix_sock(sock, cmd_ctx->llm, cmd_ctx->lttng_msg_size); if (ret < 0) { ERR("Failed to send data back to client"); } @@ -2846,7 +2886,8 @@ static int parse_args(int argc, char **argv) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:E:C:Z", long_options, &option_index); + c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:E:C:Z", + long_options, &option_index); if (c == -1) { break; } @@ -2942,7 +2983,8 @@ static int init_daemon_socket(void) } /* File permission MUST be 666 */ - ret = chmod(apps_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + ret = chmod(apps_unix_sock_path, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (ret < 0) { ERR("Set file permissions failed: %s", apps_unix_sock_path); perror("chmod"); @@ -2955,8 +2997,8 @@ end: } /* - * Check if the global socket is available, and if a daemon is answering - * at the other side. If yes, error is returned. + * Check if the global socket is available, and if a daemon is answering at the + * other side. If yes, error is returned. */ static int check_existing_daemon(void) { @@ -2964,6 +3006,7 @@ static int check_existing_daemon(void) access(apps_unix_sock_path, F_OK) < 0) { return 0; } + /* Is there anybody out there ? */ if (lttng_session_daemon_alive()) { return -EEXIST; @@ -3068,11 +3111,13 @@ static int set_kconsumerd_sockets(void) int ret; if (strlen(kconsumerd_err_unix_sock_path) == 0) { - snprintf(kconsumerd_err_unix_sock_path, PATH_MAX, KCONSUMERD_ERR_SOCK_PATH); + snprintf(kconsumerd_err_unix_sock_path, PATH_MAX, + KCONSUMERD_ERR_SOCK_PATH); } if (strlen(kconsumerd_cmd_unix_sock_path) == 0) { - snprintf(kconsumerd_cmd_unix_sock_path, PATH_MAX, KCONSUMERD_CMD_SOCK_PATH); + snprintf(kconsumerd_cmd_unix_sock_path, PATH_MAX, + KCONSUMERD_CMD_SOCK_PATH); } ret = mkdir(KCONSUMERD_PATH, S_IRWXU | S_IRWXG); @@ -3085,7 +3130,8 @@ static int set_kconsumerd_sockets(void) } /* Create the kconsumerd error unix socket */ - kconsumerd_err_sock = lttcomm_create_unix_sock(kconsumerd_err_unix_sock_path); + kconsumerd_err_sock = + lttcomm_create_unix_sock(kconsumerd_err_unix_sock_path); if (kconsumerd_err_sock < 0) { ERR("Create unix sock failed: %s", kconsumerd_err_unix_sock_path); ret = -1; @@ -3093,7 +3139,8 @@ static int set_kconsumerd_sockets(void) } /* File permission MUST be 660 */ - ret = chmod(kconsumerd_err_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + ret = chmod(kconsumerd_err_unix_sock_path, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (ret < 0) { ERR("Set file permissions failed: %s", kconsumerd_err_unix_sock_path); perror("chmod"); @@ -3107,8 +3154,8 @@ error: /* * Signal handler for the daemon * - * Simply stop all worker threads, leaving main() return gracefully - * after joining all threads and calling cleanup(). + * Simply stop all worker threads, leaving main() return gracefully after + * joining all threads and calling cleanup(). */ static void sighandler(int sig) { @@ -3281,7 +3328,7 @@ int main(int argc, char **argv) goto error; } - /* After this point, we can safely call cleanup() so goto error is used */ + /* After this point, we can safely call cleanup() with "goto exit" */ /* * These actions must be executed as root. We do that *after* setting up @@ -3335,10 +3382,10 @@ int main(int argc, char **argv) cds_wfq_init(&ust_cmd_queue.queue); /* - * Get session list pointer. This pointer MUST NOT be free(). - * This list is statically declared in session.c + * Get session list pointer. This pointer MUST NOT be free(). This list is + * statically declared in session.c */ - session_list_ptr = get_session_list(); + session_list_ptr = session_get_list(); /* Set up max poll set size */ lttng_poll_set_max_size(); @@ -3368,14 +3415,16 @@ int main(int argc, char **argv) } /* Create thread to manage application socket */ - ret = pthread_create(&apps_thread, NULL, thread_manage_apps, (void *) NULL); + ret = pthread_create(&apps_thread, NULL, + thread_manage_apps, (void *) NULL); if (ret != 0) { perror("pthread_create apps"); goto exit_apps; } /* Create kernel thread to manage kernel event */ - ret = pthread_create(&kernel_thread, NULL, thread_manage_kernel, (void *) NULL); + ret = pthread_create(&kernel_thread, NULL, + thread_manage_kernel, (void *) NULL); if (ret != 0) { perror("pthread_create kernel"); goto exit_kernel; diff --git a/ltt-sessiond/session.c b/ltt-sessiond/session.c index 1ace823c7..aaca9f937 100644 --- a/ltt-sessiond/session.c +++ b/ltt-sessiond/session.c @@ -22,6 +22,7 @@ #include #include +#include #include #include "session.h" @@ -32,7 +33,7 @@ * No ltt_session.lock is taken here because those data structure are widely * spread across the lttng-tools code base so before caling functions below * that can read/write a session, the caller MUST acquire the session lock - * using lock_session() and unlock_session(). + * using session_lock() and session_unlock(). */ /* @@ -74,7 +75,7 @@ static void del_session_list(struct ltt_session *ls) /* * Return a pointer to the session list. */ -struct ltt_session_list *get_session_list(void) +struct ltt_session_list *session_get_list(void) { return <t_session_list; } @@ -82,7 +83,7 @@ struct ltt_session_list *get_session_list(void) /* * Acquire session list lock */ -void lock_session_list(void) +void session_lock_list(void) { pthread_mutex_lock(<t_session_list.lock); } @@ -90,7 +91,7 @@ void lock_session_list(void) /* * Release session list lock */ -void unlock_session_list(void) +void session_unlock_list(void) { pthread_mutex_unlock(<t_session_list.lock); } @@ -98,7 +99,7 @@ void unlock_session_list(void) /* * Acquire session lock */ -void lock_session(struct ltt_session *session) +void session_lock(struct ltt_session *session) { pthread_mutex_lock(&session->lock); } @@ -106,7 +107,7 @@ void lock_session(struct ltt_session *session) /* * Release session lock */ -void unlock_session(struct ltt_session *session) +void session_unlock(struct ltt_session *session) { pthread_mutex_unlock(&session->lock); } @@ -115,19 +116,19 @@ void unlock_session(struct ltt_session *session) * Return a ltt_session structure ptr that matches name. * If no session found, NULL is returned. */ -struct ltt_session *find_session_by_name(char *name) +struct ltt_session *session_find_by_name(char *name) { int found = 0; struct ltt_session *iter; - lock_session_list(); + session_lock_list(); cds_list_for_each_entry(iter, <t_session_list.head, list) { if (strncmp(iter->name, name, NAME_MAX) == 0) { found = 1; break; } } - unlock_session_list(); + session_unlock_list(); if (!found) { iter = NULL; @@ -141,12 +142,11 @@ struct ltt_session *find_session_by_name(char *name) * * Return -1 if no session is found. On success, return 1; */ -int destroy_session(char *name) +int session_destroy(char *name) { - int found = -1; struct ltt_session *iter, *tmp; - lock_session_list(); + session_lock_list(); cds_list_for_each_entry_safe(iter, tmp, <t_session_list.head, list) { if (strcmp(iter->name, name) == 0) { DBG("Destroying session %s", iter->name); @@ -155,26 +155,25 @@ int destroy_session(char *name) free(iter->path); pthread_mutex_destroy(&iter->lock); free(iter); - found = 1; break; } } - unlock_session_list(); + session_unlock_list(); - return found; + return LTTCOMM_OK; } /* * Create a brand new session and add it to the session list. */ -int create_session(char *name, char *path) +int session_create(char *name, char *path) { int ret; struct ltt_session *new_session; - new_session = find_session_by_name(name); + new_session = session_find_by_name(name); if (new_session != NULL) { - ret = -EEXIST; + ret = LTTCOMM_EXIST_SESS; goto error_exist; } @@ -182,31 +181,31 @@ int create_session(char *name, char *path) new_session = malloc(sizeof(struct ltt_session)); if (new_session == NULL) { perror("malloc"); - ret = -ENOMEM; + ret = LTTCOMM_FATAL; goto error_malloc; } /* Define session name */ if (name != NULL) { if (asprintf(&new_session->name, "%s", name) < 0) { - ret = -ENOMEM; + ret = LTTCOMM_FATAL; goto error_asprintf; } } else { ERR("No session name given"); - ret = -1; + ret = LTTCOMM_FATAL; goto error; } /* Define session system path */ if (path != NULL) { if (asprintf(&new_session->path, "%s", path) < 0) { - ret = -ENOMEM; + ret = LTTCOMM_FATAL; goto error_asprintf; } } else { ERR("No session path given"); - ret = -1; + ret = LTTCOMM_FATAL; goto error; } @@ -220,13 +219,13 @@ int create_session(char *name, char *path) pthread_mutex_init(&new_session->lock, NULL); /* Add new session to the session list */ - lock_session_list(); + session_lock_list(); add_session_list(new_session); - unlock_session_list(); + session_unlock_list(); DBG("Tracing session %s created in %s", name, path); - return 0; + return LTTCOMM_OK; error: error_asprintf: diff --git a/ltt-sessiond/session.h b/ltt-sessiond/session.h index fb271ea62..bbbbffc45 100644 --- a/ltt-sessiond/session.h +++ b/ltt-sessiond/session.h @@ -29,7 +29,7 @@ * Tracing session list * * Statically declared in session.c and can be accessed by using - * get_session_list() function that returns the pointer to the list. + * session_get_list() function that returns the pointer to the list. */ struct ltt_session_list { /* @@ -63,22 +63,22 @@ struct ltt_session { /* * Protect any read/write on this session data structure. This lock must be * acquired *before* using any public functions declared below. Use - * lock_session() and unlock_session() for that. + * session_lock() and session_unlock() for that. */ pthread_mutex_t lock; struct cds_list_head list; }; /* Prototypes */ -int create_session(char *name, char *path); -int destroy_session(char *name); +int session_create(char *name, char *path); +int session_destroy(char *name); -void lock_session(struct ltt_session *session); -void lock_session_list(void); -void unlock_session(struct ltt_session *session); -void unlock_session_list(void); +void session_lock(struct ltt_session *session); +void session_lock_list(void); +void session_unlock(struct ltt_session *session); +void session_unlock_list(void); -struct ltt_session *find_session_by_name(char *name); -struct ltt_session_list *get_session_list(void); +struct ltt_session *session_find_by_name(char *name); +struct ltt_session_list *session_get_list(void); #endif /* _LTT_SESSION_H */ diff --git a/ltt-sessiond/trace-kernel.c b/ltt-sessiond/trace-kernel.c index 113eebea8..57a9eb42d 100644 --- a/ltt-sessiond/trace-kernel.c +++ b/ltt-sessiond/trace-kernel.c @@ -39,6 +39,8 @@ struct ltt_kernel_channel *trace_kernel_get_channel_by_name( goto error; } + DBG("Trying to find channel %s", name); + cds_list_for_each_entry(chan, &session->channel_list.head, list) { if (strcmp(name, chan->channel->name) == 0) { DBG("Found channel by name %s", name); diff --git a/ltt-sessiond/utils.c b/ltt-sessiond/utils.c index 91972e9a8..429d25b3b 100644 --- a/ltt-sessiond/utils.c +++ b/ltt-sessiond/utils.c @@ -29,6 +29,21 @@ #include "utils.h" +/* + * Write to writable pipe used to notify a thread. + */ +int notify_thread_pipe(int wpipe) +{ + int ret; + + ret = write(wpipe, "!", 1); + if (ret < 0) { + perror("write poll pipe"); + } + + return ret; +} + /* * Return pointer to home directory path using the env variable HOME. * diff --git a/ltt-sessiond/utils.h b/ltt-sessiond/utils.h index 4da5f498e..449c3ef6b 100644 --- a/ltt-sessiond/utils.h +++ b/ltt-sessiond/utils.h @@ -1,9 +1,5 @@ -#ifndef _LTT_UTILS_H -#define _LTT_UTILS_H - /* * Copyright (C) 2011 - David Goulet - * Copyright (C) 2011 - Mathieu Desnoyers * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -19,13 +15,13 @@ * Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +#ifndef _LTT_UTILS_H +#define _LTT_UTILS_H -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(array) (sizeof(array) / (sizeof((array)[0]))) -#endif +#include int mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid); const char *get_home_dir(void); +int notify_thread_pipe(int wpipe); #endif /* _LTT_UTILS_H */ diff --git a/tests/test_sessions.c b/tests/test_sessions.c index f99d2a462..8ea365fed 100644 --- a/tests/test_sessions.c +++ b/tests/test_sessions.c @@ -25,6 +25,7 @@ #include #include +#include #include "ltt-sessiond/session.h" #include "utils.h" @@ -116,8 +117,8 @@ static int create_one_session(char *name, char *path) { int ret; - ret = create_session(name, path); - if (ret >= 0) { + ret = session_create(name, path); + if (ret == LTTCOMM_OK) { /* Validate */ ret = find_session_name(name); if (ret < 0) { @@ -128,8 +129,8 @@ static int create_one_session(char *name, char *path) /* Success */ return 0; } - } else if (ret < 0) { - if (ret == -EEXIST) { + } else { + if (ret == LTTCOMM_EXIST_SESS) { printf("(session already exists) "); } return -1; @@ -145,8 +146,9 @@ static int destroy_one_session(char *name) { int ret; - ret = destroy_session(name); - if (ret == 1) { + ret = session_destroy(name); + + if (ret == LTTCOMM_OK) { /* Validate */ ret = find_session_name(name); if (ret < 0) { @@ -156,11 +158,6 @@ static int destroy_one_session(char *name) /* Fail */ return -1; } - } else if (ret < 0) { - if (ret == -EEXIST) { - printf("(session already exists) "); - } - return -1; } return 0; @@ -171,19 +168,19 @@ static int fuzzing_create_args(void) int ret; ret = create_one_session(NULL, NULL); - if (ret >= 0) { + if (ret > 0) { printf("Session created with (null),(null)\n"); return -1; } ret = create_one_session(NULL, PATH1); - if (ret >= 0) { + if (ret > 0) { printf("Session created with (null), %s)\n", PATH1); return -1; } ret = create_one_session(SESSION1, NULL); - if (ret >= 0) { + if (ret > 0) { printf("Session created with %s, (null)\n", SESSION1); return -1; } @@ -199,13 +196,13 @@ static int fuzzing_destroy_args(void) int ret; ret = destroy_one_session(NULL); - if (ret >= 0) { + if (ret > 0) { printf("Session destroyed with (null)\n"); return -1; } ret = destroy_one_session(OVERFLOW_SESSION_NAME); - if (ret >= 0) { + if (ret > 0) { printf("Session destroyed with %s\n", OVERFLOW_SESSION_NAME); return -1; } @@ -250,7 +247,7 @@ int main(int argc, char **argv) printf("\nTesting Sessions:\n-----------\n"); - session_list = get_session_list(); + session_list = session_get_list(); if (session_list == NULL) { return -1; } @@ -263,7 +260,7 @@ int main(int argc, char **argv) PRINT_OK(); printf("Validating created session %s: ", SESSION1); - tmp = find_session_by_name(SESSION1); + tmp = session_find_by_name(SESSION1); if (tmp == NULL) { return -1; } @@ -272,8 +269,8 @@ int main(int argc, char **argv) assert(tmp->ust_session_list.count == 0); assert(strlen(tmp->path)); assert(strlen(tmp->name)); - lock_session(tmp); - unlock_session(tmp); + session_lock(tmp); + session_unlock(tmp); PRINT_OK(); -- 2.34.1