#include <config.h>
#include <lttng-consumerd.h>
+#include <lttng-ht.h>
#include <lttng-sessiond-comm.h>
#include <lttng/lttng-consumer.h>
#include <lttngerr.h>
+#include <runas.h>
#include "channel.h"
#include "compat/poll.h"
#include "context.h"
#include "event.h"
#include "futex.h"
-#include "hashtable.h"
#include "kernel.h"
#include "lttng-sessiond.h"
#include "shm.h"
char cmd_unix_sock_path[PATH_MAX];
};
+#include "benchmark.h"
+
/* Const values */
const char default_home_dir[] = DEFAULT_HOME_DIR;
const char default_tracing_group[] = LTTNG_DEFAULT_TRACING_GROUP;
int ust_consumerd64_fd = -1;
int ust_consumerd32_fd = -1;
-static const char *consumerd32_bin =
- __stringify(CONFIG_CONSUMERD32_BIN);
-static const char *consumerd64_bin =
- __stringify(CONFIG_CONSUMERD64_BIN);
-static const char *consumerd32_libdir =
- __stringify(CONFIG_CONSUMERD32_LIBDIR);
-static const char *consumerd64_libdir =
- __stringify(CONFIG_CONSUMERD64_LIBDIR);
+static const char *consumerd32_bin = CONFIG_CONSUMERD32_BIN;
+static const char *consumerd64_bin = CONFIG_CONSUMERD64_BIN;
+static const char *consumerd32_libdir = CONFIG_CONSUMERD32_LIBDIR;
+static const char *consumerd64_libdir = CONFIG_CONSUMERD64_LIBDIR;
static
void setup_consumerd_path(void)
close(thread_quit_pipe[0]);
close(thread_quit_pipe[1]);
+ /* OUTPUT BENCHMARK RESULTS */
+ bench_init();
+
+ if (getenv("BENCH_UST_NOTIFY")) {
+ bench_print_ust_notification();
+ }
+
+ if (getenv("BENCH_UST_REGISTER")) {
+ bench_print_ust_register();
+ bench_print_ust_unregister();
+ }
+
+ if (getenv("BENCH_BOOT_PROCESS")) {
+ bench_print_boot_process();
+ }
+
+ bench_close();
+ /* END BENCHMARK */
+
/* <fun> */
DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm"
"Matthew, BEET driven development works!%c[%dm",
DBG("Notifying applications of session daemon state: %d", active);
+ tracepoint(ust_notify_apps_start);
+
/* See shm.c for this call implying mmap, shm and futex calls */
wait_shm_mmap = shm_ust_get_mmap(wait_shm_path, is_root);
if (wait_shm_mmap == NULL) {
/* Wake waiting process */
futex_wait_update((int32_t *) wait_shm_mmap, active);
+ tracepoint(ust_notify_apps_stop);
+
/* Apps notified successfully */
return 0;
char tmp;
struct lttng_poll_event events;
+ tracepoint(sessiond_th_kern_start);
+
DBG("Thread manage kernel started");
ret = create_thread_poll_set(&events, 2);
/* Zeroed the poll events */
lttng_poll_reset(&events);
+ tracepoint(sessiond_th_kern_poll);
+
/* Poll infinite value of time */
ret = lttng_poll_wait(&events, -1);
if (ret < 0) {
struct lttng_poll_event events;
struct consumer_data *consumer_data = data;
+ tracepoint(sessiond_th_kcon_start);
+
DBG("[thread] Manage consumer started");
ret = lttcomm_listen_unix_sock(consumer_data->err_sock);
nb_fd = LTTNG_POLL_GETNB(&events);
+ tracepoint(sessiond_th_kcon_poll);
+
/* Inifinite blocking call, waiting for transmission */
ret = lttng_poll_wait(&events, -1);
if (ret < 0) {
struct ust_command ust_cmd;
struct lttng_poll_event events;
+ tracepoint(sessiond_th_apps_start);
+
DBG("[thread] Manage application started");
rcu_register_thread();
DBG("Apps thread polling on %d fds", nb_fd);
+ tracepoint(sessiond_th_apps_poll);
+
/* Inifinite blocking call, waiting for transmission */
ret = lttng_poll_wait(&events, -1);
if (ret < 0) {
ERR("Apps command pipe error");
goto error;
} else if (revents & LPOLLIN) {
+ tracepoint(ust_register_read_start);
/* Empty pipe */
ret = read(apps_cmd_pipe[0], &ust_cmd, sizeof(ust_cmd));
if (ret < 0 || ret < sizeof(ust_cmd)) {
perror("read apps cmd pipe");
goto error;
}
+ tracepoint(ust_register_read_stop);
+ tracepoint(ust_register_add_start);
/* Register applicaton to the session daemon */
ret = ust_app_register(&ust_cmd.reg_msg,
ust_cmd.sock);
} else if (ret < 0) {
break;
}
+ tracepoint(ust_register_add_stop);
+ tracepoint(ust_register_done_start);
/*
* Add channel(s) and event(s) to newly registered apps
* from lttng global UST domain.
*/
update_ust_app(ust_cmd.sock);
- ret = ustctl_register_done(ust_cmd.sock);
+ ret = ust_app_register_done(ust_cmd.sock);
if (ret < 0) {
/*
* If the registration is not possible, we simply
DBG("Apps with sock %d added to poll set",
ust_cmd.sock);
}
-
+ tracepoint(ust_register_done_stop);
break;
}
} else {
* the event at poll_wait.
*/
if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+ tracepoint(ust_unregister_start);
+
/* Removing from the poll set */
ret = lttng_poll_del(&events, pollfd);
if (ret < 0) {
/* Socket closed on remote end. */
ust_app_unregister(pollfd);
+
+ tracepoint(ust_unregister_stop);
break;
}
}
struct cds_wfq_node *node;
struct ust_command *ust_cmd = NULL;
+ tracepoint(sessiond_th_dispatch_start);
+
DBG("[thread] Dispatch UST command started");
while (!dispatch_thread_exit) {
futex_nto1_prepare(&ust_cmd_queue.futex);
do {
+ tracepoint(sessiond_th_dispatch_block);
+
/* Dequeue command for registration */
node = cds_wfq_dequeue_blocking(&ust_cmd_queue.queue);
if (node == NULL) {
break;
}
+ tracepoint(ust_dispatch_register_start);
+
ust_cmd = caa_container_of(node, struct ust_command, node);
DBG("Dispatching UST registration pid:%d ppid:%d uid:%d"
free(ust_cmd);
} while (node != NULL);
+ tracepoint(ust_dispatch_register_stop);
+
/* Futex wait on queue. Blocking call on futex() */
futex_nto1_wait(&ust_cmd_queue.futex);
}
*/
struct ust_command *ust_cmd = NULL;
+ tracepoint(sessiond_th_reg_start);
+
DBG("[thread] Manage application registration started");
ret = lttcomm_listen_unix_sock(apps_sock);
while (1) {
DBG("Accepting application registration");
+ tracepoint(sessiond_th_reg_poll);
+
nb_fd = LTTNG_POLL_GETNB(&events);
/* Inifinite blocking call, waiting for transmission */
ERR("Register apps socket poll error");
goto error;
} else if (revents & LPOLLIN) {
+ /* Registration starts here. Recording cycles */
+ tracepoint(ust_register_start);
+
sock = lttcomm_accept_unix_sock(apps_sock);
if (sock < 0) {
goto error;
* barrier with the exchange in cds_wfq_enqueue.
*/
futex_nto1_wake(&ust_cmd_queue.futex);
+
+ tracepoint(ust_register_stop);
}
}
}
/*
* Exec consumerd.
*/
- if (opt_verbose > 1 || opt_verbose_consumer) {
+ if (opt_verbose_consumer) {
verbosity = "--verbose";
} else {
verbosity = "--quiet";
* sessiond's installation directory, and
* fallback on the 32-bit one,
*/
+ DBG3("Looking for a kernel consumer at these locations:");
+ DBG3(" 1) %s", consumerd64_bin);
+ DBG3(" 2) %s/%s", INSTALL_BIN_PATH, CONSUMERD_FILE);
+ DBG3(" 3) %s", consumerd32_bin);
if (stat(consumerd64_bin, &st) == 0) {
+ DBG3("Found location #1");
consumer_to_use = consumerd64_bin;
} else if (stat(INSTALL_BIN_PATH "/" CONSUMERD_FILE, &st) == 0) {
+ DBG3("Found location #2");
consumer_to_use = INSTALL_BIN_PATH "/" CONSUMERD_FILE;
} else if (stat(consumerd32_bin, &st) == 0) {
+ DBG3("Found location #3");
consumer_to_use = consumerd32_bin;
} else {
+ DBG("Could not find any valid consumerd executable");
break;
}
DBG("Using kernel consumer at: %s", consumer_to_use);
return ret;
}
+/*
+ * Check if the UID or GID match the session. Root user has access to
+ * all sessions.
+ */
+static int session_access_ok(struct ltt_session *session,
+ uid_t uid, gid_t gid)
+{
+ if (uid != session->uid && gid != session->gid
+ && uid != 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+static unsigned int lttng_sessions_count(uid_t uid, gid_t gid)
+{
+ unsigned int i = 0;
+ struct ltt_session *session;
+
+ DBG("Counting number of available session for UID %d GID %d",
+ uid, gid);
+ cds_list_for_each_entry(session, &session_list_ptr->head, list) {
+ /*
+ * Only list the sessions the user can control.
+ */
+ if (!session_access_ok(session, uid, gid)) {
+ continue;
+ }
+ i++;
+ }
+ return i;
+}
+
/*
* Using the session list, filled a lttng_session array to send back to the
* client for session listing.
* The session list lock MUST be acquired before calling this function. Use
* session_lock_list() and session_unlock_list().
*/
-static void list_lttng_sessions(struct lttng_session *sessions)
+static void list_lttng_sessions(struct lttng_session *sessions,
+ uid_t uid, gid_t gid)
{
- int i = 0;
+ unsigned int i = 0;
struct ltt_session *session;
- DBG("Getting all available session");
+ DBG("Getting all available session for UID %d GID %d",
+ uid, gid);
/*
* Iterate over session list and append data after the control struct in
* the buffer.
*/
cds_list_for_each_entry(session, &session_list_ptr->head, list) {
+ /*
+ * Only list the sessions the user can control.
+ */
+ if (!session_access_ok(session, uid, gid)) {
+ continue;
+ }
strncpy(sessions[i].path, session->path, PATH_MAX);
sessions[i].path[PATH_MAX - 1] = '\0';
strncpy(sessions[i].name, session->name, NAME_MAX);
break;
case LTTNG_DOMAIN_UST:
{
- struct cds_lfht_iter iter;
+ struct lttng_ht_iter iter;
struct ltt_ust_channel *uchan;
- cds_lfht_for_each_entry(session->ust_session->domain_global.channels,
- &iter, uchan, node) {
+ cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
+ &iter.iter, uchan, node.node) {
strncpy(channels[i].name, uchan->name, LTTNG_SYMBOL_NAME_LEN);
channels[i].attr.overwrite = uchan->attr.overwrite;
channels[i].attr.subbuf_size = uchan->attr.subbuf_size;
{
int i = 0, ret = 0;
unsigned int nb_event = 0;
- struct cds_lfht_iter iter;
- struct cds_lfht_node *node;
+ struct lttng_ht_iter iter;
+ struct lttng_ht_node_str *node;
struct ltt_ust_channel *uchan;
struct ltt_ust_event *uevent;
struct lttng_event *tmp;
rcu_read_lock();
- node = hashtable_lookup(ust_global->channels, (void *) channel_name,
- strlen(channel_name), &iter);
+ lttng_ht_lookup(ust_global->channels, (void *)channel_name, &iter);
+ node = lttng_ht_iter_get_node_str(&iter);
if (node == NULL) {
ret = -LTTCOMM_UST_CHAN_NOT_FOUND;
goto error;
}
- uchan = caa_container_of(node, struct ltt_ust_channel, node);
+ uchan = caa_container_of(&node->node, struct ltt_ust_channel, node.node);
- nb_event += hashtable_get_count(uchan->events);
+ nb_event += lttng_ht_get_count(uchan->events);
if (nb_event == 0) {
ret = nb_event;
goto error;
}
- cds_lfht_for_each_entry(uchan->events, &iter, uevent, node) {
+ cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) {
strncpy(tmp[i].name, uevent->attr.name, LTTNG_SYMBOL_NAME_LEN);
tmp[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
tmp[i].enabled = uevent->enabled;
case LTTNG_DOMAIN_UST:
{
struct ltt_ust_channel *uchan;
- struct cds_lfht *chan_ht;
+ struct lttng_ht *chan_ht;
chan_ht = usess->domain_global.channels;
{
int ret;
struct ltt_ust_session *usess = session->ust_session;
- struct cds_lfht *chan_ht;
+ struct lttng_ht *chan_ht;
DBG("Enabling channel %s for session %s", attr->name, session->name);
}
/* At this point, the session and channel exist on the tracer */
-
ret = event_ust_enable_tracepoint(usess, domain, uchan, event);
if (ret != LTTCOMM_OK) {
goto error;
usess = session->ust_session;
if (!session->enabled) {
- ret = LTTCOMM_UST_START_FAIL;
+ ret = LTTCOMM_UST_STOP_FAIL;
goto error;
}
ret = ust_app_stop_trace_all(usess);
if (ret < 0) {
- ret = LTTCOMM_UST_START_FAIL;
+ ret = LTTCOMM_UST_STOP_FAIL;
goto error;
}
}
break;
case LTTNG_DOMAIN_UST:
if (session->ust_session != NULL) {
- nb_chan = hashtable_get_count(
+ nb_chan = lttng_ht_get_count(
session->ust_session->domain_global.channels);
}
DBG3("Number of UST global channels %zd", nb_chan);
break;
}
+ /*
+ * Check that the UID or GID match that of the tracing session.
+ * The root user can interact with all sessions.
+ */
+ if (need_tracing_session) {
+ if (!session_access_ok(cmd_ctx->session,
+ cmd_ctx->creds.uid, cmd_ctx->creds.gid)) {
+ ret = LTTCOMM_EPERM;
+ goto error;
+ }
+ }
+
/* Process by command type */
switch (cmd_ctx->lsm->cmd_type) {
case LTTNG_ADD_CONTEXT:
}
case LTTNG_CREATE_SESSION:
{
+ tracepoint(create_session_start);
ret = cmd_create_session(cmd_ctx->lsm->session.name,
cmd_ctx->lsm->session.path, &cmd_ctx->creds);
+ tracepoint(create_session_end);
break;
}
case LTTNG_DESTROY_SESSION:
{
+ tracepoint(destroy_session_start);
ret = cmd_destroy_session(cmd_ctx->session,
cmd_ctx->lsm->session.name);
+ tracepoint(destroy_session_end);
break;
}
case LTTNG_LIST_DOMAINS:
}
case LTTNG_LIST_SESSIONS:
{
- session_lock_list();
+ unsigned int nr_sessions;
- if (session_list_ptr->count == 0) {
+ session_lock_list();
+ nr_sessions = lttng_sessions_count(cmd_ctx->creds.uid, cmd_ctx->creds.gid);
+ if (nr_sessions == 0) {
ret = LTTCOMM_NO_SESSION;
session_unlock_list();
goto error;
}
-
- ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_session) *
- session_list_ptr->count);
+ ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_session) * nr_sessions);
if (ret < 0) {
session_unlock_list();
goto setup_error;
}
/* Filled the session array */
- list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload));
+ list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload),
+ cmd_ctx->creds.uid, cmd_ctx->creds.gid);
session_unlock_list();
struct command_ctx *cmd_ctx = NULL;
struct lttng_poll_event events;
+ tracepoint(sessiond_th_cli_start);
+
DBG("[thread] Manage client started");
rcu_register_thread();
while (1) {
DBG("Accepting client command ...");
+ tracepoint(sessiond_th_cli_poll);
+
nb_fd = LTTNG_POLL_GETNB(&events);
/* Inifinite blocking call, waiting for transmission */
void *status;
const char *home_path;
+ tracepoint(sessiond_boot_start);
rcu_register_thread();
/* Create thread quit pipe */
goto exit_kernel;
}
+ tracepoint(sessiond_boot_end);
+
ret = pthread_join(kernel_thread, &status);
if (ret != 0) {
perror("pthread_join");