#define LTTNG_CHANNEL_INTERNAL_H
#include <common/macros.h>
+#include <lttng/channel.h>
+#include <lttng/lttng-error.h>
+
+struct lttng_dynamic_buffer;
+struct lttng_buffer_view;
struct lttng_channel_extended {
uint64_t discarded_events;
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 */
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) {
+ ERR("Failed to create lttng_channel during conversion from ltt_ust_channel to lttng_channel");
+ goto end;
+ }
+
+ if (lttng_strncpy(channel->name, uchan->name, LTTNG_SYMBOL_NAME_LEN)) {
+ ERR("Failed to set channel name during conversion from ltt_ust_channel to lttng_channel");
+ 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_ABI_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;
+}
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 */
#include <pthread.h>
#include <signal.h>
#include <stddef.h>
+#include <stdint.h>
#include <sys/stat.h>
#include <unistd.h>
}
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),
- the_kernel_poll_pipe[1]);
+ ret = cmd_enable_channel(
+ cmd_ctx, *sock, the_kernel_poll_pipe[1]);
break;
}
case LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE:
}
case LTTNG_LIST_CHANNELS:
{
- ssize_t payload_size;
- struct lttng_channel *channels = NULL;
+ enum lttng_error_code ret_code;
+ size_t original_payload_size;
+ size_t payload_size;
+ const size_t command_header_size = sizeof(struct lttcomm_list_command_header);
- 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;
- goto error;
+ ret = setup_empty_lttng_msg(cmd_ctx);
+ if (ret) {
+ ret = LTTNG_ERR_NOMEM;
+ goto setup_error;
}
- ret = setup_lttng_msg_no_cmd_header(cmd_ctx, channels,
- payload_size);
- free(channels);
+ original_payload_size = cmd_ctx->reply_payload.buffer.size;
- if (ret < 0) {
- goto setup_error;
+ ret_code = cmd_list_channels(cmd_ctx->lsm.domain.type,
+ cmd_ctx->session, &cmd_ctx->reply_payload);
+ if (ret_code != LTTNG_OK) {
+ ret = (int) ret_code;
+ goto error;
}
+ payload_size = cmd_ctx->reply_payload.buffer.size -
+ command_header_size - original_payload_size;
+ update_lttng_msg(cmd_ctx, command_header_size, payload_size);
+
ret = LTTNG_OK;
break;
}
struct lttng_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
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_ABI_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 append_extended_info(const char *filter_expression,
struct lttng_event_exclusion *exclusion,
struct lttng_userspace_probe_location *probe_location,
*
* 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;
+ const struct lttng_domain command_domain = cmd_ctx->lsm.domain;
+
+ 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, &command_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();
* 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 */
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;
}
{
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
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 {
* 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;
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
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 {
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;
}
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;
}
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;
}
/*
* 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_payload *payload)
{
- ssize_t nb_chan = 0, payload_size = 0, ret;
+ int ret = 0;
+ unsigned int i = 0;
+ struct lttcomm_list_command_header cmd_header = {};
+ size_t cmd_header_offset;
+ enum lttng_error_code ret_code;
+
+ assert(session);
+ assert(payload);
+
+ DBG("Listing channels for session %s", session->name);
+
+ cmd_header_offset = payload->buffer.size;
+
+ /* Reserve space for command reply header. */
+ ret = lttng_dynamic_buffer_set_size(&payload->buffer,
+ cmd_header_offset + sizeof(cmd_header));
+ if (ret) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end;
+ }
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;
+ 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) {
+ ret_code = LTTNG_ERR_UNK;
+ 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, &payload->buffer);
+ if (ret) {
+ ERR("Failed to serialize lttng_channel: channel name = '%s'",
+ kchan->channel->name);
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ i++;
+ }
}
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;
+ {
+ 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;
+ struct lttng_channel *channel = NULL;
+ struct lttng_channel_extended *extended;
+
+ channel = trace_ust_channel_to_lttng_channel(uchan);
+ if (!channel) {
+ ret = LTTNG_ERR_NOMEM;
+ break;
+ }
+
+ 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);
+ ret_code = LTTNG_ERR_UNK;
+ break;
+ }
+
+ extended->discarded_events = discarded_events;
+ extended->lost_packets = lost_packets;
+
+ ret = lttng_channel_serialize(
+ channel, &payload->buffer);
+ if (ret) {
+ ERR("Failed to serialize lttng_channel: channel name = '%s'",
+ channel->name);
+ ret_code = LTTNG_ERR_UNK;
+ ret = -1;
+ break;
+ }
+
+ i++;
}
+ rcu_read_unlock();
break;
+ }
default:
- ret = -LTTNG_ERR_UND;
- goto end;
+ break;
}
- if (nb_chan > 0) {
- const size_t channel_size = sizeof(struct lttng_channel) +
- sizeof(struct lttng_channel_extended);
- struct lttng_channel_extended *channel_exts;
-
- payload_size = nb_chan * channel_size;
- *channels = zmalloc(payload_size);
- if (*channels == NULL) {
- ret = -LTTNG_ERR_FATAL;
- goto end;
- }
-
- 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;
- }
- } else {
- *channels = NULL;
+ if (i > UINT32_MAX) {
+ ERR("Channel count would overflow the channel listing command's reply");
+ ret_code = LTTNG_ERR_OVERFLOW;
+ goto end;
}
- ret = payload_size;
+ /* Update command reply header. */
+ cmd_header.count = (uint32_t) i;
+ memcpy(payload->buffer.data + cmd_header_offset, &cmd_header,
+ sizeof(cmd_header));
+ ret_code = LTTNG_OK;
+
end:
- return ret;
+ return ret_code;
}
/*
#include <common/tracker.h>
struct notification_thread_handle;
+struct lttng_dynamic_buffer;
/*
* A callback (and associated user data) that should be run after a command
/* 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(
ssize_t cmd_list_events(enum lttng_domain_type domain,
struct ltt_session *session, char *channel_name,
struct lttng_payload *payload);
-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_payload *payload);
ssize_t cmd_list_domains(struct ltt_session *session,
struct lttng_domain **domains);
void cmd_list_lttng_sessions(struct lttng_session *sessions,
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_bytecode *filter,
actions/stop-session.c \
actions/rate-policy.c \
buffer-view.h buffer-view.c \
+ channel.c \
conditions/buffer-usage.c \
conditions/condition.c \
conditions/event-rule-matches.c \
--- /dev/null
+/*
+ * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <common/macros.h>
+#include <lttng/channel.h>
+#include <lttng/constant.h>
+#include <lttng/channel-internal.h>
+#include <lttng/userspace-probe-internal.h>
+#include <common/dynamic-buffer.h>
+#include <common/error.h>
+#include <assert.h>
+#include <string.h>
+#include <common/sessiond-comm/sessiond-comm.h>
+#include <common/dynamic-array.h>
+#include <common/buffer-view.h>
+
+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);
+}
+
+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 = (struct lttng_channel *) zmalloc(sizeof(*channel));
+ if (!channel) {
+ goto end;
+ }
+
+ *channel = *src;
+
+ if (src->attr.extended.ptr) {
+ extended = (struct lttng_channel_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.
+ */
+struct lttng_channel *lttng_channel_create_internal(void)
+{
+ struct lttng_channel *local_channel = NULL, *ret = NULL;
+ struct lttng_channel_extended *extended = NULL;
+
+ local_channel = (struct lttng_channel *) zmalloc(
+ sizeof(struct lttng_channel));
+ if (!local_channel) {
+ goto end;
+ }
+
+ /* Extended struct */
+ extended = (struct lttng_channel_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;
+}
+
+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 = (enum lttng_event_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;
+}
+
+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 = (struct lttng_channel_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;
+}
+
+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 = (const struct lttng_channel *)
+ 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 = (const struct lttng_channel *)
+ 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 = (void *) 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;
+}
+
+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;
+}
} LTTNG_PACKED disable;
/* Create channel */
struct {
- struct lttng_channel chan;
- struct lttng_channel_extended extended;
+ uint32_t length;
} LTTNG_PACKED channel;
/* Context */
struct {
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.
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. */
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)
{
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) {
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 =
+ (struct lttng_channel_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);
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;
}
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;
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;
}
- 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];
+ if (!cmd_header) {
+ ret = LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ if (cmd_header->count > INT_MAX) {
+ ret = -LTTNG_ERR_OVERFLOW;
+ goto end;
+ }
- chan->attr.extended.ptr = extended_at;
- extended_at += sizeof(struct lttng_channel_extended);
+ {
+ enum lttng_error_code ret_code;
+ const struct lttng_buffer_view events_view =
+ lttng_buffer_view_init(reception_buffer, 0,
+ total_payload_received);
+
+ 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;
}
return;
}
+ /* Save the pointer for later use */
extended = (struct lttng_channel_extended *) attr->extended.ptr;
memset(attr, 0, sizeof(struct lttng_channel_attr));
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) {
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:
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:
break;
}
+ if (extended) {
+ lttng_channel_set_default_extended_attr(domain, extended);
+ }
+
+ /* Reassign the extended pointer. */
attr->extended.ptr = extended;
}