Permit custom consumer registration to a session
authorDavid Goulet <david.goulet@polymtl.ca>
Fri, 12 Aug 2011 20:26:18 +0000 (16:26 -0400)
committerDavid Goulet <david.goulet@polymtl.ca>
Sat, 13 Aug 2011 16:01:04 +0000 (12:01 -0400)
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 <david.goulet@polymtl.ca>
include/lttng-sessiond-comm.h
include/lttng/lttng.h
liblttng-sessiond-comm/lttng-sessiond-comm.c
liblttngctl/lttngctl.c
ltt-sessiond/main.c
ltt-sessiond/trace.c
ltt-sessiond/trace.h
tests/test_kernel_data_trace.c

index f57b0cd5f51bad2de8701b506b013dbe3d791406..019f92ec51d6ec62a7e610cb40a3a32fea3f4429 100644 (file)
@@ -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];
index 3f96a24b695819560047dccf43831ade3fa46609..1bdb66c61e12dcbcccac846398b078d01f95cc28 100644 (file)
@@ -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).
  */
index e370fcd3542b9efddbbf40d90bc904f32264846d..9a540f0a6d0772ff2c8fadfc61a377b0582b7640 100644 (file)
@@ -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",
index 827de137e550ef33de57de09f0d823079d2fd513..51f5f6572e1a87da43400a439701efef1ca1d333 100644 (file)
@@ -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.
  */
index 5a73b68dfed46fb8c1878725b3727bb2c16e2787..b53eeb0e7a84219c17ece8b1dfab0ce349c83d00 100644 (file)
@@ -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 */
index 94d3c4946619c8429614b9f091f4000a91dd5ccc..774321e59a7d085edc8a5f50a5eae54652e3c15e 100644 (file)
@@ -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;
index 591af85730299c8c0832d11ab303236d4aeaed6d..9255bc93200d639d9c826b9c8d15fe00367551be 100644 (file)
@@ -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;
index 93fa64cac4a315873ecebeaa442429a8ca36b7c6..7a1f076c6e354fa21f34d505342c29f0c9d99a12 100644 (file)
@@ -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 */
This page took 0.031225 seconds and 4 git commands to generate.