Initial work for kernel tracing support
authorDavid Goulet <david.goulet@polymtl.ca>
Wed, 25 May 2011 16:43:59 +0000 (12:43 -0400)
committerDavid Goulet <david.goulet@polymtl.ca>
Thu, 26 May 2011 17:08:39 +0000 (13:08 -0400)
This commit adds trace kernel support to the complete set of tools. It
is working with the LTTng 2.0 and output traces readeable by babeltrace.
Quick changes log below:

Add multiple debug statement and bug fixes.
Add kernel trace directory creation.
Add kernel structure teardown.
Start kconsumerd on create session.
Start kconsumerd thread after exec.

Following up this commit, there will be a huge cleanup because a lot of codes
was added to make it work but it's not necessarily clean code structure.

Signed-off-by: David Goulet <david.goulet@polymtl.ca>
12 files changed:
include/lttng/lttng.h
liblttngctl/liblttngctl.c
liblttsessiondcomm/liblttsessiondcomm.c
liblttsessiondcomm/liblttsessiondcomm.h
ltt-sessiond/kernel-ctl.c
ltt-sessiond/kernel-ctl.h
ltt-sessiond/ltt-sessiond.h
ltt-sessiond/main.c
ltt-sessiond/session.c
ltt-sessiond/session.h
ltt-sessiond/trace.h
lttng/lttng.c

index e47338f4086e9bd47b4a8f997b7f0cb92ebf65e4..a1ccc451ee7a85786be12113597356cc001b363c 100644 (file)
@@ -82,6 +82,7 @@ extern int lttng_kernel_create_session(void);
 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 */
index d782bb07e93459d5ea9cb237de99752a2b6249a5..ab44efe90f5ce825d1443d3911e499d6b01a3e22 100644 (file)
@@ -213,6 +213,16 @@ int lttng_kernel_open_metadata(void)
        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
  *
index ddee7bcae512bc4a116506c3bc054a378117c0fc..d1e38898501c7ab74a60c36199a087e69c6466ee 100644 (file)
@@ -54,6 +54,12 @@ static const char *lttcomm_readable_code[] = {
        [ 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",
@@ -271,3 +277,41 @@ int lttcomm_close_unix_sock(int sock)
 
        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;
+}
index 9a31aacce04e7e72a8e2445c8c3e91eb01936ac9..46469f15d6d86225b21cb43efe3acefbeab0230f 100644 (file)
@@ -50,6 +50,7 @@
 enum lttcomm_sessiond_command {
        KERNEL_CREATE_CHANNEL,
        KERNEL_CREATE_SESSION,
+       KERNEL_CREATE_STREAM,
        KERNEL_DISABLE_EVENT,
        KERNEL_ENABLE_EVENT,
        KERNEL_OPEN_METADATA,
@@ -107,6 +108,12 @@ enum lttcomm_return_code {
        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 */
@@ -199,6 +206,7 @@ extern int lttcomm_connect_unix_sock(const char *pathname);
 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);
index 969acfbf437deb51de608fcba7d991e9ba8353b6..d00f7e5bc4e48266a736959d7351cd086164735a 100644 (file)
  * 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"
@@ -31,7 +34,7 @@
  *
  *  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;
@@ -51,8 +54,13 @@ int kernel_create_session(struct command_ctx *cmd_ctx, int tracer_fd)
 
        /* 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;
 
@@ -65,7 +73,7 @@ error:
  *
  *  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;
@@ -86,17 +94,30 @@ int kernel_create_channel(struct command_ctx *cmd_ctx)
        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;
 
@@ -109,9 +130,10 @@ error:
  *
  *  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;
 
@@ -129,13 +151,17 @@ int kernel_enable_event(struct ltt_kernel_channel *channel, char *name)
        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;
 
@@ -174,9 +200,126 @@ int kernel_open_metadata(struct ltt_kernel_session *session)
                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;
 
index a1ab0c25cccbf5b052a421cf1f301befad442170..4eb8f4e2d0e797a63333771435682c9b13d0da55 100644 (file)
 #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 */
index d563d1016a9672d18f607d4142c91bea2d1cabee..161da0d8e60547169b1da8e061e119b9c468d82d 100644 (file)
@@ -1,15 +1,16 @@
-/* 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[],
index 9b76a56adce2486efca5aecd66f29b2aca1343e3..79e8ec12d6e9b5c9de4092474e05695d2f45ea5a 100644 (file)
@@ -22,6 +22,7 @@
 #include <grp.h>
 #include <limits.h>
 #include <pthread.h>
+#include <semaphore.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -69,10 +70,12 @@ static int set_signal_handler(void);
 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);
@@ -96,7 +99,13 @@ static char kconsumerd_cmd_unix_sock_path[PATH_MAX]; /* kconsumerd command Unix
 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
@@ -107,6 +116,7 @@ static int kernel_tracer_fd;
 static void *thread_manage_kconsumerd(void *data)
 {
        int sock, ret;
+       enum lttcomm_return_code code;
 
        DBG("[thread] Manage kconsumerd started");
 
@@ -120,15 +130,37 @@ static void *thread_manage_kconsumerd(void *data)
                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;
 }
 
@@ -427,6 +459,194 @@ error:
        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
  *
@@ -461,6 +681,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
        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:
@@ -494,9 +715,32 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                        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;
@@ -512,9 +756,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                        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;
@@ -533,7 +778,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
 
                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;
@@ -561,6 +806,99 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                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 */
@@ -970,6 +1308,32 @@ end:
        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
  *
@@ -1003,6 +1367,8 @@ static void init_kernel_tracer(void)
                WARN("No kernel tracer available");
                kernel_tracer_fd = 0;
        }
+
+       DBG("Kernel tracer fd %d", kernel_tracer_fd);
 }
 
 /*
@@ -1124,6 +1490,8 @@ static void cleanup()
 {
        int ret;
        char *cmd;
+       struct ltt_session *sess;
+       struct ltt_session_list *session_list = get_session_list();
 
        DBG("Cleaning up");
 
@@ -1147,7 +1515,12 @@ static void cleanup()
                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);
 }
 
index 9fef73cf7ecdce33e10a7599b2a580742ecc3257..5764b71dc61ed4ecfb1f350989a7f9b51df77c14 100644 (file)
@@ -33,10 +33,20 @@ static void add_session_list(struct ltt_session *ls);
 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 &ltt_session_list;
+}
+
 /*
  *  get_session_count
  *
index 7567d986767b185e2be046c44eb3675c949570f3..16e6946a754dbd5bd80e98f28f601fa956b55413 100644 (file)
@@ -50,5 +50,6 @@ void get_lttng_session(struct lttng_session *sessions);
 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 */
index 910d38f041d55649742adf97588ae0e2b514d075..2f80143fe8042ec8d22b5c97b1c80a325e10dc92 100644 (file)
@@ -28,6 +28,16 @@ struct ltt_kernel_event_list {
        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;
@@ -38,21 +48,37 @@ struct ltt_kernel_event {
 /* 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 */
index 9714e8a3476c10ad721362bca4d019c1c2fc62ae..7fbbcd68f4f216388aedc661f8b2cef4951c0778 100644 (file)
@@ -50,6 +50,7 @@ static int process_opt_list_traces(void);
 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);
@@ -137,6 +138,22 @@ static int process_client_opt(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) {
@@ -175,6 +192,33 @@ error:     /* fall through */
        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
  *
This page took 0.062334 seconds and 4 git commands to generate.