extern int lttng_kernel_start_tracing(void);
extern int lttng_kernel_stop_tracing(void);
extern int lttng_kernel_create_channel(void);
+extern int lttng_kernel_create_stream(void);
extern int lttng_kernel_open_metadata(void);
#endif /* _LIBLTTNGCTL_H */
return ask_sessiond(KERNEL_OPEN_METADATA, NULL);
}
+/*
+ * lttng_kernel_create_stream
+ *
+ * Create stream in the kernel tracer.
+ */
+int lttng_kernel_create_stream(void)
+{
+ return ask_sessiond(KERNEL_CREATE_STREAM, NULL);
+}
+
/*
* lttng_kernel_start_tracing
*
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_ENABLE_FAIL) ] = "Enable kernel event failed",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_DISABLE_FAIL) ] = "Disable kernel event failed",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_META_FAIL) ] = "Opening metadata failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_START_FAIL) ] = "Starting kernel trace failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_STOP_FAIL) ] = "Stoping kernel trace failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_CONSUMER_FAIL) ] = "Kernel consumer start failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_STREAM_FAIL) ] = "Kernel create stream failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_DIR_FAIL) ] = "Kernel trace directory creation failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_DIR_EXIST) ] = "Kernel trace directory already exist",
[ LTTCOMM_ERR_INDEX(KCONSUMERD_COMMAND_SOCK_READY) ] = "Kconsumerd command socket ready",
[ LTTCOMM_ERR_INDEX(KCONSUMERD_SUCCESS_RECV_FD) ] = "Kconsumerd success on receiving fds",
[ LTTCOMM_ERR_INDEX(KCONSUMERD_ERROR_RECV_FD) ] = "Kconsumerd error on receiving fds",
return ret;
}
+
+/*
+ * lttcomm_send_fds_unix_sock
+ *
+ * Send multiple fds on a unix socket.
+ */
+ssize_t lttcomm_send_fds_unix_sock(int sock, void *buf, int *fds, size_t nb_fd, size_t len)
+{
+ struct msghdr msg;
+ struct cmsghdr *cmptr;
+ struct iovec iov[1];
+ ssize_t ret = -1;
+ unsigned int sizeof_fds = nb_fd * sizeof(int);
+ char tmp[CMSG_SPACE(sizeof_fds)];
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_control = (caddr_t)tmp;
+ msg.msg_controllen = CMSG_LEN(sizeof_fds);
+
+ cmptr = CMSG_FIRSTHDR(&msg);
+ cmptr->cmsg_len = CMSG_LEN(sizeof_fds);
+ cmptr->cmsg_level = SOL_SOCKET;
+ cmptr->cmsg_type = SCM_RIGHTS;
+ memcpy(CMSG_DATA(cmptr), fds, sizeof_fds);
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = len;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+ ret = sendmsg(sock, &msg, 0);
+ if (ret < 0) {
+ perror("sendmsg");
+ }
+
+ return ret;
+}
enum lttcomm_sessiond_command {
KERNEL_CREATE_CHANNEL,
KERNEL_CREATE_SESSION,
+ KERNEL_CREATE_STREAM,
KERNEL_DISABLE_EVENT,
KERNEL_ENABLE_EVENT,
KERNEL_OPEN_METADATA,
LTTCOMM_KERN_ENABLE_FAIL, /* Kernel enable event failed */
LTTCOMM_KERN_DISABLE_FAIL, /* Kernel disable event failed */
LTTCOMM_KERN_META_FAIL, /* Kernel open metadata failed */
+ LTTCOMM_KERN_START_FAIL, /* Kernel start trace failed */
+ LTTCOMM_KERN_STOP_FAIL, /* Kernel stop trace failed */
+ LTTCOMM_KERN_CONSUMER_FAIL, /* Kernel consumer start failed */
+ LTTCOMM_KERN_STREAM_FAIL, /* Kernel create stream failed */
+ LTTCOMM_KERN_DIR_FAIL, /* Kernel trace directory creation failed */
+ LTTCOMM_KERN_DIR_EXIST, /* Kernel traec directory exist */
KCONSUMERD_COMMAND_SOCK_READY, /* when kconsumerd command socket ready */
KCONSUMERD_SUCCESS_RECV_FD, /* success on receiving fds */
KCONSUMERD_ERROR_RECV_FD, /* error on receiving fds */
extern int lttcomm_accept_unix_sock(int sock);
extern int lttcomm_listen_unix_sock(int sock);
extern int lttcomm_close_unix_sock(int sock);
+extern ssize_t lttcomm_send_fds_unix_sock(int sock, void *buf, int *fds, size_t nb_fd, size_t len);
extern ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len);
extern ssize_t lttcomm_send_unix_sock(int sock, void *buf, size_t len);
extern const char *lttcomm_get_readable_code(enum lttcomm_return_code code);
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#define _GNU_SOURCE
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
+#include "lttngerr.h"
#include "ltt-sessiond.h"
#include "libkernelctl.h"
#include "kernel-ctl.h"
*
* Create a new kernel session using the command context session.
*/
-int kernel_create_session(struct command_ctx *cmd_ctx, int tracer_fd)
+int kernel_create_session(struct ltt_session *session, int tracer_fd)
{
int ret;
struct ltt_kernel_session *lks;
/* Assigning session fd and to the command context */
lks->fd = ret;
- cmd_ctx->session->kernel_session = lks;
- cmd_ctx->session->kern_session_count++;
+ lks->channel_count = 0;
+ lks->stream_count_global = 0;
+ session->kernel_session = lks;
+ session->kern_session_count++;
+ CDS_INIT_LIST_HEAD(&lks->channel_list.head);
+
+ DBG("Kernel session created (fd: %d)", lks->fd);
return 0;
*
* Create a kernel channel within the kernel session.
*/
-int kernel_create_channel(struct command_ctx *cmd_ctx)
+int kernel_create_channel(struct ltt_kernel_session *session)
{
int ret;
struct ltt_kernel_channel *lkc;
chan->switch_timer_interval = DEFAULT_KERNEL_SWITCH_TIMER;
chan->read_timer_interval = DEFAULT_KERNEL_READ_TIMER;
- ret = kernctl_create_channel(cmd_ctx->session->kernel_session->fd, chan);
+ ret = kernctl_create_channel(session->fd, chan);
if (ret < 0) {
perror("ioctl create channel");
goto error;
}
+ /* Setup the channel */
lkc->fd = ret;
lkc->channel = chan;
+ lkc->stream_count = 0;
+ ret = asprintf(&lkc->pathname, "%s", DEFAULT_TRACE_OUTPUT);
+ if (ret < 0) {
+ perror("asprintf kernel create channel");
+ goto error;
+ }
+
+ DBG("Channel path set to %s", lkc->pathname);
+
CDS_INIT_LIST_HEAD(&lkc->events_list.head);
+ CDS_INIT_LIST_HEAD(&lkc->stream_list.head);
+ cds_list_add(&lkc->list, &session->channel_list.head);
+ session->channel_count++;
- cmd_ctx->session->kernel_session->channel = lkc;
+ DBG("Kernel channel created (fd: %d)", lkc->fd);
return 0;
*
* Enable kernel event.
*/
-int kernel_enable_event(struct ltt_kernel_channel *channel, char *name)
+int kernel_enable_event(struct ltt_kernel_session *session, char *name)
{
int ret;
+ struct ltt_kernel_channel *chan;
struct ltt_kernel_event *event;
struct lttng_kernel_event *lke;
lke->instrumentation = LTTNG_KERNEL_TRACEPOINTS;
event->event = lke;
- ret = kernctl_create_event(channel->fd, lke);
- if (ret < 0) {
- goto error;
- }
+ cds_list_for_each_entry(chan, &session->channel_list.head, list) {
+ ret = kernctl_create_event(chan->fd, lke);
+ if (ret < 0) {
+ goto error;
+ }
- /* Add event to event list */
- cds_list_add(&event->list, &channel->events_list.head);
+ event->fd = ret;
+ /* Add event to event list */
+ cds_list_add(&event->list, &chan->events_list.head);
+ DBG("Event %s enabled (fd: %d)", name, event->fd);
+ }
return 0;
goto error;
}
+ lkm->fd = ret;
+ lkm->conf = conf;
+ ret = asprintf(&lkm->pathname, "%s/metadata", DEFAULT_TRACE_OUTPUT);
+ if (ret < 0) {
+ perror("asprintf kernel metadata");
+ goto error;
+ }
session->metadata = lkm;
- session->metadata->fd = ret;
- session->metadata->conf = conf;
+
+ DBG("Kernel metadata opened (fd: %d)", lkm->fd);
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * kernel_start_session
+ *
+ * Start tracing session.
+ */
+int kernel_start_session(struct ltt_kernel_session *session)
+{
+ int ret;
+
+ ret = kernctl_start_session(session->fd);
+ if (ret < 0) {
+ goto error;
+ }
+
+ DBG("Kernel session started");
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * kernel_stop_session
+ *
+ * Stop tracing session.
+ */
+int kernel_stop_session(struct ltt_kernel_session *session)
+{
+ int ret;
+
+ ret = kernctl_stop_session(session->fd);
+ if (ret < 0) {
+ goto error;
+ }
+
+ DBG("Kernel session stopped");
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * kernel_create_channel_stream
+ *
+ * Create a stream for a channel.
+ *
+ * Return the number of created stream. Else, a negative value.
+ */
+int kernel_create_channel_stream(struct ltt_kernel_channel *channel)
+{
+ int ret;
+ struct ltt_kernel_stream *lks;
+
+ while ((ret = kernctl_create_stream(channel->fd)) > 0) {
+ lks = malloc(sizeof(struct ltt_kernel_stream));
+ if (lks == NULL) {
+ perror("kernel create stream malloc");
+ ret = -errno;
+ goto error;
+ }
+
+ lks->fd = ret;
+ ret = asprintf(&lks->pathname, "%s/trace_%d",
+ channel->pathname, channel->stream_count);
+ if (ret < 0) {
+ perror("asprintf kernel create stream");
+ goto error;
+ }
+ lks->state = 0;
+
+ cds_list_add(&lks->list, &channel->stream_list.head);
+ channel->stream_count++;
+ }
+
+ DBG("Kernel channel stream created (num: %d)", channel->stream_count);
+
+ return channel->stream_count;
+
+error:
+ return ret;
+}
+
+/*
+ * kernel_create_metadata_stream
+ *
+ * Create the metadata stream.
+ */
+int kernel_create_metadata_stream(struct ltt_kernel_session *session)
+{
+ int ret;
+
+ ret = kernctl_create_stream(session->metadata->fd);
+ if (ret < 0) {
+ perror("kernel create metadata stream");
+ ret = -errno;
+ goto error;
+ }
+
+ DBG("Kernel metadata stream created (fd: %d)", ret);
+ session->metadata_stream_fd = ret;
return 0;
#define _LTT_KERNEL_CTL_H
#include "trace.h"
+#include "session.h"
-int kernel_create_session(struct command_ctx *cmd_ctx, int tracer_fd);
-int kernel_create_channel(struct command_ctx *cmd_ctx);
-int kernel_enable_event(struct ltt_kernel_channel *channel, char *name);
+int kernel_create_session(struct ltt_session *session, int tracer_fd);
+int kernel_create_channel(struct ltt_kernel_session *session);
+int kernel_enable_event(struct ltt_kernel_session *session, char *name);
int kernel_open_metadata(struct ltt_kernel_session *session);
+int kernel_create_metadata_stream(struct ltt_kernel_session *session);
+int kernel_create_channel_stream(struct ltt_kernel_channel *channel);
+int kernel_start_session(struct ltt_kernel_session *session);
+int kernel_stop_session(struct ltt_kernel_session *session);
+pid_t kernel_start_consumer(void);
#endif /* _LTT_KERNEL_CTL_H */
-/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
*
* 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; either version 2
* of the License, or (at your option) any later version.
- *
+ *
* 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.
#define _LTT_SESSIOND_H
#define DEFAULT_HOME_DIR "/tmp"
-#define DEFAULT_UST_SOCK_DIR "/tmp/ust-app-socks"
-#define DEFAULT_GLOBAL_APPS_PIPE "/tmp/ust-app-socks/global"
+#define DEFAULT_UST_SOCK_DIR DEFAULT_HOME_DIR "/ust-app-socks"
+#define DEFAULT_GLOBAL_APPS_PIPE DEFAULT_UST_SOCK_DIR "/global"
+#define DEFAULT_TRACE_OUTPUT DEFAULT_HOME_DIR "/lttng"
/*
* Kernel tracer defines
*/
#define DEFAULT_KERNEL_TRACER_PATH "/mnt/debugfs/lttng"
#define DEFAULT_KERNEL_OVERWRITE 0
-#define DEFAULT_KERNEL_SUBBUF_SIZE 512 /* bytes */
-#define DEFAULT_KERNEL_SUBBUF_NUM 2 /* Must always be a power of 2 */
-#define DEFAULT_KERNEL_SWITCH_TIMER 0 /* usec */
-#define DEFAULT_KERNEL_READ_TIMER 10000 /* usec */
+#define DEFAULT_KERNEL_SUBBUF_SIZE 4096 /* bytes */
+#define DEFAULT_KERNEL_SUBBUF_NUM 8 /* Must always be a power of 2 */
+#define DEFAULT_KERNEL_SWITCH_TIMER 0 /* usec */
+#define DEFAULT_KERNEL_READ_TIMER 200 /* usec */
extern const char default_home_dir[],
default_tracing_group[],
#include <grp.h>
#include <limits.h>
#include <pthread.h>
+#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
static int set_permissions(void);
static int setup_lttng_msg(struct command_ctx *cmd_ctx, size_t size);
static int create_lttng_rundir(void);
+static int create_trace_dir(struct ltt_kernel_session *session);
static int set_kconsumerd_sockets(void);
static void cleanup(void);
static void sighandler(int sig);
static void clean_command_ctx(struct command_ctx *cmd_ctx);
+static void teardown_kernel_session(struct ltt_session *session);
static void *thread_manage_clients(void *data);
static void *thread_manage_apps(void *data);
static int client_sock;
static int apps_sock;
static int kconsumerd_err_sock;
+static int kconsumerd_cmd_sock;
static int kernel_tracer_fd;
+static pthread_t kconsumerd_thread;
+static sem_t kconsumerd_sem;
+
+static pthread_mutex_t kconsumerd_pid_mutex;
+static pid_t kconsumerd_pid;
/*
* thread_manage_kconsumerd
static void *thread_manage_kconsumerd(void *data)
{
int sock, ret;
+ enum lttcomm_return_code code;
DBG("[thread] Manage kconsumerd started");
goto error;
}
- while (1) {
- //ret = lttcomm_recv_unix_sock(sock, &lsm, sizeof(lsm));
- if (ret <= 0) {
- /* TODO: Consumerd died? */
- continue;
+ 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);
+ if (kconsumerd_cmd_sock < 0) {
+ perror("kconsumerd connect");
+ goto error;
}
+ /* Signal condition to tell that the kconsumerd is ready */
+ sem_post(&kconsumerd_sem);
+ DBG("Kconsumerd command socket ready");
+ } else {
+ DBG("[sessiond] Kconsumerd error when waiting for SOCK_READY : %s",
+ lttcomm_get_readable_code(-code));
+ goto error;
+ }
+
+ /* Wait for any kconsumerd error */
+ ret = lttcomm_recv_unix_sock(sock, &code, sizeof(enum lttcomm_return_code));
+ if (ret <= 0) {
+ ERR("[sessiond] Kconsumerd closed the command socket");
+ goto error;
}
+ ERR("Kconsumerd return code : %s", lttcomm_get_readable_code(-code));
+
error:
+ teardown_kernel_session((struct ltt_session *) data);
return NULL;
}
return ret;
}
+/*
+ * start_kconsumerd_thread
+ *
+ * Start the thread_manage_kconsumerd. This must be done after a kconsumerd
+ * exec or it will fails.
+ */
+static int start_kconsumerd_thread(struct ltt_session *session)
+{
+ int ret;
+
+ /* Setup semaphore */
+ sem_init(&kconsumerd_sem, 0, 0);
+
+ ret = pthread_create(&kconsumerd_thread, NULL, thread_manage_kconsumerd, (void *) session);
+ if (ret != 0) {
+ perror("pthread_create kconsumerd");
+ goto error;
+ }
+
+ sem_wait(&kconsumerd_sem);
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * kernel_start_consumer
+ *
+ * Start a kernel consumer daemon (kconsumerd).
+ *
+ * Return pid if successful else -1.
+ */
+pid_t kernel_start_consumer(void)
+{
+ int ret;
+ pid_t pid;
+
+ pid = fork();
+ if (pid == 0) {
+ /*
+ * Exec kconsumerd.
+ */
+ execlp("kconsumerd", "kconsumerd", "--daemonize", NULL);
+ if (errno != 0) {
+ perror("kernel start consumer exec");
+ }
+ exit(EXIT_FAILURE);
+ } else if (pid > 0) {
+ ret = pid;
+ goto error;
+ } else {
+ perror("kernel start consumer fork");
+ ret = -errno;
+ goto error;
+ }
+
+error:
+ return ret;
+}
+
+/*
+ * send_kconsumerd_fds
+ *
+ * Send all stream fds of the kernel session to the consumer.
+ */
+static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session)
+{
+ int ret, i = 0;
+ /* Plus one here for the metadata fd */
+ size_t nb_fd = session->stream_count_global + 1;
+ int fds[nb_fd];
+ struct ltt_kernel_stream *stream;
+ struct ltt_kernel_channel *chan;
+ struct lttcomm_kconsumerd_header lkh;
+ struct lttcomm_kconsumerd_msg buf[nb_fd];
+
+ /* Add metadata data */
+ fds[i] = session->metadata_stream_fd;
+ buf[i].fd = fds[i];
+ buf[i].state = ACTIVE_FD;
+ buf[i].max_sb_size = session->metadata->conf->subbuf_size;
+ strncpy(buf[i].path_name, session->metadata->pathname, PATH_MAX);
+
+ cds_list_for_each_entry(chan, &session->channel_list.head, list) {
+ cds_list_for_each_entry(stream, &chan->stream_list.head, list) {
+ i++;
+ fds[i] = stream->fd;
+ buf[i].fd = stream->fd;
+ buf[i].state = stream->state;
+ buf[i].max_sb_size = chan->channel->subbuf_size;
+ strncpy(buf[i].path_name, stream->pathname, PATH_MAX);
+ }
+ }
+
+ /* Setup header */
+ lkh.payload_size = nb_fd * sizeof(struct lttcomm_kconsumerd_msg);
+ lkh.cmd_type = LTTCOMM_ADD_STREAM;
+
+ DBG("Sending kconsumerd header");
+
+ ret = lttcomm_send_unix_sock(sock, &lkh, sizeof(struct lttcomm_kconsumerd_header));
+ if (ret < 0) {
+ perror("send kconsumerd header");
+ goto error;
+ }
+
+ DBG("Sending all fds to kconsumerd");
+
+ ret = lttcomm_send_fds_unix_sock(sock, buf, fds, nb_fd, lkh.payload_size);
+ if (ret < 0) {
+ perror("send kconsumerd fds");
+ goto error;
+ }
+
+ DBG("Kconsumerd fds sent");
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * free_kernel_session
+ *
+ * Free all data structure inside a kernel session and the session pointer.
+ */
+static void free_kernel_session(struct ltt_kernel_session *session)
+{
+ struct ltt_kernel_channel *chan;
+ struct ltt_kernel_stream *stream;
+ struct ltt_kernel_event *event;
+
+ /* Clean metadata */
+ close(session->metadata_stream_fd);
+ close(session->metadata->fd);
+ free(session->metadata->conf);
+ free(session->metadata);
+
+ cds_list_for_each_entry(chan, &session->channel_list.head, list) {
+ /* Clean all event(s) */
+ cds_list_for_each_entry(event, &chan->events_list.head, list) {
+ close(event->fd);
+ free(event->event);
+ free(event);
+ }
+
+ /* Clean streams */
+ cds_list_for_each_entry(stream, &chan->stream_list.head, list) {
+ close(stream->fd);
+ free(stream->pathname);
+ free(stream);
+ }
+ /* Clean channel */
+ close(chan->fd);
+ free(chan->channel);
+ free(chan->pathname);
+ free(chan);
+ }
+
+ close(session->fd);
+ free(session);
+
+ DBG("All kernel session data structures freed");
+}
+
+/*
+ * teardown_kernel_session
+ *
+ * Complete teardown of a kernel session. This free all data structure
+ * related to a kernel session and update counter.
+ */
+static void teardown_kernel_session(struct ltt_session *session)
+{
+ if (session->kernel_session != NULL) {
+ DBG("Tearing down kernel session");
+ free_kernel_session(session->kernel_session);
+ /* Extra precaution */
+ session->kernel_session = NULL;
+ /* Decrement session count */
+ session->kern_session_count--;
+ /* Set kconsumerd pid to 0 (inactive) */
+ session->kernel_consumer = 0;
+ }
+}
+
/*
* process_client_msg
*
switch (cmd_ctx->lsm->cmd_type) {
case KERNEL_CREATE_SESSION:
case KERNEL_CREATE_CHANNEL:
+ case KERNEL_CREATE_STREAM:
case KERNEL_DISABLE_EVENT:
case KERNEL_ENABLE_EVENT:
case KERNEL_OPEN_METADATA:
goto setup_error;
}
+ DBG("Checking if kconsumerd is alive");
+ pthread_mutex_lock(&kconsumerd_pid_mutex);
+ if (kconsumerd_pid == 0) {
+ ret = kernel_start_consumer();
+ if (ret < 0) {
+ ERR("Kernel start kconsumerd failed");
+ ret = LTTCOMM_KERN_CONSUMER_FAIL;
+ pthread_mutex_unlock(&kconsumerd_pid_mutex);
+ goto error;
+ }
+
+ /* Setting up the global kconsumerd_pid */
+ kconsumerd_pid = ret;
+ }
+ pthread_mutex_unlock(&kconsumerd_pid_mutex);
+
+ ret = start_kconsumerd_thread(cmd_ctx->session);
+ if (ret < 0) {
+ ERR("Fatal error : start_kconsumerd_thread()");
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
DBG("Creating kernel session");
- ret = kernel_create_session(cmd_ctx, kernel_tracer_fd);
+ ret = kernel_create_session(cmd_ctx->session, kernel_tracer_fd);
if (ret < 0) {
ret = LTTCOMM_KERN_SESS_FAIL;
goto error;
goto setup_error;
}
- DBG("Creating kernel session");
+ DBG("Creating kernel channel");
+
+ ret = kernel_create_channel(cmd_ctx->session->kernel_session);
- ret = kernel_create_channel(cmd_ctx);
if (ret < 0) {
ret = LTTCOMM_KERN_CHAN_FAIL;
goto error;
DBG("Enabling kernel event %s", cmd_ctx->lsm->u.event.event_name);
- ret = kernel_enable_event(cmd_ctx->session->kernel_session->channel, cmd_ctx->lsm->u.event.event_name);
+ ret = kernel_enable_event(cmd_ctx->session->kernel_session, cmd_ctx->lsm->u.event.event_name);
if (ret < 0) {
ret = LTTCOMM_KERN_ENABLE_FAIL;
goto error;
ret = LTTCOMM_OK;
break;
}
+ case KERNEL_CREATE_STREAM:
+ {
+ struct ltt_kernel_channel *chan;
+ /* Setup lttng message with no payload */
+ ret = setup_lttng_msg(cmd_ctx, 0);
+ if (ret < 0) {
+ goto setup_error;
+ }
+
+ DBG("Creating kernel stream");
+
+ ret = kernel_create_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) {
+ ret = kernel_create_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 = LTTCOMM_OK;
+ break;
+ }
+ case KERNEL_START_TRACE:
+ {
+ /* Setup lttng message with no payload */
+ ret = setup_lttng_msg(cmd_ctx, 0);
+ if (ret < 0) {
+ goto setup_error;
+ }
+
+ DBG("Start kernel tracing");
+
+ ret = create_trace_dir(cmd_ctx->session->kernel_session);
+ if (ret < 0) {
+ if (ret == -EEXIST) {
+ ret = LTTCOMM_KERN_DIR_EXIST;
+ } else {
+ ret = LTTCOMM_KERN_DIR_FAIL;
+ goto error;
+ }
+ }
+
+ ret = kernel_start_session(cmd_ctx->session->kernel_session);
+ if (ret < 0) {
+ ERR("Kernel start session failed");
+ ret = LTTCOMM_KERN_START_FAIL;
+ goto error;
+ }
+
+ ret = send_kconsumerd_fds(kconsumerd_cmd_sock, cmd_ctx->session->kernel_session);
+ if (ret < 0) {
+ ERR("Send kconsumerd fds failed");
+ ret = LTTCOMM_KERN_CONSUMER_FAIL;
+ goto error;
+ }
+
+ ret = LTTCOMM_OK;
+ break;
+ }
+ case KERNEL_STOP_TRACE:
+ {
+ /* Setup lttng message with no payload */
+ ret = setup_lttng_msg(cmd_ctx, 0);
+ if (ret < 0) {
+ goto setup_error;
+ }
+
+ DBG("Stop kernel tracing");
+
+ ret = kernel_stop_session(cmd_ctx->session->kernel_session);
+ if (ret < 0) {
+ ERR("Kernel stop session failed");
+ ret = LTTCOMM_KERN_STOP_FAIL;
+ goto error;
+ }
+
+ /* Clean kernel session teardown */
+ teardown_kernel_session(cmd_ctx->session);
+
+ ret = LTTCOMM_OK;
+ break;
+ }
case LTTNG_CREATE_SESSION:
{
/* Setup lttng message with no payload */
return ret;
}
+/*
+ * create_trace_dir
+ *
+ * Create the trace output directory.
+ */
+static int create_trace_dir(struct ltt_kernel_session *session)
+{
+ int ret;
+ struct ltt_kernel_channel *chan;
+
+ /* Create all channel directories */
+ cds_list_for_each_entry(chan, &session->channel_list.head, list) {
+ ret = mkdir(chan->pathname, S_IRWXU | S_IRWXG );
+ if (ret < 0) {
+ perror("mkdir trace path");
+ ret = -errno;
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ return ret;
+}
+
/*
* create_lttng_rundir
*
WARN("No kernel tracer available");
kernel_tracer_fd = 0;
}
+
+ DBG("Kernel tracer fd %d", kernel_tracer_fd);
}
/*
{
int ret;
char *cmd;
+ struct ltt_session *sess;
+ struct ltt_session_list *session_list = get_session_list();
DBG("Cleaning up");
ERR("Unable to clean " LTTNG_RUNDIR);
}
- // TODO Clean kernel trace fds
+ /* Cleanup ALL session */
+ cds_list_for_each_entry(sess, &session_list->head, list) {
+ teardown_kernel_session(sess);
+ // TODO complete session cleanup (including UST)
+ }
+
close(kernel_tracer_fd);
}
static void del_session_list(struct ltt_session *ls);
/* Init session's list */
-static struct ltt_session_list ltt_session_list = {
+struct ltt_session_list ltt_session_list = {
.head = CDS_LIST_HEAD_INIT(ltt_session_list.head),
};
+/*
+ * get_session_list
+ *
+ * Return a pointer to the session list.
+ */
+struct ltt_session_list *get_session_list(void)
+{
+ return <t_session_list;
+}
+
/*
* get_session_count
*
struct ltt_session *find_session_by_uuid(uuid_t session_id);
struct ltt_session *find_session_by_name(char *name);
unsigned int get_session_count(void);
+struct ltt_session_list *get_session_list(void);
#endif /* _LTT_SESSION_H */
struct cds_list_head head;
};
+/* Channel stream list */
+struct ltt_kernel_stream_list {
+ struct cds_list_head head;
+};
+
+/* Channel list */
+struct ltt_kernel_channel_list {
+ struct cds_list_head head;
+};
+
/* Kernel event */
struct ltt_kernel_event {
int fd;
/* Kernel channel */
struct ltt_kernel_channel {
int fd;
+ char *pathname;
+ unsigned int stream_count;
struct lttng_kernel_channel *channel;
struct ltt_kernel_event_list events_list;
+ struct ltt_kernel_stream_list stream_list;
+ struct cds_list_head list;
};
/* Metadata */
struct ltt_kernel_metadata {
int fd;
+ char *pathname;
struct lttng_kernel_channel *conf;
};
+/* Channel stream */
+struct ltt_kernel_stream {
+ int fd;
+ char *pathname;
+ int state;
+ struct cds_list_head list;
+};
+
/* Kernel session */
struct ltt_kernel_session {
int fd;
+ int metadata_stream_fd;
+ unsigned int channel_count;
+ unsigned int stream_count_global;
struct ltt_kernel_metadata *metadata;
- struct ltt_kernel_channel *channel;
+ struct ltt_kernel_channel_list channel_list;
};
/* UST trace representation */
static int process_opt_create_session(void);
static int process_kernel_create_trace(void);
static int process_opt_kernel_event(void);
+static int process_kernel_start_trace(void);
static int set_session_uuid(void);
static void sighandler(int sig);
static int set_signal_handler(void);
} else {
// Enable all events
}
+
+ if (auto_trace || opt_start_trace) {
+ DBG("Starting kernel tracing");
+ ret = process_kernel_start_trace();
+ if (ret < 0) {
+ goto end;
+ }
+ }
+
+ if (opt_stop_trace) {
+ DBG("Stopping kernel tracing");
+ ret = lttng_kernel_stop_tracing();
+ if (ret < 0) {
+ goto end;
+ }
+ }
}
if (opt_trace_pid != 0) {
return ret;
}
+/*
+ * process_kernel_start_trace
+ *
+ * Start a kernel trace.
+ */
+static int process_kernel_start_trace(void)
+{
+ int ret;
+
+ ret = lttng_kernel_create_stream();
+ if (ret < 0) {
+ goto error;
+ }
+
+ ret = lttng_kernel_start_tracing();
+ if (ret < 0) {
+ goto error;
+ }
+
+ MSG("Kernel tracing started");
+
+ return 0;
+
+error:
+ return ret;
+}
+
/*
* process_kernel_create_trace
*