From d980092014bba68425b9c63a020bfbc034dc9ad1 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Fri, 12 Aug 2011 16:26:18 -0400 Subject: [PATCH] Permit custom consumer registration to a session Introduce the new API call lttng_register_consumer(...). By giving a lttng_handle and a socket path, the fds will be sent to that socket for the specific tracing session and domain. No kernel consumer will be spawned by the session daemon for that session. At this point, only kernel consumer is supported. Signed-off-by: David Goulet --- include/lttng-sessiond-comm.h | 6 ++ include/lttng/lttng.h | 11 +++ liblttng-sessiond-comm/lttng-sessiond-comm.c | 1 + liblttngctl/lttngctl.c | 18 ++++ ltt-sessiond/main.c | 99 +++++++++++++++++--- ltt-sessiond/trace.c | 1 + ltt-sessiond/trace.h | 1 + tests/test_kernel_data_trace.c | 1 + 8 files changed, 127 insertions(+), 11 deletions(-) diff --git a/include/lttng-sessiond-comm.h b/include/lttng-sessiond-comm.h index f57b0cd5f..019f92ec5 100644 --- a/include/lttng-sessiond-comm.h +++ b/include/lttng-sessiond-comm.h @@ -63,6 +63,7 @@ enum lttcomm_sessiond_command { LTTNG_LIST_EVENTS, LTTNG_LIST_SESSIONS, LTTNG_LIST_TRACEPOINTS, + LTTNG_REGISTER_CONSUMER, LTTNG_START_TRACE, LTTNG_STOP_TRACE, }; @@ -91,6 +92,7 @@ enum lttcomm_return_code { LTTCOMM_SELECT_SESS, /* Must select a session */ LTTCOMM_EXIST_SESS, /* Session name already exist */ LTTCOMM_NO_EVENT, /* No event found */ + LTTCOMM_CONNECT_FAIL, /* Unable to connect to unix socket */ LTTCOMM_KERN_NA, /* Kernel tracer unavalable */ LTTCOMM_KERN_EVENT_EXIST, /* Kernel event already exists */ LTTCOMM_KERN_SESS_FAIL, /* Kernel create session failed */ @@ -154,6 +156,10 @@ struct lttcomm_session_msg { char event_name[NAME_MAX]; struct lttng_event_context ctx; } context; + /* Use by register_consumer */ + struct { + char path[PATH_MAX]; + } reg; /* List */ struct { char channel_name[NAME_MAX]; diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 3f96a24b6..1bdb66c61 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -293,6 +293,17 @@ extern int lttng_set_tracing_group(const char *name); */ extern const char *lttng_get_readable_code(int code); +/* + * This call permits to register an "outside consumer" to a session and a lttng + * domain. No consumer will be spawned and all fds/commands will go through the + * socket path given (socket_path). + * + * NOTE: At the moment, if you use the liblttkconsumerd, you can only use the + * command socket. The error socket is not supported yet for roaming consumers. + */ +extern int lttng_register_consumer(struct lttng_handle *handle, + const char *socket_path); + /* * Start tracing for *all* registered trace (kernel and user-space). */ diff --git a/liblttng-sessiond-comm/lttng-sessiond-comm.c b/liblttng-sessiond-comm/lttng-sessiond-comm.c index e370fcd35..9a540f0a6 100644 --- a/liblttng-sessiond-comm/lttng-sessiond-comm.c +++ b/liblttng-sessiond-comm/lttng-sessiond-comm.c @@ -51,6 +51,7 @@ static const char *lttcomm_readable_code[] = { [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_TRACEABLE) ] = "App is not traceable", [ LTTCOMM_ERR_INDEX(LTTCOMM_SELECT_SESS) ] = "A session MUST be selected", [ LTTCOMM_ERR_INDEX(LTTCOMM_EXIST_SESS) ] = "Session name already exist", + [ LTTCOMM_ERR_INDEX(LTTCOMM_CONNECT_FAIL) ] = "Unable to connect to Unix socket", [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_NA) ] = "Kernel tracer not available", [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_EVENT_EXIST) ] = "Kernel event already exists", [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_SESS_FAIL) ] = "Kernel create session failed", diff --git a/liblttngctl/lttngctl.c b/liblttngctl/lttngctl.c index 827de137e..51f5f6572 100644 --- a/liblttngctl/lttngctl.c +++ b/liblttngctl/lttngctl.c @@ -333,6 +333,24 @@ void lttng_destroy_handle(struct lttng_handle *handle) } } +/* + * Register an outside consumer. + */ +int lttng_register_consumer(struct lttng_handle *handle, + const char *socket_path) +{ + struct lttcomm_session_msg lsm; + + lsm.cmd_type = LTTNG_REGISTER_CONSUMER; + copy_string(lsm.session.name, handle->session_name, + sizeof(lsm.session.name)); + copy_lttng_domain(&lsm.domain, &handle->domain); + + copy_string(lsm.u.reg.path, socket_path, sizeof(lsm.u.reg.path)); + + return ask_sessiond(&lsm, NULL); +} + /* * Start tracing for all trace of the session. */ diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index 5a73b68df..b53eeb0e7 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -158,6 +158,15 @@ static void teardown_kernel_session(struct ltt_session *session) { if (session->kernel_session != NULL) { DBG("Tearing down kernel session"); + + /* + * If a custom kernel consumer was registered, close the socket before + * tearing down the complete kernel session structure + */ + if (session->kernel_session->consumer_fd != kconsumerd_cmd_sock) { + lttcomm_close_unix_sock(session->kernel_session->consumer_fd); + } + trace_destroy_kernel_session(session->kernel_session); /* Extra precaution */ session->kernel_session = NULL; @@ -313,7 +322,7 @@ error: /* * Send all stream fds of the kernel session to the consumer. */ -static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session) +static int send_kconsumerd_fds(struct ltt_kernel_session *session) { int ret; struct ltt_kernel_channel *chan; @@ -326,7 +335,7 @@ static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session) DBG("Sending kconsumerd header for metadata"); - ret = lttcomm_send_unix_sock(sock, &lkh, sizeof(struct lttcomm_kconsumerd_header)); + ret = lttcomm_send_unix_sock(session->consumer_fd, &lkh, sizeof(struct lttcomm_kconsumerd_header)); if (ret < 0) { perror("send kconsumerd header"); goto error; @@ -334,6 +343,11 @@ static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session) DBG("Sending metadata stream fd"); + /* Extra protection. It's NOT suppose to be set to 0 at this point */ + if (session->consumer_fd == 0) { + session->consumer_fd = kconsumerd_cmd_sock; + } + if (session->metadata_stream_fd != 0) { /* Send metadata stream fd first */ lkm.fd = session->metadata_stream_fd; @@ -343,7 +357,7 @@ static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session) strncpy(lkm.path_name, session->metadata->pathname, PATH_MAX); lkm.path_name[PATH_MAX - 1] = '\0'; - ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm)); + ret = lttcomm_send_fds_unix_sock(session->consumer_fd, &lkm, &lkm.fd, 1, sizeof(lkm)); if (ret < 0) { perror("send kconsumerd fd"); goto error; @@ -351,7 +365,7 @@ static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session) } cds_list_for_each_entry(chan, &session->channel_list.head, list) { - ret = send_kconsumerd_channel_fds(sock, chan); + ret = send_kconsumerd_channel_fds(session->consumer_fd, chan); if (ret < 0) { goto error; } @@ -550,6 +564,12 @@ static int update_kernel_stream(int fd) unlock_session(session); continue; } + + /* This is not suppose to be 0 but this is an extra security check */ + if (session->kernel_session->consumer_fd == 0) { + session->kernel_session->consumer_fd = kconsumerd_cmd_sock; + } + cds_list_for_each_entry(channel, &session->kernel_session->channel_list.head, list) { if (channel->fd == fd) { DBG("Channel found, updating kernel streams"); @@ -557,12 +577,14 @@ static int update_kernel_stream(int fd) if (ret < 0) { goto end; } + /* * Have we already sent fds to the consumer? If yes, it means that * tracing is started so it is safe to send our updated stream fds. */ if (session->kernel_session->kconsumer_fds_sent == 1) { - ret = send_kconsumerd_channel_fds(kconsumerd_cmd_sock, channel); + ret = send_kconsumerd_channel_fds(session->kernel_session->consumer_fd, + channel); if (ret < 0) { goto end; } @@ -887,6 +909,9 @@ error: return ret; } +/* + * Join kernel consumer thread + */ static int join_kconsumerd_thread(void) { void *status; @@ -1009,7 +1034,7 @@ static int modprobe_kernel_modules(void) ERR("Unable to launch modprobe for module %s", kernel_modules_list[i].name); } else if (kernel_modules_list[i].required - && WEXITSTATUS(ret) != 0) { + && WEXITSTATUS(ret) != 0) { ERR("Unable to load module %s", kernel_modules_list[i].name); } else { @@ -1045,7 +1070,7 @@ static int modprobe_remove_kernel_modules(void) ERR("Unable to launch modprobe --remove for module %s", kernel_modules_list[i].name); } else if (kernel_modules_list[i].required - && WEXITSTATUS(ret) != 0) { + && WEXITSTATUS(ret) != 0) { ERR("Unable to remove module %s", kernel_modules_list[i].name); } else { @@ -1173,7 +1198,16 @@ static int start_kernel_trace(struct ltt_kernel_session *session) int ret = 0; if (session->kconsumer_fds_sent == 0) { - ret = send_kconsumerd_fds(kconsumerd_cmd_sock, session); + /* + * Assign default kernel consumer if no consumer assigned to the kernel + * session. At this point, it's NOT suppose to be 0 but this is an extra + * security check. + */ + if (session->consumer_fd == 0) { + session->consumer_fd = kconsumerd_cmd_sock; + } + + ret = send_kconsumerd_fds(session); if (ret < 0) { ERR("Send kconsumerd fds failed"); ret = LTTCOMM_KERN_CONSUMER_FAIL; @@ -1247,6 +1281,11 @@ static int create_kernel_session(struct ltt_session *session) goto error; } + /* Set kernel consumer socket fd */ + if (kconsumerd_cmd_sock) { + session->kernel_session->consumer_fd = kconsumerd_cmd_sock; + } + ret = asprintf(&session->kernel_session->trace_path, "%s/kernel", session->path); if (ret < 0) { @@ -1412,10 +1451,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* Need a session for kernel command */ switch (cmd_ctx->lsm->cmd_type) { + case LTTNG_CALIBRATE: case LTTNG_CREATE_SESSION: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: - case LTTNG_CALIBRATE: break; default: if (cmd_ctx->session->kernel_session == NULL) { @@ -1426,7 +1465,9 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } /* Start the kernel consumer daemon */ - if (kconsumerd_pid == 0) { + + if (kconsumerd_pid == 0 && + cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) { ret = start_kconsumerd(); if (ret < 0) { goto error; @@ -2113,7 +2154,6 @@ static int process_client_msg(struct command_ctx *cmd_ctx) ret = LTTCOMM_OK; break; } - case LTTNG_CALIBRATE: { /* Setup lttng message with no payload */ @@ -2143,6 +2183,43 @@ static int process_client_msg(struct command_ctx *cmd_ctx) ret = LTTCOMM_OK; break; } + case LTTNG_REGISTER_CONSUMER: + { + int sock; + + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: + { + /* Can't register a consumer if there is already one */ + if (cmd_ctx->session->kernel_session->consumer_fd != 0) { + ret = LTTCOMM_CONNECT_FAIL; + goto error; + } + + sock = lttcomm_connect_unix_sock(cmd_ctx->lsm->u.reg.path); + if (sock < 0) { + ret = LTTCOMM_CONNECT_FAIL; + goto error; + } + + cmd_ctx->session->kernel_session->consumer_fd = sock; + break; + } + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; + } + + ret = LTTCOMM_OK; + break; + } default: /* Undefined command */ diff --git a/ltt-sessiond/trace.c b/ltt-sessiond/trace.c index 94d3c4946..774321e59 100644 --- a/ltt-sessiond/trace.c +++ b/ltt-sessiond/trace.c @@ -103,6 +103,7 @@ struct ltt_kernel_session *trace_create_kernel_session(void) lks->channel_count = 0; lks->stream_count_global = 0; lks->metadata = NULL; + lks->consumer_fd = 0; CDS_INIT_LIST_HEAD(&lks->channel_list.head); return lks; diff --git a/ltt-sessiond/trace.h b/ltt-sessiond/trace.h index 591af8573..9255bc932 100644 --- a/ltt-sessiond/trace.h +++ b/ltt-sessiond/trace.h @@ -84,6 +84,7 @@ struct ltt_kernel_session { int fd; int metadata_stream_fd; int kconsumer_fds_sent; + int consumer_fd; unsigned int channel_count; unsigned int stream_count_global; char *trace_path; diff --git a/tests/test_kernel_data_trace.c b/tests/test_kernel_data_trace.c index 93fa64cac..7a1f076c6 100644 --- a/tests/test_kernel_data_trace.c +++ b/tests/test_kernel_data_trace.c @@ -73,6 +73,7 @@ static void create_one_kernel_session(void) assert(kern->channel_count == 0); assert(kern->stream_count_global == 0); assert(kern->metadata == NULL); + assert(kern->consumer_fd == 0); PRINT_OK(); /* Init list in order to avoid sefaults from cds_list_del */ -- 2.34.1