From 33b9609d08bf77e0afcb34d8d14b6fee44ffa0aa Mon Sep 17 00:00:00 2001 From: Jonathan Rajotte Date: Wed, 12 Jan 2022 18:18:08 -0500 Subject: [PATCH] Fix: liblttng-ctl comm: lttng_channel is not packed MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Observed issue ============== The size of the struct differs between bitness for x86-64 and x86 leading to serialization/deserialization problem across client (liblttng-ctl) and lttng-sessiond. sizeof(struct lttng_channel): x86: 608 x86-64: 624 The struct cannot be marked as LTTNG_PACKED since it is part of the API. Solution ======== Adopt a similar pattern to the new API with a "serialize" & "create_from_buffer" approach. The only particularity is that we need to flatten the channels on listing. Most of the complexity is moved to `src/common/channel.c` Known drawbacks ========= None. Signed-off-by: Jonathan Rajotte Signed-off-by: Jérémie Galarneau Change-Id: I59b0e92286e36c4f183d2950417cb180d4efc200 --- include/lttng/channel-internal.h | 51 +++ src/bin/lttng-sessiond/channel.c | 53 +++ src/bin/lttng-sessiond/channel.h | 3 + src/bin/lttng-sessiond/client.c | 32 +- src/bin/lttng-sessiond/cmd.c | 364 +++++++++--------- src/bin/lttng-sessiond/cmd.h | 11 +- src/bin/lttng-sessiond/trace-ust.h | 1 + src/common/Makefile.am | 1 + src/common/channel.c | 467 +++++++++++++++++++++++ src/common/sessiond-comm/sessiond-comm.h | 12 +- src/lib/lttng-ctl/lttng-ctl.c | 187 ++++----- 11 files changed, 884 insertions(+), 298 deletions(-) create mode 100644 src/common/channel.c diff --git a/include/lttng/channel-internal.h b/include/lttng/channel-internal.h index 04b19322f..2e9590836 100644 --- a/include/lttng/channel-internal.h +++ b/include/lttng/channel-internal.h @@ -9,6 +9,10 @@ #define LTTNG_CHANNEL_INTERNAL_H #include +#include + +struct lttng_dynamic_buffer; +struct lttng_buffer_view; struct lttng_channel_extended { uint64_t discarded_events; @@ -17,4 +21,51 @@ struct lttng_channel_extended { int64_t blocking_timeout; } LTTNG_PACKED; +struct lttng_channel_comm { + /* Includes terminator `\0`. */ + uint32_t name_len; + uint8_t enabled; + + /* attr */ + int8_t overwrite; + uint64_t subbuf_size; + uint64_t num_subbuf; + uint32_t switch_timer_interval; + uint32_t read_timer_interval; + uint8_t output; + uint64_t tracefile_size; + uint64_t tracefile_count; + uint32_t live_timer_interval; + + /* Extended struct */ + uint64_t discarded_events; + uint64_t lost_packets; + uint64_t monitor_timer_interval; + int64_t blocking_timeout; +} LTTNG_PACKED; + +LTTNG_HIDDEN +struct lttng_channel *lttng_channel_create_internal(void); + +LTTNG_HIDDEN +struct lttng_channel *lttng_channel_copy(const struct lttng_channel *src); + +LTTNG_HIDDEN +ssize_t lttng_channel_create_from_buffer(const struct lttng_buffer_view *view, + struct lttng_channel **event); + +LTTNG_HIDDEN +int lttng_channel_serialize(struct lttng_channel *channel, + struct lttng_dynamic_buffer *buf); + +LTTNG_HIDDEN +void lttng_channel_set_default_extended_attr(struct lttng_domain *domain, + struct lttng_channel_extended *extended_attr); + +LTTNG_HIDDEN +enum lttng_error_code lttng_channels_create_and_flatten_from_buffer( + const struct lttng_buffer_view *view, + unsigned int count, + struct lttng_channel **channels); + #endif /* LTTNG_CHANNEL_INTERNAL_H */ diff --git a/src/bin/lttng-sessiond/channel.c b/src/bin/lttng-sessiond/channel.c index e2596ce58..365b24a59 100644 --- a/src/bin/lttng-sessiond/channel.c +++ b/src/bin/lttng-sessiond/channel.c @@ -544,3 +544,56 @@ end: error: return ret; } + +struct lttng_channel *trace_ust_channel_to_lttng_channel( + const struct ltt_ust_channel *uchan) +{ + struct lttng_channel *channel = NULL, *ret = NULL; + + channel = lttng_channel_create_internal(); + if (!channel) { + goto end; + } + + if (lttng_strncpy(channel->name, uchan->name, LTTNG_SYMBOL_NAME_LEN)) { + goto end; + } + + channel->attr.overwrite = uchan->attr.overwrite; + channel->attr.subbuf_size = uchan->attr.subbuf_size; + channel->attr.num_subbuf = uchan->attr.num_subbuf; + channel->attr.switch_timer_interval = uchan->attr.switch_timer_interval; + channel->attr.read_timer_interval = uchan->attr.read_timer_interval; + channel->enabled = uchan->enabled; + channel->attr.tracefile_size = uchan->tracefile_size; + channel->attr.tracefile_count = uchan->tracefile_count; + + /* + * Map enum lttng_ust_output to enum lttng_event_output. + */ + switch (uchan->attr.output) { + case LTTNG_UST_MMAP: + channel->attr.output = LTTNG_EVENT_MMAP; + break; + default: + /* + * LTTNG_UST_MMAP is the only supported UST + * output mode. + */ + abort(); + break; + } + + lttng_channel_set_blocking_timeout( + channel, uchan->attr.u.s.blocking_timeout); + lttng_channel_set_monitor_timer_interval( + channel, uchan->monitor_timer_interval); + + ret = channel; + channel = NULL; + +end: + lttng_channel_destroy(channel); + + return ret; +} diff --git a/src/bin/lttng-sessiond/channel.h b/src/bin/lttng-sessiond/channel.h index b4ff9f4fd..1b6e29bd7 100644 --- a/src/bin/lttng-sessiond/channel.h +++ b/src/bin/lttng-sessiond/channel.h @@ -31,4 +31,7 @@ int channel_ust_enable(struct ltt_ust_session *usess, int channel_ust_disable(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan); +struct lttng_channel *trace_ust_channel_to_lttng_channel( + const struct ltt_ust_channel *uchan); + #endif /* _LTT_CHANNEL_H */ diff --git a/src/bin/lttng-sessiond/client.c b/src/bin/lttng-sessiond/client.c index be907ebe3..5e95a59f0 100644 --- a/src/bin/lttng-sessiond/client.c +++ b/src/bin/lttng-sessiond/client.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "client.h" @@ -716,6 +717,9 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, int ret = LTTNG_OK; int need_tracing_session = 1; int need_domain; + struct lttng_dynamic_buffer payload; + + lttng_dynamic_buffer_init(&payload); DBG("Processing client command %d", cmd_ctx->lsm->cmd_type); @@ -1195,12 +1199,7 @@ error_add_context: } case LTTNG_ENABLE_CHANNEL: { - cmd_ctx->lsm->u.channel.chan.attr.extended.ptr = - (struct lttng_channel_extended *) &cmd_ctx->lsm->u.channel.extended; - ret = cmd_enable_channel(cmd_ctx->session, - ALIGNED_CONST_PTR(cmd_ctx->lsm->domain), - ALIGNED_CONST_PTR(cmd_ctx->lsm->u.channel.chan), - kernel_poll_pipe[1]); + ret = cmd_enable_channel(cmd_ctx, *sock, kernel_poll_pipe[1]); break; } case LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE: @@ -1706,20 +1705,20 @@ error_add_context: } case LTTNG_LIST_CHANNELS: { - ssize_t payload_size; - struct lttng_channel *channels = NULL; + uint32_t nb_channel; + enum lttng_error_code ret_code; + struct lttcomm_list_command_header cmd_header = { 0 }; - payload_size = cmd_list_channels(cmd_ctx->lsm->domain.type, - cmd_ctx->session, &channels); - if (payload_size < 0) { - /* Return value is a negative lttng_error_code. */ - ret = -payload_size; + ret_code = cmd_list_channels(cmd_ctx->lsm->domain.type, + cmd_ctx->session, &payload, &nb_channel); + if (ret_code != LTTNG_OK) { + ret = (int) ret_code; goto error; } - ret = setup_lttng_msg_no_cmd_header(cmd_ctx, channels, - payload_size); - free(channels); + cmd_header.count = nb_channel; + ret = setup_lttng_msg(cmd_ctx, payload.data, payload.size, + &cmd_header, sizeof(cmd_header)); if (ret < 0) { goto setup_error; @@ -2108,6 +2107,7 @@ setup_error: } init_setup_error: assert(!rcu_read_ongoing()); + lttng_dynamic_buffer_reset(&payload); return ret; } diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 655e4727d..01dc3bb74 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -111,6 +111,10 @@ static int cmd_enable_event_internal(struct ltt_session *session, struct lttng_filter_bytecode *filter, struct lttng_event_exclusion *exclusion, int wpipe); +static int cmd_enable_channel_internal(struct ltt_session *session, + const struct lttng_domain *domain, + const struct lttng_channel *_attr, + int wpipe); /* * Create a session path used by list_lttng_sessions for the case that the @@ -281,118 +285,6 @@ end: return ret; } -/* - * Fill lttng_channel array of all channels. - */ -static ssize_t list_lttng_channels(enum lttng_domain_type domain, - struct ltt_session *session, struct lttng_channel *channels, - struct lttng_channel_extended *chan_exts) -{ - int i = 0, ret = 0; - struct ltt_kernel_channel *kchan; - - DBG("Listing channels for session %s", session->name); - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - /* Kernel channels */ - if (session->kernel_session != NULL) { - cds_list_for_each_entry(kchan, - &session->kernel_session->channel_list.head, list) { - uint64_t discarded_events, lost_packets; - struct lttng_channel_extended *extended; - - extended = (struct lttng_channel_extended *) - kchan->channel->attr.extended.ptr; - - ret = get_kernel_runtime_stats(session, kchan, - &discarded_events, &lost_packets); - if (ret < 0) { - goto end; - } - /* Copy lttng_channel struct to array */ - memcpy(&channels[i], kchan->channel, sizeof(struct lttng_channel)); - channels[i].enabled = kchan->enabled; - chan_exts[i].discarded_events = - discarded_events; - chan_exts[i].lost_packets = lost_packets; - chan_exts[i].monitor_timer_interval = - extended->monitor_timer_interval; - chan_exts[i].blocking_timeout = 0; - i++; - } - } - break; - case LTTNG_DOMAIN_UST: - { - struct lttng_ht_iter iter; - struct ltt_ust_channel *uchan; - - rcu_read_lock(); - cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, - &iter.iter, uchan, node.node) { - uint64_t discarded_events = 0, lost_packets = 0; - - if (lttng_strncpy(channels[i].name, uchan->name, - LTTNG_SYMBOL_NAME_LEN)) { - break; - } - channels[i].attr.overwrite = uchan->attr.overwrite; - channels[i].attr.subbuf_size = uchan->attr.subbuf_size; - channels[i].attr.num_subbuf = uchan->attr.num_subbuf; - channels[i].attr.switch_timer_interval = - uchan->attr.switch_timer_interval; - channels[i].attr.read_timer_interval = - uchan->attr.read_timer_interval; - channels[i].enabled = uchan->enabled; - channels[i].attr.tracefile_size = uchan->tracefile_size; - channels[i].attr.tracefile_count = uchan->tracefile_count; - - /* - * Map enum lttng_ust_output to enum lttng_event_output. - */ - switch (uchan->attr.output) { - case LTTNG_UST_MMAP: - channels[i].attr.output = LTTNG_EVENT_MMAP; - break; - default: - /* - * LTTNG_UST_MMAP is the only supported UST - * output mode. - */ - assert(0); - break; - } - - chan_exts[i].monitor_timer_interval = - uchan->monitor_timer_interval; - chan_exts[i].blocking_timeout = - uchan->attr.u.s.blocking_timeout; - - ret = get_ust_runtime_stats(session, uchan, - &discarded_events, &lost_packets); - if (ret < 0) { - break; - } - chan_exts[i].discarded_events = discarded_events; - chan_exts[i].lost_packets = lost_packets; - i++; - } - rcu_read_unlock(); - break; - } - default: - break; - } - -end: - if (ret < 0) { - return -LTTNG_ERR_FATAL; - } else { - return LTTNG_OK; - } -} - static int increment_extended_len(const char *filter_expression, struct lttng_event_exclusion *exclusion, const struct lttng_userspace_probe_location *probe_location, @@ -1434,30 +1326,84 @@ error: * * The wpipe arguments is used as a notifier for the kernel thread. */ -int cmd_enable_channel(struct ltt_session *session, - const struct lttng_domain *domain, const struct lttng_channel *_attr, int wpipe) +int cmd_enable_channel(struct command_ctx *cmd_ctx, int sock, int wpipe) +{ + int ret; + size_t channel_len; + ssize_t sock_recv_len; + struct lttng_channel *channel = NULL; + struct lttng_buffer_view view; + struct lttng_dynamic_buffer channel_buffer; + + lttng_dynamic_buffer_init(&channel_buffer); + channel_len = (size_t) cmd_ctx->lsm->u.channel.length; + ret = lttng_dynamic_buffer_set_size(&channel_buffer, channel_len); + if (ret) { + ret = LTTNG_ERR_NOMEM; + goto end; + } + + sock_recv_len = lttcomm_recv_unix_sock(sock, channel_buffer.data, + channel_len); + if (sock_recv_len < 0 || sock_recv_len != channel_len) { + ERR("Failed to receive \"enable channel\" command payload"); + ret = LTTNG_ERR_INVALID; + goto end; + } + + view = lttng_buffer_view_from_dynamic_buffer(&channel_buffer, 0, channel_len); + if (!lttng_buffer_view_is_valid(&view)) { + ret = LTTNG_ERR_INVALID; + goto end; + } + + if (lttng_channel_create_from_buffer(&view, &channel) != channel_len) { + ERR("Invalid channel payload received in \"enable channel\" command"); + ret = LTTNG_ERR_INVALID; + goto end; + } + + ret = cmd_enable_channel_internal(cmd_ctx->session, + ALIGNED_CONST_PTR(cmd_ctx->lsm->domain), channel, + wpipe); + +end: + lttng_dynamic_buffer_reset(&channel_buffer); + lttng_channel_destroy(channel); + return ret; +} + +static int cmd_enable_channel_internal(struct ltt_session *session, + const struct lttng_domain *domain, + const struct lttng_channel *_attr, + int wpipe) { int ret; struct ltt_ust_session *usess = session->ust_session; struct lttng_ht *chan_ht; size_t len; - struct lttng_channel attr; + struct lttng_channel *attr = NULL; assert(session); assert(_attr); assert(domain); - attr = *_attr; - len = lttng_strnlen(attr.name, sizeof(attr.name)); + attr = lttng_channel_copy(_attr); + if (!attr) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + + len = lttng_strnlen(attr->name, sizeof(attr->name)); /* Validate channel name */ - if (attr.name[0] == '.' || - memchr(attr.name, '/', len) != NULL) { + if (attr->name[0] == '.' || + memchr(attr->name, '/', len) != NULL) { ret = LTTNG_ERR_INVALID_CHANNEL_NAME; goto end; } - DBG("Enabling channel %s for session %s", attr.name, session->name); + DBG("Enabling channel %s for session %s", attr->name, session->name); rcu_read_lock(); @@ -1467,8 +1413,8 @@ int cmd_enable_channel(struct ltt_session *session, * beacons for inactive streams. */ if (session->live_timer > 0) { - attr.attr.live_timer_interval = session->live_timer; - attr.attr.switch_timer_interval = 0; + attr->attr.live_timer_interval = session->live_timer; + attr->attr.switch_timer_interval = 0; } /* Check for feature support */ @@ -1480,8 +1426,8 @@ int cmd_enable_channel(struct ltt_session *session, WARN("Kernel tracer does not support buffer monitoring. " "Setting the monitor interval timer to 0 " "(disabled) for channel '%s' of session '%s'", - attr.name, session->name); - lttng_channel_set_monitor_timer_interval(&attr, 0); + attr->name, session->name); + lttng_channel_set_monitor_timer_interval(attr, 0); } break; } @@ -1506,8 +1452,8 @@ int cmd_enable_channel(struct ltt_session *session, { struct ltt_kernel_channel *kchan; - kchan = trace_kernel_get_channel_by_name(attr.name, - session->kernel_session); + kchan = trace_kernel_get_channel_by_name( + attr->name, session->kernel_session); if (kchan == NULL) { /* * Don't try to create a channel if the session has been started at @@ -1521,10 +1467,11 @@ int cmd_enable_channel(struct ltt_session *session, if (session->snapshot.nb_output > 0 || session->snapshot_mode) { /* Enforce mmap output for snapshot sessions. */ - attr.attr.output = LTTNG_EVENT_MMAP; + attr->attr.output = LTTNG_EVENT_MMAP; } - ret = channel_kernel_create(session->kernel_session, &attr, wpipe); - if (attr.name[0] != '\0') { + ret = channel_kernel_create( + session->kernel_session, attr, wpipe); + if (attr->name[0] != '\0') { session->kernel_session->has_non_default_channel = 1; } } else { @@ -1554,19 +1501,19 @@ int cmd_enable_channel(struct ltt_session *session, * adhered to. */ if (domain->type == LTTNG_DOMAIN_JUL) { - if (strncmp(attr.name, DEFAULT_JUL_CHANNEL_NAME, + if (strncmp(attr->name, DEFAULT_JUL_CHANNEL_NAME, LTTNG_SYMBOL_NAME_LEN)) { ret = LTTNG_ERR_INVALID_CHANNEL_NAME; goto error; } } else if (domain->type == LTTNG_DOMAIN_LOG4J) { - if (strncmp(attr.name, DEFAULT_LOG4J_CHANNEL_NAME, + if (strncmp(attr->name, DEFAULT_LOG4J_CHANNEL_NAME, LTTNG_SYMBOL_NAME_LEN)) { ret = LTTNG_ERR_INVALID_CHANNEL_NAME; goto error; } } else if (domain->type == LTTNG_DOMAIN_PYTHON) { - if (strncmp(attr.name, DEFAULT_PYTHON_CHANNEL_NAME, + if (strncmp(attr->name, DEFAULT_PYTHON_CHANNEL_NAME, LTTNG_SYMBOL_NAME_LEN)) { ret = LTTNG_ERR_INVALID_CHANNEL_NAME; goto error; @@ -1575,7 +1522,7 @@ int cmd_enable_channel(struct ltt_session *session, chan_ht = usess->domain_global.channels; - uchan = trace_ust_find_channel_by_name(chan_ht, attr.name); + uchan = trace_ust_find_channel_by_name(chan_ht, attr->name); if (uchan == NULL) { /* * Don't try to create a channel if the session has been started at @@ -1586,8 +1533,8 @@ int cmd_enable_channel(struct ltt_session *session, goto error; } - ret = channel_ust_create(usess, &attr, domain->buf_type); - if (attr.name[0] != '\0') { + ret = channel_ust_create(usess, attr, domain->buf_type); + if (attr->name[0] != '\0') { usess->has_non_default_channel = 1; } } else { @@ -1600,12 +1547,13 @@ int cmd_enable_channel(struct ltt_session *session, goto error; } - if (ret == LTTNG_OK && attr.attr.output != LTTNG_EVENT_MMAP) { + if (ret == LTTNG_OK && attr->attr.output != LTTNG_EVENT_MMAP) { session->has_non_mmap_channel = true; } error: rcu_read_unlock(); end: + lttng_channel_destroy(attr); return ret; } @@ -2232,7 +2180,8 @@ static int _cmd_enable_event(struct ltt_session *session, goto error; } - ret = cmd_enable_channel(session, domain, attr, wpipe); + ret = cmd_enable_channel_internal( + session, domain, attr, wpipe); if (ret != LTTNG_OK) { goto error; } @@ -2371,7 +2320,8 @@ static int _cmd_enable_event(struct ltt_session *session, goto error; } - ret = cmd_enable_channel(session, domain, attr, wpipe); + ret = cmd_enable_channel_internal( + session, domain, attr, wpipe); if (ret != LTTNG_OK) { goto error; } @@ -3665,67 +3615,113 @@ error: /* * Command LTTNG_LIST_CHANNELS processed by the client thread. */ -ssize_t cmd_list_channels(enum lttng_domain_type domain, - struct ltt_session *session, struct lttng_channel **channels) +enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain, + struct ltt_session *session, + struct lttng_dynamic_buffer *buffer, + uint32_t *nb_channel) { - ssize_t nb_chan = 0, payload_size = 0, ret; + int ret = 0; + uint32_t i = 0; + + assert(session); + assert(buffer); + assert(nb_channel); + + DBG("Listing channels for session %s", session->name); switch (domain) { case LTTNG_DOMAIN_KERNEL: + { + /* Kernel channels */ + struct ltt_kernel_channel *kchan; if (session->kernel_session != NULL) { - nb_chan = session->kernel_session->channel_count; - } - DBG3("Number of kernel channels %zd", nb_chan); - if (nb_chan <= 0) { - ret = -LTTNG_ERR_KERN_CHAN_NOT_FOUND; - goto end; - } - break; - case LTTNG_DOMAIN_UST: - if (session->ust_session != NULL) { - rcu_read_lock(); - nb_chan = lttng_ht_get_count( - session->ust_session->domain_global.channels); - rcu_read_unlock(); - } - DBG3("Number of UST global channels %zd", nb_chan); - if (nb_chan < 0) { - ret = -LTTNG_ERR_UST_CHAN_NOT_FOUND; - goto end; + cds_list_for_each_entry(kchan, + &session->kernel_session->channel_list.head, list) { + uint64_t discarded_events, lost_packets; + struct lttng_channel_extended *extended; + + extended = (struct lttng_channel_extended *) + kchan->channel->attr.extended.ptr; + + ret = get_kernel_runtime_stats(session, kchan, + &discarded_events, &lost_packets); + if (ret < 0) { + goto end; + } + + /* + * Update the discarded_events and lost_packets + * count for the channel + */ + extended->discarded_events = discarded_events; + extended->lost_packets = lost_packets; + + ret = lttng_channel_serialize( + kchan->channel, buffer); + if (ret) { + ret = -1; + goto end; + } + + i++; + } } break; - default: - ret = -LTTNG_ERR_UND; - goto end; } + case LTTNG_DOMAIN_UST: + { + struct lttng_ht_iter iter; + struct ltt_ust_channel *uchan; - if (nb_chan > 0) { - const size_t channel_size = sizeof(struct lttng_channel) + - sizeof(struct lttng_channel_extended); - struct lttng_channel_extended *channel_exts; + rcu_read_lock(); + cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht, + &iter.iter, uchan, node.node) { + uint64_t discarded_events = 0, lost_packets = 0; + struct lttng_channel *channel = NULL; + struct lttng_channel_extended *extended; - payload_size = nb_chan * channel_size; - *channels = zmalloc(payload_size); - if (*channels == NULL) { - ret = -LTTNG_ERR_FATAL; - goto end; - } + channel = trace_ust_channel_to_lttng_channel(uchan); + if (!channel) { + ret = -1; + break; + } - channel_exts = ((void *) *channels) + - (nb_chan * sizeof(struct lttng_channel)); - ret = list_lttng_channels(domain, session, *channels, channel_exts); - if (ret != LTTNG_OK) { - free(*channels); - *channels = NULL; - goto end; + extended = (struct lttng_channel_extended *) + channel->attr.extended.ptr; + + ret = get_ust_runtime_stats(session, uchan, + &discarded_events, &lost_packets); + if (ret < 0) { + lttng_channel_destroy(channel); + break; + } + + extended->discarded_events = discarded_events; + extended->lost_packets = lost_packets; + + ret = lttng_channel_serialize(channel, buffer); + if (ret) { + ret = -1; + break; + } + + i++; } - } else { - *channels = NULL; + rcu_read_unlock(); + break; + } + default: + break; } - ret = payload_size; end: - return ret; + if (ret < 0) { + *nb_channel = 0; + return LTTNG_ERR_FATAL; + } else { + *nb_channel = i; + return LTTNG_OK; + } } /* diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 1be746031..65e3846c8 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -15,6 +15,7 @@ #include struct notification_thread_handle; +struct lttng_dynamic_buffer; /* * A callback (and associated user data) that should be run after a command @@ -46,9 +47,7 @@ int cmd_destroy_session(struct ltt_session *session, /* Channel commands */ int cmd_disable_channel(struct ltt_session *session, enum lttng_domain_type domain, char *channel_name); -int cmd_enable_channel(struct ltt_session *session, - const struct lttng_domain *domain, const struct lttng_channel *attr, - int wpipe); +int cmd_enable_channel(struct command_ctx *cmd_ctx, int sock, int wpipe); /* Process attribute tracker commands */ enum lttng_error_code cmd_process_attr_tracker_get_tracking_policy( @@ -112,8 +111,10 @@ ssize_t cmd_list_domains(struct ltt_session *session, ssize_t cmd_list_events(enum lttng_domain_type domain, struct ltt_session *session, char *channel_name, 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); +enum lttng_error_code cmd_list_channels(enum lttng_domain_type domain, + struct ltt_session *session, + struct lttng_dynamic_buffer *buffer, + uint32_t *nb_channel); ssize_t cmd_list_domains(struct ltt_session *session, struct lttng_domain **domains); void cmd_list_lttng_sessions(struct lttng_session *sessions, diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h index 960ba57d5..f0e35b8bd 100644 --- a/src/bin/lttng-sessiond/trace-ust.h +++ b/src/bin/lttng-sessiond/trace-ust.h @@ -196,6 +196,7 @@ struct agent *trace_ust_find_agent(struct ltt_ust_session *session, struct ltt_ust_session *trace_ust_create_session(uint64_t session_id); struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr, enum lttng_domain_type domain); + enum lttng_error_code trace_ust_create_event(struct lttng_event *ev, char *filter_expression, struct lttng_filter_bytecode *filter, diff --git a/src/common/Makefile.am b/src/common/Makefile.am index ca9c70d80..8b698c921 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -33,6 +33,7 @@ libcommon_lgpl_la_SOURCES = \ action.c \ buffer-view.h buffer-view.c \ buffer-usage.c \ + channel.c \ credentials.h \ condition.c \ defaults.c \ diff --git a/src/common/channel.c b/src/common/channel.c new file mode 100644 index 000000000..4a237e471 --- /dev/null +++ b/src/common/channel.c @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2021 Jonathan Rajotte + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static enum lttng_error_code flatten_lttng_channels( + struct lttng_dynamic_pointer_array *channels, + struct lttng_channel **flattened_channels); + +static enum lttng_error_code channel_list_create_from_buffer( + const struct lttng_buffer_view *buffer, + uint32_t count, + struct lttng_dynamic_pointer_array *channel_list); + +static void channel_list_destructor(void *ptr) +{ + struct lttng_channel *element = (struct lttng_channel *) ptr; + + lttng_channel_destroy(element); +} + +LTTNG_HIDDEN +struct lttng_channel *lttng_channel_copy(const struct lttng_channel *src) +{ + struct lttng_channel_extended *extended = NULL; + struct lttng_channel *channel = NULL, *ret = NULL; + + channel = zmalloc(sizeof(*channel)); + if (!channel) { + goto end; + } + + memcpy(channel, src, sizeof(*channel)); + + if (src->attr.extended.ptr) { + extended = zmalloc(sizeof(*extended)); + if (!extended) { + goto end; + } + memcpy(extended, src->attr.extended.ptr, sizeof(*extended)); + channel->attr.extended.ptr = extended; + extended = NULL; + } + + ret = channel; + channel = NULL; +end: + free(channel); + free(extended); + return ret; +} + +/* + * The channel object is NOT populated. + */ +LTTNG_HIDDEN +struct lttng_channel *lttng_channel_create_internal(void) +{ + struct lttng_channel *local_channel = NULL, *ret = NULL; + struct lttng_channel_extended *extended = NULL; + + local_channel = zmalloc(sizeof(struct lttng_channel)); + if (!local_channel) { + goto end; + } + + /* Extended struct */ + extended = zmalloc(sizeof(*extended)); + if (!extended) { + goto end; + } + + local_channel->attr.extended.ptr = extended; + extended = NULL; + + ret = local_channel; + local_channel = NULL; +end: + free(extended); + free(local_channel); + return ret; +} + +LTTNG_HIDDEN +ssize_t lttng_channel_create_from_buffer(const struct lttng_buffer_view *view, + struct lttng_channel **channel) +{ + ssize_t ret, offset = 0; + struct lttng_channel *local_channel = NULL; + const struct lttng_channel_comm *channel_comm; + struct lttng_channel_extended *extended = NULL; + + assert(channel); + + if (!view || !channel) { + ret = -1; + goto end; + } + + /* + * Create an 'internal' channel since `lttng_create_channel` requires a + * domain and we cannot infer the domain from the payload. + */ + local_channel = lttng_channel_create_internal(); + if (!local_channel) { + ret = -1; + goto end; + } + + extended = (typeof(extended)) local_channel->attr.extended.ptr; + + /* lttng_trigger_comm header */ + { + const struct lttng_buffer_view comm_view = + lttng_buffer_view_from_view(view, offset, + sizeof(*channel_comm)); + + if (!lttng_buffer_view_is_valid(&comm_view)) { + ret = -1; + goto end; + } + + channel_comm = (const struct lttng_channel_comm *) + comm_view.data; + offset += sizeof(*channel_comm); + } + + { + const char *name; + const struct lttng_buffer_view name_view = + lttng_buffer_view_from_view(view, offset, + channel_comm->name_len); + + if (channel_comm->name_len > LTTNG_SYMBOL_NAME_LEN - 1) { + ret = -1; + goto end; + } + + name = name_view.data; + if (!lttng_buffer_view_contains_string( + &name_view, name, channel_comm->name_len)) { + ret = -1; + goto end; + } + + strcpy(local_channel->name, name); + offset += channel_comm->name_len; + } + + /* Populate the channel */ + local_channel->enabled = channel_comm->enabled; + + /* attr */ + local_channel->attr.overwrite = channel_comm->overwrite; + local_channel->attr.subbuf_size = channel_comm->subbuf_size; + local_channel->attr.num_subbuf = channel_comm->num_subbuf; + local_channel->attr.switch_timer_interval = + channel_comm->switch_timer_interval; + local_channel->attr.read_timer_interval = + channel_comm->read_timer_interval; + local_channel->attr.output = channel_comm->output; + local_channel->attr.tracefile_size = channel_comm->tracefile_size; + local_channel->attr.tracefile_count = channel_comm->tracefile_count; + local_channel->attr.live_timer_interval = + channel_comm->live_timer_interval; + + extended->discarded_events = channel_comm->discarded_events; + extended->lost_packets = channel_comm->lost_packets; + extended->monitor_timer_interval = channel_comm->monitor_timer_interval; + extended->blocking_timeout = channel_comm->blocking_timeout; + + *channel = local_channel; + local_channel = NULL; + + ret = offset; +end: + lttng_channel_destroy(local_channel); + return ret; +} + +LTTNG_HIDDEN +int lttng_channel_serialize( + struct lttng_channel *channel, struct lttng_dynamic_buffer *buf) +{ + int ret; + size_t name_len; + struct lttng_channel_comm channel_comm = { 0 }; + struct lttng_channel_extended *extended; + + assert(channel); + assert(buf); + + extended = channel->attr.extended.ptr; + + name_len = lttng_strnlen(channel->name, LTTNG_SYMBOL_NAME_LEN); + if (name_len == LTTNG_SYMBOL_NAME_LEN) { + /* channel name is not NULL-terminated. */ + ret = -1; + goto end; + } + + /* Include string termination. */ + name_len += 1; + + /* Base field */ + channel_comm.name_len = (uint32_t) name_len; + channel_comm.enabled = channel->enabled; + + /* attr */ + channel_comm.overwrite = channel->attr.overwrite; + channel_comm.subbuf_size = channel->attr.subbuf_size; + channel_comm.num_subbuf = channel->attr.num_subbuf; + channel_comm.switch_timer_interval = + channel->attr.switch_timer_interval; + channel_comm.read_timer_interval = channel->attr.read_timer_interval; + channel_comm.output = channel->attr.output; + channel_comm.tracefile_size = channel->attr.tracefile_size; + channel_comm.tracefile_count = channel->attr.tracefile_count; + channel_comm.live_timer_interval = channel->attr.live_timer_interval; + + /* Extended struct */ + channel_comm.discarded_events = extended->discarded_events; + channel_comm.lost_packets = extended->lost_packets; + channel_comm.monitor_timer_interval = extended->monitor_timer_interval; + channel_comm.blocking_timeout = extended->blocking_timeout; + + /* Header */ + ret = lttng_dynamic_buffer_append( + buf, &channel_comm, sizeof(channel_comm)); + if (ret) { + goto end; + } + + /* channel name */ + ret = lttng_dynamic_buffer_append(buf, channel->name, name_len); + if (ret) { + goto end; + } +end: + return ret; +} + +LTTNG_HIDDEN +void lttng_channel_set_default_extended_attr(struct lttng_domain *domain, + struct lttng_channel_extended *extended_attr) +{ + assert(domain); + assert(extended_attr); + + memset(extended_attr, 0, sizeof(*extended_attr)); + + switch (domain->type) { + case LTTNG_DOMAIN_KERNEL: + extended_attr->monitor_timer_interval = + DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER; + extended_attr->blocking_timeout = + DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT; + break; + case LTTNG_DOMAIN_UST: + switch (domain->buf_type) { + case LTTNG_BUFFER_PER_UID: + extended_attr->monitor_timer_interval = + DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER; + extended_attr->blocking_timeout = + DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT; + break; + case LTTNG_BUFFER_PER_PID: + default: + if (extended_attr) { + extended_attr->monitor_timer_interval = + DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER; + extended_attr->blocking_timeout = + DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT; + } + break; + } + default: + /* Default behavior: leave set to 0. */ + break; + } +} + +static enum lttng_error_code channel_list_create_from_buffer( + const struct lttng_buffer_view *view, + unsigned int count, + struct lttng_dynamic_pointer_array *channel_list) +{ + enum lttng_error_code ret_code; + int ret, i; + int offset = 0; + + assert(view); + assert(channel_list); + + for (i = 0; i < count; i++) { + ssize_t channel_size; + struct lttng_channel *channel = NULL; + const struct lttng_buffer_view channel_view = + lttng_buffer_view_from_view(view, offset, -1); + + channel_size = lttng_channel_create_from_buffer( + &channel_view, &channel); + if (channel_size < 0) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + /* Lifetime and management of the object is now bound to the array. */ + ret = lttng_dynamic_pointer_array_add_pointer(channel_list, channel); + if (ret) { + lttng_channel_destroy(channel); + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + offset += channel_size; + } + + if (view->size != offset) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + ret_code = LTTNG_OK; + +end: + return ret_code; +} + +static enum lttng_error_code flatten_lttng_channels(struct lttng_dynamic_pointer_array *channels, + struct lttng_channel **flattened_channels) +{ + enum lttng_error_code ret_code; + int ret, i; + size_t storage_req = 0; + struct lttng_dynamic_buffer local_flattened_channels; + int nb_channels; + + assert(channels); + assert(flattened_channels); + + lttng_dynamic_buffer_init(&local_flattened_channels); + nb_channels = lttng_dynamic_pointer_array_get_count(channels); + + storage_req += sizeof(struct lttng_channel) * nb_channels; + storage_req += sizeof(struct lttng_channel_extended) * nb_channels; + + /* + * We must ensure that "local_flattened_channels" is never resized so as + * to preserve the validity of the flattened objects. + */ + ret = lttng_dynamic_buffer_set_capacity( + &local_flattened_channels, storage_req); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + /* Start by laying the struct lttng_channel */ + for (i = 0; i < nb_channels; i++) { + const struct lttng_channel *element = + lttng_dynamic_pointer_array_get_pointer( + channels, i); + + if (!element) { + ret_code = LTTNG_ERR_FATAL; + goto end; + } + ret = lttng_dynamic_buffer_append(&local_flattened_channels, + element, sizeof(struct lttng_channel)); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + } + + /* Flatten the extended data */ + for (i = 0; i < nb_channels; i++) { + const struct lttng_channel *element = + lttng_dynamic_pointer_array_get_pointer( + channels, i); + /* + * Sample the location of the flattened channel we are about + * to modify + */ + struct lttng_channel *channel = (struct lttng_channel *) + (local_flattened_channels.data + (sizeof(struct lttng_channel) * i)); + /* + * Sample the location of the extended attributes we are about + * to add. + */ + struct lttng_channel_extended *channel_extended = + (struct lttng_channel_extended *) + (local_flattened_channels.data + local_flattened_channels.size); + + if (!element) { + ret_code = LTTNG_ERR_FATAL; + goto end; + } + + ret = lttng_dynamic_buffer_append(&local_flattened_channels, + element->attr.extended.ptr, + sizeof(struct lttng_channel_extended)); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + /* + * Update the flattened lttng_channel object with its flattened + * extended object location. + */ + channel->attr.extended.ptr = channel_extended; + } + + /* Don't reset local_flattened_channels buffer as we return its content. */ + *flattened_channels = (struct lttng_channel *) local_flattened_channels.data; + lttng_dynamic_buffer_init(&local_flattened_channels); + ret_code = LTTNG_OK; +end: + lttng_dynamic_buffer_reset(&local_flattened_channels); + return ret_code; +} + +LTTNG_HIDDEN +enum lttng_error_code lttng_channels_create_and_flatten_from_buffer( + const struct lttng_buffer_view *view, + uint32_t count, + struct lttng_channel **channels) +{ + enum lttng_error_code ret_code; + struct lttng_dynamic_pointer_array local_channels; + + lttng_dynamic_pointer_array_init(&local_channels, channel_list_destructor); + + /* Deserialize the channels */ + { + const struct lttng_buffer_view channels_view = + lttng_buffer_view_from_view(view, 0, -1); + + ret_code = channel_list_create_from_buffer( + &channels_view, count, &local_channels); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + ret_code = flatten_lttng_channels(&local_channels, channels); + +end: + lttng_dynamic_pointer_array_reset(&local_channels); + return ret_code; +} diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index b9ab05bcb..0d3e374b3 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -311,9 +311,7 @@ struct lttcomm_session_msg { } LTTNG_PACKED disable; /* Create channel */ struct { - struct lttng_channel chan LTTNG_PACKED; - /* struct lttng_channel_extended is already packed. */ - struct lttng_channel_extended extended; + uint32_t length; } LTTNG_PACKED channel; /* Context */ struct { @@ -453,6 +451,14 @@ struct lttcomm_event_command_header { uint32_t nb_events; } LTTNG_PACKED; +/* + * Listing command header. + */ +struct lttcomm_list_command_header { + /* Number of elements */ + uint32_t count; +} LTTNG_PACKED; + /* * Event extended info header. This is the structure preceding each * extended info data. diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 5cdc2b011..622a2bd04 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -1509,10 +1509,9 @@ end: struct lttng_channel *lttng_channel_create(struct lttng_domain *domain) { struct lttng_channel *channel = NULL; - struct lttng_channel_extended *extended = NULL; if (!domain) { - goto error; + goto end; } /* Validate domain. */ @@ -1523,36 +1522,26 @@ struct lttng_channel *lttng_channel_create(struct lttng_domain *domain) case LTTNG_BUFFER_PER_PID: break; default: - goto error; + goto end; } break; case LTTNG_DOMAIN_KERNEL: if (domain->buf_type != LTTNG_BUFFER_GLOBAL) { - goto error; + goto end; } break; default: - goto error; + goto end; } - channel = zmalloc(sizeof(*channel)); + channel = lttng_channel_create_internal(); if (!channel) { - goto error; - } - - extended = zmalloc(sizeof(*extended)); - if (!extended) { - goto error; + goto end; } - channel->attr.extended.ptr = extended; - lttng_channel_set_default_attr(domain, &channel->attr); +end: return channel; -error: - free(channel); - free(extended); - return NULL; } void lttng_channel_destroy(struct lttng_channel *channel) @@ -1576,56 +1565,32 @@ int lttng_enable_channel(struct lttng_handle *handle, { enum lttng_error_code ret_code; int ret; + struct lttng_dynamic_buffer buffer; struct lttcomm_session_msg lsm; uint64_t total_buffer_size_needed_per_cpu = 0; + struct lttng_channel *channel = NULL; + + lttng_dynamic_buffer_init(&buffer); /* NULL arguments are forbidden. No default values. */ if (handle == NULL || in_chan == NULL) { - return -LTTNG_ERR_INVALID; - } - - memset(&lsm, 0, sizeof(lsm)); - memcpy(&lsm.u.channel.chan, in_chan, sizeof(lsm.u.channel.chan)); - lsm.u.channel.chan.attr.extended.ptr = NULL; - - if (!in_chan->attr.extended.ptr) { - struct lttng_channel *channel; - struct lttng_channel_extended *extended; - - channel = lttng_channel_create(&handle->domain); - if (!channel) { - return -LTTNG_ERR_NOMEM; - } - - /* - * Create a new channel in order to use default extended - * attribute values. - */ - extended = (struct lttng_channel_extended *) - channel->attr.extended.ptr; - memcpy(&lsm.u.channel.extended, extended, sizeof(*extended)); - lttng_channel_destroy(channel); - } else { - struct lttng_channel_extended *extended; - - extended = (struct lttng_channel_extended *) - in_chan->attr.extended.ptr; - memcpy(&lsm.u.channel.extended, extended, sizeof(*extended)); + ret = -LTTNG_ERR_INVALID; + goto end; } /* * Verify that the amount of memory required to create the requested * buffer is available on the system at the moment. */ - if (lsm.u.channel.chan.attr.num_subbuf > - UINT64_MAX / lsm.u.channel.chan.attr.subbuf_size) { + if (in_chan->attr.num_subbuf > + UINT64_MAX / in_chan->attr.subbuf_size) { /* Overflow */ ret = -LTTNG_ERR_OVERFLOW; goto end; } - total_buffer_size_needed_per_cpu = lsm.u.channel.chan.attr.num_subbuf * - lsm.u.channel.chan.attr.subbuf_size; + total_buffer_size_needed_per_cpu = + in_chan->attr.num_subbuf * in_chan->attr.subbuf_size; ret_code = check_enough_available_memory( total_buffer_size_needed_per_cpu); if (ret_code != LTTNG_OK) { @@ -1633,6 +1598,30 @@ int lttng_enable_channel(struct lttng_handle *handle, goto end; } + /* Copy the channel for easier manipulation. */ + channel = lttng_channel_copy(in_chan); + if (!channel) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + + /* Populate the channel extended attribute if necessary. */ + if (!channel->attr.extended.ptr) { + struct lttng_channel_extended *extended = + zmalloc(sizeof(*extended)); + + if (!extended) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + lttng_channel_set_default_extended_attr( + &handle->domain, extended); + channel->attr.extended.ptr = extended; + } + + /* Prepare the payload */ + memset(&lsm, 0, sizeof(lsm)); + lsm.cmd_type = LTTNG_ENABLE_CHANNEL; COPY_DOMAIN_PACKED(lsm.domain, handle->domain); @@ -1643,8 +1632,19 @@ int lttng_enable_channel(struct lttng_handle *handle, goto end; } - ret = lttng_ctl_ask_sessiond(&lsm, NULL); + ret = lttng_channel_serialize(channel, &buffer); + if (ret) { + ret = -LTTNG_ERR_FATAL; + goto end; + } + + lsm.u.channel.length = buffer.size; + + ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( + &lsm, buffer.data, buffer.size, NULL); end: + lttng_channel_destroy(channel); + lttng_dynamic_buffer_reset(&buffer); return ret; } @@ -2242,12 +2242,14 @@ error: int lttng_list_channels(struct lttng_handle *handle, struct lttng_channel **channels) { - int ret; - size_t channel_count, i; - const size_t channel_size = sizeof(struct lttng_channel) + - sizeof(struct lttng_channel_extended); + int ret, total_payload_received; struct lttcomm_session_msg lsm; - void *extended_at; + char *reception_buffer = NULL; + size_t cmd_header_len = 0; + struct lttcomm_list_command_header *cmd_header = NULL; + struct lttng_dynamic_buffer tmp_buffer; + + lttng_dynamic_buffer_init(&tmp_buffer); if (handle == NULL) { ret = -LTTNG_ERR_INVALID; @@ -2265,31 +2267,48 @@ int lttng_list_channels(struct lttng_handle *handle, COPY_DOMAIN_PACKED(lsm.domain, handle->domain); - ret = lttng_ctl_ask_sessiond(&lsm, (void**) channels); + ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm, NULL, 0, NULL, 0, + (void **) &reception_buffer, (void **) &cmd_header, + &cmd_header_len); if (ret < 0) { goto end; } - if (ret % channel_size) { - ret = -LTTNG_ERR_UNK; - free(*channels); - *channels = NULL; + total_payload_received = ret; + + if (cmd_header_len != sizeof(*cmd_header)) { + ret = -LTTNG_ERR_FATAL; + goto end; + } + + if (!cmd_header) { + ret = LTTNG_ERR_UNK; + goto end; + } + + if (cmd_header->count > INT_MAX) { + ret = -LTTNG_ERR_OVERFLOW; goto end; } - channel_count = (size_t) ret / channel_size; - /* Set extended info pointers */ - extended_at = ((void *) *channels) + - channel_count * sizeof(struct lttng_channel); - for (i = 0; i < channel_count; i++) { - struct lttng_channel *chan = &(*channels)[i]; + { + enum lttng_error_code ret_code; + const struct lttng_buffer_view events_view = + lttng_buffer_view_init(reception_buffer, 0, + total_payload_received); - chan->attr.extended.ptr = extended_at; - extended_at += sizeof(struct lttng_channel_extended); + ret_code = lttng_channels_create_and_flatten_from_buffer( + &events_view, cmd_header->count, channels); + if (ret_code != LTTNG_OK) { + ret = -ret_code; + goto end; + } } - ret = (int) channel_count; + ret = (int) cmd_header->count; end: + free(cmd_header); + free(reception_buffer); return ret; } @@ -2598,6 +2617,7 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, return; } + /* Save the pointer for later use */ extended = (struct lttng_channel_extended *) attr->extended.ptr; memset(attr, 0, sizeof(struct lttng_channel_attr)); @@ -2614,12 +2634,6 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, attr->subbuf_size = default_get_kernel_channel_subbuf_size(); attr->num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM; attr->output = DEFAULT_KERNEL_CHANNEL_OUTPUT; - if (extended) { - extended->monitor_timer_interval = - DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER; - extended->blocking_timeout = - DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT; - } break; case LTTNG_DOMAIN_UST: switch (domain->buf_type) { @@ -2631,12 +2645,6 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER; attr->read_timer_interval = DEFAULT_UST_UID_CHANNEL_READ_TIMER; - if (extended) { - extended->monitor_timer_interval = - DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER; - extended->blocking_timeout = - DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT; - } break; case LTTNG_BUFFER_PER_PID: default: @@ -2647,12 +2655,6 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER; attr->read_timer_interval = DEFAULT_UST_PID_CHANNEL_READ_TIMER; - if (extended) { - extended->monitor_timer_interval = - DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER; - extended->blocking_timeout = - DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT; - } break; } default: @@ -2660,6 +2662,11 @@ void lttng_channel_set_default_attr(struct lttng_domain *domain, break; } + if (extended) { + lttng_channel_set_default_extended_attr(domain, extended); + } + + /* Reassign the extended pointer. */ attr->extended.ptr = extended; } -- 2.34.1