X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=ltt-sessiond%2Fmain.c;h=0effeb1f5ab51a0c91973505c7efd9629dee5a3c;hp=46e6fff454e66aa7dd091fb8a49edadc1d008c53;hb=2b1173d8cb43cb5d7c9ce3772dbdbef3436c407e;hpb=f3ed775ef4842019b396f06095b053c3a70bc3c8 diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index 46e6fff45..0effeb1f5 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -1,7 +1,4 @@ /* - DBG("Creating kernel event %s for channel %s.", - cmd_ctx->lsm->u.enable.event.name, cmd_ctx->lsm->u.enable.channel_name); - * Copyright (C) 2011 - David Goulet * * This program is free software; you can redistribute it and/or @@ -31,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +49,7 @@ #include "traceable-app.h" #include "lttng-kconsumerd.h" #include "libustctl.h" +#include "utils.h" /* * TODO: @@ -285,12 +284,10 @@ 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); - // TODO: recursive create dir - ret = mkdir(chan->pathname, S_IRWXU | S_IRWXG ); + ret = mkdir_recursive(chan->pathname, S_IRWXU | S_IRWXG ); if (ret < 0) { if (ret != EEXIST) { - perror("mkdir trace path"); - ret = -errno; + ERR("Trace directory creation error"); goto error; } } @@ -584,7 +581,7 @@ static pid_t spawn_kconsumerd(void) /* * Exec kconsumerd. */ - execlp("kconsumerd", "kconsumerd", "--verbose", NULL); + execlp("ltt-kconsumerd", "ltt-kconsumerd", "--verbose", NULL); if (errno != 0) { perror("kernel start consumer exec"); } @@ -645,6 +642,58 @@ error: return ret; } +/* + * modprobe_kernel_modules + */ +static int modprobe_kernel_modules(void) +{ + int ret = 0, i = 0; + char modprobe[256]; + + while (kernel_modules_list[i] != NULL) { + ret = snprintf(modprobe, sizeof(modprobe), "/sbin/modprobe %s", + kernel_modules_list[i]); + if (ret < 0) { + perror("snprintf modprobe"); + goto error; + } + ret = system(modprobe); + if (ret < 0) { + ERR("Unable to load module %s", kernel_modules_list[i]); + } + DBG("Modprobe successfully %s", kernel_modules_list[i]); + i++; + } + +error: + return ret; +} + +/* + * mount_debugfs + */ +static int mount_debugfs(char *path) +{ + int ret; + char *type = "debugfs"; + + ret = mkdir_recursive(path, S_IRWXU | S_IRWXG); + if (ret < 0) { + goto error; + } + + ret = mount(type, path, type, 0, NULL); + if (ret < 0) { + perror("mount debugfs"); + goto error; + } + + DBG("Mounted debugfs successfully at %s", path); + +error: + return ret; +} + /* * init_kernel_tracer * @@ -652,14 +701,80 @@ error: */ static void init_kernel_tracer(void) { - /* Set the global kernel tracer fd */ - kernel_tracer_fd = open(DEFAULT_KERNEL_TRACER_PATH, O_RDWR); + int ret; + char *proc_mounts = "/proc/mounts"; + char line[256]; + char *debugfs_path = NULL, *lttng_path; + FILE *fp; + + /* Detect debugfs */ + fp = fopen(proc_mounts, "r"); + if (fp == NULL) { + ERR("Unable to probe %s", proc_mounts); + goto error; + } + + while (fgets(line, sizeof(line), fp) != NULL) { + if (strstr(line, "debugfs") != NULL) { + /* Remove first string */ + strtok(line, " "); + /* Dup string here so we can reuse line later on */ + debugfs_path = strdup(strtok(NULL, " ")); + DBG("Got debugfs path : %s", debugfs_path); + break; + } + } + + fclose(fp); + + /* Mount debugfs if needded */ + if (debugfs_path == NULL) { + ret = asprintf(&debugfs_path, "/mnt/debugfs"); + if (ret < 0) { + perror("asprintf debugfs path"); + goto error; + } + ret = mount_debugfs(debugfs_path); + if (ret < 0) { + goto error; + } + } + + /* Modprobe lttng kernel modules */ + ret = modprobe_kernel_modules(); + if (ret < 0) { + goto error; + } + + /* Setup lttng kernel path */ + ret = asprintf(<tng_path, "%s/lttng", debugfs_path); + if (ret < 0) { + perror("asprintf lttng path"); + goto error; + } + + /* Open debugfs lttng */ + kernel_tracer_fd = open(lttng_path, O_RDWR); if (kernel_tracer_fd < 0) { - WARN("No kernel tracer available"); - kernel_tracer_fd = 0; + DBG("Failed to open %s", lttng_path); + goto error; } + free(lttng_path); + free(debugfs_path); DBG("Kernel tracer fd %d", kernel_tracer_fd); + return; + +error: + if (lttng_path) { + free(lttng_path); + } + if (debugfs_path) { + free(debugfs_path); + } + WARN("No kernel tracer available"); + kernel_tracer_fd = 0; + return; } /* @@ -723,6 +838,7 @@ static struct lttng_channel *init_default_channel(void) chan->attr.num_subbuf = DEFAULT_CHANNEL_SUBBUF_NUM; chan->attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; chan->attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; + chan->attr.output = DEFAULT_KERNEL_CHANNEL_OUTPUT; error: return chan; @@ -754,7 +870,7 @@ static int create_kernel_session(struct ltt_session *session) DBG("Creating default kernel channel %s", DEFAULT_CHANNEL_NAME); - ret = kernel_create_channel(session->kernel_session, chan); + ret = kernel_create_channel(session->kernel_session, chan, session->path); if (ret < 0) { ret = LTTCOMM_KERN_CHAN_FAIL; goto error; @@ -806,6 +922,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) * Check kernel command for kernel session. */ switch (cmd_ctx->lsm->cmd_type) { + case LTTNG_KERNEL_ADD_CONTEXT: case LTTNG_KERNEL_CREATE_CHANNEL: case LTTNG_KERNEL_DISABLE_ALL_EVENT: case LTTNG_KERNEL_DISABLE_CHANNEL: @@ -826,12 +943,14 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* Need a session for kernel command */ if (cmd_ctx->lsm->cmd_type != LTTNG_KERNEL_LIST_EVENTS && 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) { ret = start_kconsumerd(); if (ret < 0) { @@ -853,6 +972,84 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* Process by command type */ switch (cmd_ctx->lsm->cmd_type) { + case LTTNG_KERNEL_ADD_CONTEXT: + { + int found = 0, no_event = 0; + struct ltt_kernel_channel *chan; + struct ltt_kernel_event *event; + + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + /* Check if event name is given */ + if (strlen(cmd_ctx->lsm->u.context.event_name) == 0) { + no_event = 1; + } + + if (strlen(cmd_ctx->lsm->u.context.channel_name) == 0) { + /* Go over all channels */ + DBG("Adding context to all channels"); + cds_list_for_each_entry(chan, + &cmd_ctx->session->kernel_session->channel_list.head, list) { + if (no_event) { + ret = kernel_add_channel_context(chan, + &cmd_ctx->lsm->u.context.ctx); + if (ret < 0) { + continue; + } + } else { + event = get_kernel_event_by_name(cmd_ctx->lsm->u.context.event_name, chan); + if (event != NULL) { + ret = kernel_add_event_context(event, + &cmd_ctx->lsm->u.context.ctx); + if (ret < 0) { + ret = LTTCOMM_KERN_CONTEXT_FAIL; + goto error; + } + found = 1; + break; + } + } + } + } else { + chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.context.channel_name, + cmd_ctx->session->kernel_session); + if (chan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } + + if (no_event) { + ret = kernel_add_channel_context(chan, + &cmd_ctx->lsm->u.context.ctx); + if (ret < 0) { + ret = LTTCOMM_KERN_CONTEXT_FAIL; + goto error; + } + } else { + event = get_kernel_event_by_name(cmd_ctx->lsm->u.context.event_name, chan); + if (event != NULL) { + ret = kernel_add_event_context(event, + &cmd_ctx->lsm->u.context.ctx); + if (ret < 0) { + ret = LTTCOMM_KERN_CONTEXT_FAIL; + goto error; + } + } + } + } + + if (!found && !no_event) { + ret = LTTCOMM_NO_EVENT; + goto error; + } + + ret = LTTCOMM_OK; + break; + } case LTTNG_KERNEL_CREATE_CHANNEL: { /* Setup lttng message with no payload */ @@ -865,7 +1062,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) DBG("Creating kernel channel"); ret = kernel_create_channel(cmd_ctx->session->kernel_session, - &cmd_ctx->lsm->u.channel.chan); + &cmd_ctx->lsm->u.channel.chan, cmd_ctx->session->path); if (ret < 0) { ret = LTTCOMM_KERN_CHAN_FAIL; goto error; @@ -874,9 +1071,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx) ret = LTTCOMM_OK; break; } - case LTTNG_KERNEL_ENABLE_EVENT: + case LTTNG_KERNEL_DISABLE_CHANNEL: { - int found = 0; struct ltt_kernel_channel *chan; /* Setup lttng message with no payload */ @@ -885,36 +1081,167 @@ static int process_client_msg(struct command_ctx *cmd_ctx) goto setup_error; } - /* Get channel by name and create event for that channel */ - cds_list_for_each_entry(chan, &cmd_ctx->session->kernel_session->channel_list.head, list) { - if (strcmp(cmd_ctx->lsm->u.enable.channel_name, chan->channel->name) == 0) { - DBG("Creating kernel event %s for channel %s.", - cmd_ctx->lsm->u.enable.event.name, cmd_ctx->lsm->u.enable.channel_name); + chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, + cmd_ctx->session->kernel_session); + if (chan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } else if (chan->enabled == 1) { + ret = kernel_disable_channel(chan); + if (ret < 0) { + if (ret != EEXIST) { + ret = LTTCOMM_KERN_CHAN_DISABLE_FAIL; + } + goto error; + } + } - ret = kernel_create_event(chan, &cmd_ctx->lsm->u.enable.event); - if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; - goto error; + kernel_wait_quiescent(kernel_tracer_fd); + ret = LTTCOMM_OK; + break; + } + case LTTNG_KERNEL_DISABLE_EVENT: + { + struct ltt_kernel_channel *chan; + struct ltt_kernel_event *ev; + + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, + cmd_ctx->session->kernel_session); + if (chan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } + + ev = get_kernel_event_by_name(cmd_ctx->lsm->u.disable.name, chan); + if (ev != NULL) { + DBG("Disabling kernel event %s for channel %s.", + cmd_ctx->lsm->u.disable.name, cmd_ctx->lsm->u.disable.channel_name); + ret = kernel_disable_event(ev); + if (ret < 0) { + ret = LTTCOMM_KERN_ENABLE_FAIL; + goto error; + } + } + + kernel_wait_quiescent(kernel_tracer_fd); + ret = LTTCOMM_OK; + break; + } + case LTTNG_KERNEL_DISABLE_ALL_EVENT: + { + struct ltt_kernel_channel *chan; + struct ltt_kernel_event *ev; + + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + DBG("Disabling all enabled kernel events"); + + chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, + cmd_ctx->session->kernel_session); + if (chan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } + + /* For each event in the kernel session */ + cds_list_for_each_entry(ev, &chan->events_list.head, list) { + DBG("Disabling kernel event %s for channel %s.", + ev->event->name, cmd_ctx->lsm->u.disable.channel_name); + ret = kernel_disable_event(ev); + if (ret < 0) { + continue; + } + } + + /* Quiescent wait after event disable */ + kernel_wait_quiescent(kernel_tracer_fd); + ret = LTTCOMM_OK; + break; + } + case LTTNG_KERNEL_ENABLE_CHANNEL: + { + struct ltt_kernel_channel *chan; + + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.enable.channel_name, + cmd_ctx->session->kernel_session); + if (chan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } else if (chan->enabled == 0) { + ret = kernel_enable_channel(chan); + if (ret < 0) { + if (ret != EEXIST) { + ret = LTTCOMM_KERN_CHAN_ENABLE_FAIL; } - found = 1; - break; + goto error; } } - if (!found) { + kernel_wait_quiescent(kernel_tracer_fd); + ret = LTTCOMM_OK; + break; + } + case LTTNG_KERNEL_ENABLE_EVENT: + { + struct ltt_kernel_channel *chan; + struct ltt_kernel_event *ev; + + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.enable.channel_name, + cmd_ctx->session->kernel_session); + if (chan == NULL) { ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } + + ev = get_kernel_event_by_name(cmd_ctx->lsm->u.enable.event.name, chan); + if (ev == NULL) { + DBG("Creating kernel event %s for channel %s.", + cmd_ctx->lsm->u.enable.event.name, chan->channel->name); + ret = kernel_create_event(&cmd_ctx->lsm->u.enable.event, chan); } else { - kernel_wait_quiescent(kernel_tracer_fd); - ret = LTTCOMM_OK; + DBG("Enabling kernel event %s for channel %s.", + cmd_ctx->lsm->u.enable.event.name, chan->channel->name); + ret = kernel_enable_event(ev); + } + + if (ret < 0) { + ret = LTTCOMM_KERN_ENABLE_FAIL; + goto error; } + + kernel_wait_quiescent(kernel_tracer_fd); + ret = LTTCOMM_OK; break; } case LTTNG_KERNEL_ENABLE_ALL_EVENT: { - int pos, size, found; + int pos, size; char *event_list, *event, *ptr; struct ltt_kernel_channel *chan; - struct lttng_event ev; + struct ltt_kernel_event *ev; + struct lttng_event ev_attr; /* Setup lttng message with no payload */ ret = setup_lttng_msg(cmd_ctx, 0); @@ -924,36 +1251,43 @@ static int process_client_msg(struct command_ctx *cmd_ctx) DBG("Enabling all kernel event"); - size = kernel_list_events(kernel_tracer_fd, &event_list); - if (size < 0) { - ret = LTTCOMM_KERN_LIST_FAIL; + chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.enable.channel_name, + cmd_ctx->session->kernel_session); + if (chan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; goto error; } - /* Get channel by name and create event for that channel */ - cds_list_for_each_entry(chan, &cmd_ctx->session->kernel_session->channel_list.head, list) { - if (strcmp(cmd_ctx->lsm->u.enable.channel_name, chan->channel->name) == 0) { - found = 1; - break; + /* For each event in the kernel session */ + cds_list_for_each_entry(ev, &chan->events_list.head, list) { + DBG("Enabling kernel event %s for channel %s.", + ev->event->name, chan->channel->name); + ret = kernel_enable_event(ev); + if (ret < 0) { + continue; } } - if (!found) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + 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) { - strncpy(ev.name, event, LTTNG_SYM_NAME_LEN); - /* Default event type for enable all */ - ev.type = LTTNG_EVENT_TRACEPOINTS; - /* Enable each single tracepoint event */ - ret = kernel_create_event(chan, &ev); - if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; - goto error; + ev = get_kernel_event_by_name(event, chan); + if (ev == NULL) { + strncpy(ev_attr.name, event, LTTNG_SYM_NAME_LEN); + /* Default event type for enable all */ + ev_attr.type = LTTNG_EVENT_TRACEPOINTS; + /* Enable each single tracepoint event */ + ret = kernel_create_event(&ev_attr, chan); + if (ret < 0) { + /* Ignore error here and continue */ + } } + /* Move pointer to the next line */ ptr += pos + 1; free(event); @@ -1010,7 +1344,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx) 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); + ret = kernel_open_metadata(cmd_ctx->session->kernel_session, + cmd_ctx->session->path); if (ret < 0) { ret = LTTCOMM_KERN_META_FAIL; goto error; @@ -1539,32 +1874,13 @@ static int check_existing_daemon() return ret; } -/* - * get_home_dir - * - * Return pointer to home directory path using - * the env variable HOME. - * - * Default : /tmp - */ -static const char *get_home_dir(void) -{ - const char *home_path; - - if ((home_path = (const char *) getenv("HOME")) == NULL) { - home_path = default_home_dir; - } - - return home_path; -} - /* * set_permissions * * Set the tracing group gid onto the client socket. * * Race window between mkdir and chown is OK because we are going from - * less permissive (root.root) to more permissive (root.tracing). + * more permissive (root.root) to les permissive (root.tracing). */ static int set_permissions(void) { @@ -1577,8 +1893,13 @@ static int set_permissions(void) (grp = getgrnam(default_tracing_group)); if (grp == NULL) { - ERR("Missing tracing group. Aborting execution.\n"); - ret = -1; + if (is_root) { + WARN("No tracing group detected"); + ret = 0; + } else { + ERR("Missing tracing group. Aborting execution."); + ret = -1; + } goto end; } @@ -1773,6 +2094,7 @@ int main(int argc, char **argv) { int ret = 0; void *status; + const char *home_path; /* Parse arguments */ progname = argv[0]; @@ -1792,7 +2114,6 @@ int main(int argc, char **argv) /* Check if daemon is UID = 0 */ is_root = !getuid(); - /* Set all sockets path */ if (is_root) { ret = create_lttng_rundir(); if (ret < 0) { @@ -1820,15 +2141,22 @@ int main(int argc, char **argv) /* Set ulimit for open files */ set_ulimit(); } else { + home_path = get_home_dir(); + if (home_path == NULL) { + ERR("Can't get HOME directory for sockets creation.\n \ + Please specify --socket PATH."); + goto error; + } + if (strlen(apps_unix_sock_path) == 0) { snprintf(apps_unix_sock_path, PATH_MAX, - DEFAULT_HOME_APPS_UNIX_SOCK, get_home_dir()); + DEFAULT_HOME_APPS_UNIX_SOCK, home_path); } /* Set the cli tool unix socket path */ if (strlen(client_unix_sock_path) == 0) { snprintf(client_unix_sock_path, PATH_MAX, - DEFAULT_HOME_CLIENT_UNIX_SOCK, get_home_dir()); + DEFAULT_HOME_CLIENT_UNIX_SOCK, home_path); } }