Add kernel tracer check on kernel command
[lttng-tools.git] / ltt-sessiond / main.c
index 5337d6df44781980c7cc77fd4211932fcf540de0..cbd6a3f3f6a7469ddc2be72fb5b313555bf37989 100644 (file)
@@ -45,6 +45,7 @@
 #include "ust-ctl.h"
 #include "session.h"
 #include "traceable-app.h"
+#include "lttng-kconsumerd.h"
 
 /*
  * TODO:
@@ -55,7 +56,7 @@
 
 /* Const values */
 const char default_home_dir[] = DEFAULT_HOME_DIR;
-const char default_tracing_group[] = DEFAULT_TRACING_GROUP;
+const char default_tracing_group[] = LTTNG_DEFAULT_TRACING_GROUP;
 const char default_ust_sock_dir[] = DEFAULT_UST_SOCK_DIR;
 const char default_global_apps_pipe[] = DEFAULT_GLOBAL_APPS_PIPE;
 
@@ -90,50 +91,6 @@ static sem_t kconsumerd_sem;
 
 static pthread_mutex_t kconsumerd_pid_mutex;   /* Mutex to control kconsumerd pid assignation */
 
-/*
- *  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
  *
@@ -144,7 +101,7 @@ 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);
+               trace_destroy_kernel_session(session->kernel_session);
                /* Extra precaution */
                session->kernel_session = NULL;
                /* Decrement session count */
@@ -375,6 +332,7 @@ static void *thread_manage_kconsumerd(void *data)
                goto error;
        }
 
+       /* Getting status code from kconsumerd */
        ret = lttcomm_recv_unix_sock(sock, &code, sizeof(enum lttcomm_return_code));
        if (ret <= 0) {
                goto error;
@@ -383,6 +341,7 @@ static void *thread_manage_kconsumerd(void *data)
        if (code == KCONSUMERD_COMMAND_SOCK_READY) {
                kconsumerd_cmd_sock = lttcomm_connect_unix_sock(kconsumerd_cmd_unix_sock_path);
                if (kconsumerd_cmd_sock < 0) {
+                       sem_post(&kconsumerd_sem);
                        perror("kconsumerd connect");
                        goto error;
                }
@@ -390,7 +349,7 @@ static void *thread_manage_kconsumerd(void *data)
                sem_post(&kconsumerd_sem);
                DBG("Kconsumerd command socket ready");
        } else {
-               DBG("[sessiond] Kconsumerd error when waiting for SOCK_READY : %s",
+               DBG("Kconsumerd error when waiting for SOCK_READY : %s",
                                lttcomm_get_readable_code(-code));
                goto error;
        }
@@ -398,7 +357,7 @@ static void *thread_manage_kconsumerd(void *data)
        /* 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");
+               ERR("Kconsumerd closed the command socket");
                goto error;
        }
 
@@ -406,6 +365,7 @@ static void *thread_manage_kconsumerd(void *data)
 
 error:
        kconsumerd_pid = 0;
+       DBG("Kconsumerd thread dying");
        return NULL;
 }
 
@@ -477,12 +437,12 @@ error:
 }
 
 /*
- *  start_kconsumerd_thread
+ *  spawn_kconsumerd_thread
  *
  *  Start the thread_manage_kconsumerd. This must be done after a kconsumerd
  *  exec or it will fails.
  */
-static int start_kconsumerd_thread(void)
+static int spawn_kconsumerd_thread(void)
 {
        int ret;
 
@@ -495,32 +455,45 @@ static int start_kconsumerd_thread(void)
                goto error;
        }
 
+       /* Wait for the kconsumerd thread to be ready */
        sem_wait(&kconsumerd_sem);
 
+       if (kconsumerd_pid == 0) {
+               ERR("Kconsumerd did not start");
+               goto error;
+       }
+
        return 0;
 
 error:
+       ret = LTTCOMM_KERN_CONSUMER_FAIL;
        return ret;
 }
 
 /*
- *  kernel_start_consumer
+ *  spawn_kconsumerd
+ *
+ *  Fork and exec a kernel consumer daemon (kconsumerd).
  *
- *  Start a kernel consumer daemon (kconsumerd).
+ *  NOTE: It is very important to fork a kconsumerd BEFORE opening any kernel
+ *  file descriptor using the libkernelctl or kernel-ctl functions. So, a
+ *  kernel consumer MUST only be spawned before creating a kernel session.
  *
  *  Return pid if successful else -1.
  */
-pid_t kernel_start_consumer(void)
+static pid_t spawn_kconsumerd(void)
 {
        int ret;
        pid_t pid;
 
+       DBG("Spawning kconsumerd");
+
        pid = fork();
        if (pid == 0) {
                /*
                 * Exec kconsumerd.
                 */
-               execlp("kconsumerd", "kconsumerd", "--daemonize", NULL);
+               execlp("kconsumerd", "kconsumerd", "--verbose", NULL);
                if (errno != 0) {
                        perror("kernel start consumer exec");
                }
@@ -538,6 +511,49 @@ error:
        return ret;
 }
 
+/*
+ *  start_kconsumerd
+ *
+ *  Spawn the kconsumerd daemon and session daemon thread.
+ */
+static int start_kconsumerd(void)
+{
+       int ret;
+
+       pthread_mutex_lock(&kconsumerd_pid_mutex);
+       if (kconsumerd_pid != 0) {
+               goto end;
+       }
+
+       ret = spawn_kconsumerd();
+       if (ret < 0) {
+               ERR("Spawning 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);
+
+       DBG("Kconsumerd pid %d", ret);
+
+       DBG("Spawning kconsumerd thread");
+       ret = spawn_kconsumerd_thread();
+       if (ret < 0) {
+               ERR("Fatal error spawning kconsumerd thread");
+               goto error;
+       }
+
+end:
+       pthread_mutex_unlock(&kconsumerd_pid_mutex);
+       return 0;
+
+error:
+       return ret;
+}
+
 /*
  *  send_kconsumerd_fds
  *
@@ -545,36 +561,18 @@ error:
  */
 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];
+       int ret;
+       size_t nb_fd;
        struct ltt_kernel_stream *stream;
        struct ltt_kernel_channel *chan;
        struct lttcomm_kconsumerd_header lkh;
-       struct lttcomm_kconsumerd_msg buf[nb_fd];
+       struct lttcomm_kconsumerd_msg lkm;
 
-       /* 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);
-               }
-       }
+       nb_fd = session->stream_count_global;
 
        /* Setup header */
-       lkh.payload_size = nb_fd * sizeof(struct lttcomm_kconsumerd_msg);
-       lkh.cmd_type = LTTCOMM_ADD_STREAM;
+       lkh.payload_size = (nb_fd + 1) * sizeof(struct lttcomm_kconsumerd_msg);
+       lkh.cmd_type = ADD_STREAM;
 
        DBG("Sending kconsumerd header");
 
@@ -584,14 +582,37 @@ static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session)
                goto error;
        }
 
-       DBG("Sending all fds to kconsumerd");
+       DBG("Sending metadata stream fd");
 
-       ret = lttcomm_send_fds_unix_sock(sock, buf, fds, nb_fd, lkh.payload_size);
+       /* Send metadata stream fd first */
+       lkm.fd = session->metadata_stream_fd;
+       lkm.state = ACTIVE_FD;
+       lkm.max_sb_size = session->metadata->conf->subbuf_size;
+       strncpy(lkm.path_name, session->metadata->pathname, PATH_MAX);
+
+       ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm));
        if (ret < 0) {
-               perror("send kconsumerd fds");
+               perror("send kconsumerd fd");
                goto error;
        }
 
+       cds_list_for_each_entry(chan, &session->channel_list.head, list) {
+               cds_list_for_each_entry(stream, &chan->stream_list.head, list) {
+                       lkm.fd = stream->fd;
+                       lkm.state = stream->state;
+                       lkm.max_sb_size = chan->channel->subbuf_size;
+                       strncpy(lkm.path_name, stream->pathname, PATH_MAX);
+
+                       DBG("Sending fd %d to kconsumerd", lkm.fd);
+
+                       ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm));
+                       if (ret < 0) {
+                               perror("send kconsumerd fd");
+                               goto error;
+                       }
+               }
+       }
+
        DBG("Kconsumerd fds sent");
 
        return 0;
@@ -612,6 +633,7 @@ static int create_trace_dir(struct ltt_kernel_session *session)
 
        /* Create all channel directories */
        cds_list_for_each_entry(chan, &session->channel_list.head, list) {
+               DBG("Creating trace directory at %s", chan->pathname);
                ret = mkdir(chan->pathname, S_IRWXU | S_IRWXG );
                if (ret < 0) {
                        perror("mkdir trace path");
@@ -626,6 +648,22 @@ error:
        return ret;
 }
 
+/*
+ *  init_kernel_tracer
+ *
+ *  Setup necessary data for kernel tracer action.
+ */
+static void init_kernel_tracer(void)
+{
+       /* Set the global kernel tracer fd */
+       kernel_tracer_fd = open(DEFAULT_KERNEL_TRACER_PATH, O_RDWR);
+       if (kernel_tracer_fd < 0) {
+               WARN("No kernel tracer available");
+               kernel_tracer_fd = 0;
+       }
+
+       DBG("Kernel tracer fd %d", kernel_tracer_fd);
+}
 
 /*
  *     process_client_msg
@@ -646,6 +684,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
        switch (cmd_ctx->lsm->cmd_type) {
        case LTTNG_CREATE_SESSION:
        case LTTNG_LIST_SESSIONS:
+       case KERNEL_LIST_EVENTS:
        case UST_LIST_APPS:
                break;
        default:
@@ -664,14 +703,17 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
        case KERNEL_CREATE_STREAM:
        case KERNEL_DISABLE_EVENT:
        case KERNEL_ENABLE_EVENT:
+       case KERNEL_LIST_EVENTS:
        case KERNEL_OPEN_METADATA:
        case KERNEL_START_TRACE:
        case KERNEL_STOP_TRACE:
-               /* TODO: reconnect to kernel tracer to check if
-                * it's loadded */
+               /* Kernel tracer check */
                if (kernel_tracer_fd == 0) {
-                       ret = LTTCOMM_KERN_NA;
-                       goto error;
+                       init_kernel_tracer();
+                       if (kernel_tracer_fd == 0) {
+                               ret = LTTCOMM_KERN_NA;
+                               goto error;
+                       }
                }
                break;
        }
@@ -695,26 +737,8 @@ 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();
+               ret = start_kconsumerd();
                if (ret < 0) {
-                       ERR("Fatal error : start_kconsumerd_thread()");
-                       ret = LTTCOMM_FATAL;
                        goto error;
                }
 
@@ -767,6 +791,71 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                ret = LTTCOMM_OK;
                break;
        }
+       case KERNEL_ENABLE_ALL_EVENT:
+       {
+               int pos, size;
+               char *event_list, *event, *ptr;
+
+               /* Setup lttng message with no payload */
+               ret = setup_lttng_msg(cmd_ctx, 0);
+               if (ret < 0) {
+                       goto setup_error;
+               }
+
+               DBG("Enabling all kernel event");
+
+               size = kernel_list_events(kernel_tracer_fd, &event_list);
+               if (size < 0) {
+                       ret = LTTCOMM_KERN_LIST_FAIL;
+                       goto error;
+               }
+
+               ptr = event_list;
+               while ((size = sscanf(ptr, "event { name = %m[^;]; };%n\n", &event, &pos)) == 1) {
+                       /* Enable each single event */
+                       ret = kernel_enable_event(cmd_ctx->session->kernel_session, event);
+                       if (ret < 0) {
+                               ret = LTTCOMM_KERN_ENABLE_FAIL;
+                               goto error;
+                       }
+                       /* Move pointer to the next line */
+                       ptr += pos + 1;
+                       free(event);
+               }
+
+               free(event_list);
+
+               ret = LTTCOMM_OK;
+               break;
+       }
+       case KERNEL_LIST_EVENTS:
+       {
+               char *event_list;
+               ssize_t size;
+
+               size = kernel_list_events(kernel_tracer_fd, &event_list);
+               if (size < 0) {
+                       ret = LTTCOMM_KERN_LIST_FAIL;
+                       goto error;
+               }
+
+               /*
+                * Setup lttng message with payload size set to the event list size in
+                * bytes and then copy list into the llm payload.
+                */
+               ret = setup_lttng_msg(cmd_ctx, size);
+               if (ret < 0) {
+                       goto setup_error;
+               }
+
+               /* Copy event list into message payload */
+               memcpy(cmd_ctx->llm->payload, event_list, size);
+
+               free(event_list);
+
+               ret = LTTCOMM_OK;
+               break;
+       }
        case KERNEL_OPEN_METADATA:
        {
                /* Setup lttng message with no payload */
@@ -864,6 +953,11 @@ static int process_client_msg(struct command_ctx *cmd_ctx)
                        goto setup_error;
                }
 
+               if (cmd_ctx->session->kernel_session == NULL) {
+                       ret = LTTCOMM_KERN_NO_SESSION;
+                       goto error;
+               }
+
                DBG("Stop kernel tracing");
 
                ret = kernel_stop_session(cmd_ctx->session->kernel_session);
@@ -1126,6 +1220,9 @@ static void *thread_manage_clients(void *data)
                }
 
                clean_command_ctx(cmd_ctx);
+
+               /* End of transmission */
+               close(sock);
        }
 
 error:
@@ -1382,31 +1479,18 @@ static int create_lttng_rundir(void)
 
        ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG );
        if (ret < 0) {
-               ERR("Unable to create " LTTNG_RUNDIR);
-               goto error;
+               if (errno != EEXIST) {
+                       ERR("Unable to create " LTTNG_RUNDIR);
+                       goto error;
+               } else {
+                       ret = 0;
+               }
        }
 
 error:
        return ret;
 }
 
-/*
- *  init_kernel_tracer
- *
- *  Setup necessary data for kernel tracer action.
- */
-static void init_kernel_tracer(void)
-{
-       /* Set the global kernel tracer fd */
-       kernel_tracer_fd = open(DEFAULT_KERNEL_TRACER_PATH, O_RDWR);
-       if (kernel_tracer_fd < 0) {
-               WARN("No kernel tracer available");
-               kernel_tracer_fd = 0;
-       }
-
-       DBG("Kernel tracer fd %d", kernel_tracer_fd);
-}
-
 /*
  *  set_kconsumerd_sockets
  *
This page took 0.028908 seconds and 4 git commands to generate.