From b4e3ceb9d379829bc5d6ec799f83086317aeafd8 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Fri, 28 Aug 2015 17:48:39 -0400 Subject: [PATCH] Transfer filter strings from sessiond to client MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Previously, the payload of the list events was a simple array of struct lttng_event. [event1][event2][event3] This patch adds an array of variable-length extended infos at the end of the event array: [event1][event2][event3][extinfo1][extinfo2][extinfo3] When received on the client side, the event structures are edited so that their new extended.ptr member points to their respective extended infos: [event1][event2][event3][extinfo1][extinfo2][extinfo3] \ \ \ ^ ^ ^ \ \ \____/_________/_________/ \ \__________/_________/ \________________/ This allows this whole block to be freed at once, so as to keep existing applications linked with liblttng-ctl working without being recompiled. The variable-length extended info has this layout for the moment: [extended info header][filter string] The extended info header contains the length of the subsequent filter string, including its terminal null character. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- include/lttng/event.h | 8 +- src/bin/lttng-sessiond/cmd.c | 111 ++++++++++++++++++++--- src/bin/lttng-sessiond/cmd.h | 2 +- src/bin/lttng-sessiond/main.c | 26 ++++-- src/common/sessiond-comm/sessiond-comm.h | 20 ++++ src/lib/lttng-ctl/lttng-ctl.c | 42 ++++++++- 6 files changed, 184 insertions(+), 25 deletions(-) diff --git a/include/lttng/event.h b/include/lttng/event.h index c90107cb3..06a63ccba 100644 --- a/include/lttng/event.h +++ b/include/lttng/event.h @@ -257,7 +257,13 @@ struct lttng_event { enum lttng_event_flag flags; /* Offset 284 */ - char padding[LTTNG_EVENT_PADDING1]; + char padding[4]; + + /* Offset 288 */ + union { + char padding[8]; + void *ptr; + } extended; /* Offset 296 */ /* Per event type configuration */ diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 821f01cd4..12bdf17cd 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -198,19 +198,48 @@ static void list_lttng_channels(enum lttng_domain_type domain, } } +static void increment_extended_len(const char *filter_expression, + size_t *extended_len) +{ + *extended_len += sizeof(struct lttcomm_event_extended_header); + + if (filter_expression) { + *extended_len += strlen(filter_expression) + 1; + } +} + +static void append_extended_info(const char *filter_expression, + void **extended_at) +{ + struct lttcomm_event_extended_header extended_header; + size_t filter_len = 0; + + if (filter_expression) { + filter_len = strlen(filter_expression) + 1; + } + + extended_header.filter_len = filter_len; + memcpy(*extended_at, &extended_header, sizeof(extended_header)); + *extended_at += sizeof(extended_header); + memcpy(*extended_at, filter_expression, filter_len); + *extended_at += filter_len; +} + /* * Create a list of agent domain events. * * Return number of events in list on success or else a negative value. */ static int list_lttng_agent_events(struct agent *agt, - struct lttng_event **events) + struct lttng_event **events, size_t *total_size) { int i = 0, ret = 0; unsigned int nb_event = 0; struct agent_event *event; struct lttng_event *tmp_events; struct lttng_ht_iter iter; + size_t extended_len = 0; + void *extended_at; assert(agt); assert(events); @@ -222,16 +251,34 @@ static int list_lttng_agent_events(struct agent *agt, rcu_read_unlock(); if (nb_event == 0) { ret = nb_event; + *total_size = 0; goto error; } - tmp_events = zmalloc(nb_event * sizeof(*tmp_events)); + /* Compute required extended infos size */ + extended_len = nb_event * sizeof(struct lttcomm_event_extended_header); + + /* + * This is only valid because the commands which add events are + * processed in the same thread as the listing. + */ + rcu_read_lock(); + cds_lfht_for_each_entry(agt->events->ht, &iter.iter, event, node.node) { + increment_extended_len(event->filter_expression, &extended_len); + } + rcu_read_unlock(); + + *total_size = nb_event * sizeof(*tmp_events) + extended_len; + tmp_events = zmalloc(*total_size); if (!tmp_events) { PERROR("zmalloc agent events session"); ret = -LTTNG_ERR_FATAL; goto error; } + extended_at = ((uint8_t *) tmp_events) + + nb_event * sizeof(struct lttng_event); + rcu_read_lock(); cds_lfht_for_each_entry(agt->events->ht, &iter.iter, event, node.node) { strncpy(tmp_events[i].name, event->name, sizeof(tmp_events[i].name)); @@ -240,6 +287,9 @@ static int list_lttng_agent_events(struct agent *agt, tmp_events[i].loglevel = event->loglevel_value; tmp_events[i].loglevel_type = event->loglevel_type; i++; + + /* Append extended info */ + append_extended_info(event->filter_expression, &extended_at); } rcu_read_unlock(); @@ -255,7 +305,8 @@ error: * Create a list of ust global domain events. */ static int list_lttng_ust_global_events(char *channel_name, - struct ltt_ust_domain_global *ust_global, struct lttng_event **events) + struct ltt_ust_domain_global *ust_global, + struct lttng_event **events, size_t *total_size) { int i = 0, ret = 0; unsigned int nb_event = 0; @@ -264,6 +315,8 @@ static int list_lttng_ust_global_events(char *channel_name, struct ltt_ust_channel *uchan; struct ltt_ust_event *uevent; struct lttng_event *tmp; + size_t extended_len = 0; + void *extended_at; DBG("Listing UST global events for channel %s", channel_name); @@ -281,21 +334,35 @@ static int list_lttng_ust_global_events(char *channel_name, nb_event = lttng_ht_get_count(uchan->events); if (nb_event == 0) { ret = nb_event; + *total_size = 0; goto error; } DBG3("Listing UST global %d events", nb_event); - tmp = zmalloc(nb_event * sizeof(struct lttng_event)); + /* Compute required extended infos size */ + cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) { + if (uevent->internal) { + nb_event--; + continue; + } + + increment_extended_len(uevent->filter_expression, + &extended_len); + } + + *total_size = nb_event * sizeof(struct lttng_event) + extended_len; + tmp = zmalloc(*total_size); if (tmp == NULL) { ret = LTTNG_ERR_FATAL; goto error; } + extended_at = ((uint8_t *) tmp) + nb_event * sizeof(struct lttng_event); + cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) { if (uevent->internal) { /* This event should remain hidden from clients */ - nb_event--; continue; } strncpy(tmp[i].name, uevent->attr.name, LTTNG_SYMBOL_NAME_LEN); @@ -333,6 +400,9 @@ static int list_lttng_ust_global_events(char *channel_name, tmp[i].exclusion = 1; } i++; + + /* Append extended info */ + append_extended_info(uevent->filter_expression, &extended_at); } ret = nb_event; @@ -347,12 +417,15 @@ error: * Fill lttng_event array of all kernel events in the channel. */ static int list_lttng_kernel_events(char *channel_name, - struct ltt_kernel_session *kernel_session, struct lttng_event **events) + struct ltt_kernel_session *kernel_session, + struct lttng_event **events, size_t *total_size) { int i = 0, ret; unsigned int nb_event; struct ltt_kernel_event *event; struct ltt_kernel_channel *kchan; + size_t extended_len = 0; + void *extended_at; kchan = trace_kernel_get_channel_by_name(channel_name, kernel_session); if (kchan == NULL) { @@ -365,16 +438,26 @@ static int list_lttng_kernel_events(char *channel_name, DBG("Listing events for channel %s", kchan->channel->name); if (nb_event == 0) { + *total_size = 0; *events = NULL; goto syscall; } - *events = zmalloc(nb_event * sizeof(struct lttng_event)); + /* Compute required extended infos size */ + cds_list_for_each_entry(event, &kchan->events_list.head, list) { + increment_extended_len(event->filter_expression, &extended_len); + } + + *total_size = nb_event * sizeof(struct lttng_event) + extended_len; + *events = zmalloc(*total_size); if (*events == NULL) { ret = LTTNG_ERR_FATAL; goto error; } + extended_at = ((uint8_t *) events) + + nb_event * sizeof(struct lttng_event); + /* Kernel channels */ cds_list_for_each_entry(event, &kchan->events_list.head , list) { strncpy((*events)[i].name, event->event->name, LTTNG_SYMBOL_NAME_LEN); @@ -413,6 +496,9 @@ static int list_lttng_kernel_events(char *channel_name, break; } i++; + + /* Append extended info */ + append_extended_info(event->filter_expression, &extended_at); } syscall: @@ -2771,7 +2857,7 @@ error: */ ssize_t cmd_list_events(enum lttng_domain_type domain, struct ltt_session *session, char *channel_name, - struct lttng_event **events) + struct lttng_event **events, size_t *total_size) { int ret = 0; ssize_t nb_event = 0; @@ -2780,14 +2866,16 @@ ssize_t cmd_list_events(enum lttng_domain_type domain, case LTTNG_DOMAIN_KERNEL: if (session->kernel_session != NULL) { nb_event = list_lttng_kernel_events(channel_name, - session->kernel_session, events); + session->kernel_session, events, + total_size); } break; case LTTNG_DOMAIN_UST: { if (session->ust_session != NULL) { nb_event = list_lttng_ust_global_events(channel_name, - &session->ust_session->domain_global, events); + &session->ust_session->domain_global, events, + total_size); } break; } @@ -2803,7 +2891,8 @@ ssize_t cmd_list_events(enum lttng_domain_type domain, &iter.iter, agt, node.node) { if (agt->domain == domain) { nb_event = list_lttng_agent_events( - agt, events); + agt, events, + total_size); break; } } diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index cbb39b6ce..e9c9054ea 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -79,7 +79,7 @@ ssize_t cmd_list_domains(struct ltt_session *session, struct lttng_domain **domains); ssize_t cmd_list_events(enum lttng_domain_type domain, struct ltt_session *session, char *channel_name, - struct lttng_event **events); + struct lttng_event **events, size_t *total_size); ssize_t cmd_list_channels(enum lttng_domain_type domain, struct ltt_session *session, struct lttng_channel **channels); ssize_t cmd_list_domains(struct ltt_session *session, diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 545f456e9..72232122c 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -899,12 +899,16 @@ static int setup_lttng_msg(struct command_ctx *cmd_ctx, cmd_ctx->lttng_msg_size = total_msg_size; /* Copy command header */ - memcpy(((uint8_t *) cmd_ctx->llm) + cmd_header_offset, cmd_header_buf, - cmd_header_len); + if (cmd_header_len) { + memcpy(((uint8_t *) cmd_ctx->llm) + cmd_header_offset, cmd_header_buf, + cmd_header_len); + } /* Copy payload */ - memcpy(((uint8_t *) cmd_ctx->llm) + payload_offset, payload_buf, - payload_len); + if (payload_len) { + memcpy(((uint8_t *) cmd_ctx->llm) + payload_offset, payload_buf, + payload_len); + } end: return ret; @@ -3866,17 +3870,23 @@ error_add_context: { ssize_t nb_event; struct lttng_event *events = NULL; + struct lttcomm_event_command_header cmd_header; + size_t total_size; + + /* Extended infos are included at the end of events */ + nb_event = cmd_list_events(cmd_ctx->lsm->domain.type, + cmd_ctx->session, cmd_ctx->lsm->u.list.channel_name, + &events, &total_size); - nb_event = cmd_list_events(cmd_ctx->lsm->domain.type, cmd_ctx->session, - cmd_ctx->lsm->u.list.channel_name, &events); if (nb_event < 0) { /* Return value is a negative lttng_error_code. */ ret = -nb_event; goto error; } - ret = setup_lttng_msg_no_cmd_header(cmd_ctx, events, - nb_event * sizeof(struct lttng_event)); + cmd_header.nb_events = nb_event; + ret = setup_lttng_msg(cmd_ctx, events, total_size, + &cmd_header, sizeof(cmd_header)); free(events); if (ret < 0) { diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index 675e54c2d..c38ed3745 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -341,6 +341,26 @@ struct lttng_event_exclusion { #define LTTNG_EVENT_EXCLUSION_NAME_AT(_exclusion, _i) \ (&(_exclusion)->names[_i][0]) +/* + * Event command header. + */ +struct lttcomm_event_command_header { + /* Number of events */ + uint32_t nb_events; +} LTTNG_PACKED; + +/* + * Event extended info header. This is the structure preceding each + * extended info data. + */ +struct lttcomm_event_extended_header { + /* + * Size of filter string immediately following this header. + * This size includes the terminal null character. + */ + uint32_t filter_len; +} LTTNG_PACKED; + /* * Data structure for the response from sessiond to the lttng client. */ diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index b47231e00..9cb2eb4a6 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -1726,6 +1726,10 @@ int lttng_list_events(struct lttng_handle *handle, { int ret; struct lttcomm_session_msg lsm; + struct lttcomm_event_command_header *cmd_header = NULL; + size_t cmd_header_len; + uint32_t nb_events, i; + void *extended_at; /* Safety check. An handle and channel name are mandatory */ if (handle == NULL || channel_name == NULL) { @@ -1738,17 +1742,47 @@ int lttng_list_events(struct lttng_handle *handle, sizeof(lsm.session.name)); lttng_ctl_copy_string(lsm.u.list.channel_name, channel_name, sizeof(lsm.u.list.channel_name)); - lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); - ret = lttng_ctl_ask_sessiond(&lsm, (void**) events); + ret = lttng_ctl_ask_sessiond_varlen(&lsm, NULL, 0, (void **) events, + (void **) &cmd_header, &cmd_header_len); if (ret < 0) { - return ret; + goto error; } - return ret / sizeof(struct lttng_event); + /* Set number of events and free command header */ + nb_events = cmd_header->nb_events; + if (nb_events > INT_MAX) { + ret = -EOVERFLOW; + goto error; + } + ret = (int) nb_events; + free(cmd_header); + cmd_header = NULL; + + /* Set extended info pointers */ + extended_at = ((void*) (*events)) + + nb_events * sizeof(struct lttng_event); + + for (i = 0; i < nb_events; i++) { + struct lttcomm_event_extended_header *ext_header; + struct lttng_event *event = &(*events)[i]; + + event->extended.ptr = extended_at; + ext_header = + (struct lttcomm_event_extended_header *) extended_at; + extended_at += sizeof(*ext_header); + extended_at += ext_header->filter_len; + } + + return ret; +error: + free(cmd_header); + free(*events); + return ret; } + /* * Sets the tracing_group variable with name. * This function allocates memory pointed to by tracing_group. -- 2.34.1