2 * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include <common/buffer-view.hpp>
9 #include <common/dynamic-array.hpp>
10 #include <common/dynamic-buffer.hpp>
11 #include <common/error.hpp>
12 #include <common/macros.hpp>
13 #include <common/sessiond-comm/sessiond-comm.hpp>
14 #include <common/urcu.hpp>
16 #include <lttng/channel-internal.hpp>
17 #include <lttng/channel.h>
18 #include <lttng/constant.h>
19 #include <lttng/userspace-probe-internal.hpp>
21 static enum lttng_error_code
flatten_lttng_channels(struct lttng_dynamic_pointer_array
*channels
,
22 struct lttng_channel
**flattened_channels
);
24 static enum lttng_error_code
25 channel_list_create_from_buffer(const struct lttng_buffer_view
*buffer
,
27 struct lttng_dynamic_pointer_array
*channel_list
);
29 static void channel_list_destructor(void *ptr
)
31 struct lttng_channel
*element
= (struct lttng_channel
*) ptr
;
33 lttng_channel_destroy(element
);
36 struct lttng_channel
*lttng_channel_copy(const struct lttng_channel
*src
)
38 struct lttng_channel_extended
*extended
= nullptr;
39 struct lttng_channel
*channel
= nullptr, *ret
= nullptr;
41 channel
= zmalloc
<lttng_channel
>();
48 if (src
->attr
.extended
.ptr
) {
49 extended
= zmalloc
<lttng_channel_extended
>();
53 memcpy(extended
, src
->attr
.extended
.ptr
, sizeof(*extended
));
54 channel
->attr
.extended
.ptr
= extended
;
67 * The channel object is NOT populated.
69 struct lttng_channel
*lttng_channel_create_internal()
71 struct lttng_channel
*local_channel
= nullptr, *ret
= nullptr;
72 struct lttng_channel_extended
*extended
= nullptr;
74 local_channel
= zmalloc
<lttng_channel
>();
80 extended
= zmalloc
<lttng_channel_extended
>();
85 local_channel
->attr
.extended
.ptr
= extended
;
89 local_channel
= nullptr;
96 ssize_t
lttng_channel_create_from_buffer(const struct lttng_buffer_view
*view
,
97 struct lttng_channel
**channel
)
99 ssize_t ret
, offset
= 0;
100 struct lttng_channel
*local_channel
= nullptr;
101 const struct lttng_channel_comm
*channel_comm
;
102 struct lttng_channel_extended
*extended
= nullptr;
106 if (!view
|| !channel
) {
112 * Create an 'internal' channel since `lttng_create_channel` requires a
113 * domain and we cannot infer the domain from the payload.
115 local_channel
= lttng_channel_create_internal();
116 if (!local_channel
) {
121 extended
= (typeof(extended
)) local_channel
->attr
.extended
.ptr
;
123 /* lttng_trigger_comm header */
125 const struct lttng_buffer_view comm_view
=
126 lttng_buffer_view_from_view(view
, offset
, sizeof(*channel_comm
));
128 if (!lttng_buffer_view_is_valid(&comm_view
)) {
133 channel_comm
= (const struct lttng_channel_comm
*) comm_view
.data
;
134 offset
+= sizeof(*channel_comm
);
139 const struct lttng_buffer_view name_view
=
140 lttng_buffer_view_from_view(view
, offset
, channel_comm
->name_len
);
142 name
= name_view
.data
;
143 if (!lttng_buffer_view_contains_string(&name_view
, name
, channel_comm
->name_len
)) {
148 ret
= lttng_strncpy(local_channel
->name
, name
, sizeof(local_channel
->name
));
153 offset
+= channel_comm
->name_len
;
156 /* Populate the channel */
157 local_channel
->enabled
= channel_comm
->enabled
;
160 local_channel
->attr
.overwrite
= channel_comm
->overwrite
;
161 local_channel
->attr
.subbuf_size
= channel_comm
->subbuf_size
;
162 local_channel
->attr
.num_subbuf
= channel_comm
->num_subbuf
;
163 local_channel
->attr
.switch_timer_interval
= channel_comm
->switch_timer_interval
;
164 local_channel
->attr
.read_timer_interval
= channel_comm
->read_timer_interval
;
165 local_channel
->attr
.output
= (enum lttng_event_output
) channel_comm
->output
;
166 local_channel
->attr
.tracefile_size
= channel_comm
->tracefile_size
;
167 local_channel
->attr
.tracefile_count
= channel_comm
->tracefile_count
;
168 local_channel
->attr
.live_timer_interval
= channel_comm
->live_timer_interval
;
170 extended
->discarded_events
= channel_comm
->discarded_events
;
171 extended
->lost_packets
= channel_comm
->lost_packets
;
172 extended
->monitor_timer_interval
= channel_comm
->monitor_timer_interval
;
173 extended
->blocking_timeout
= channel_comm
->blocking_timeout
;
175 *channel
= local_channel
;
176 local_channel
= nullptr;
180 lttng_channel_destroy(local_channel
);
184 int lttng_channel_serialize(struct lttng_channel
*channel
, struct lttng_dynamic_buffer
*buf
)
188 struct lttng_channel_comm channel_comm
= {};
189 struct lttng_channel_extended
*extended
;
194 extended
= (struct lttng_channel_extended
*) channel
->attr
.extended
.ptr
;
196 name_len
= lttng_strnlen(channel
->name
, LTTNG_SYMBOL_NAME_LEN
);
197 if (name_len
== LTTNG_SYMBOL_NAME_LEN
) {
198 /* channel name is not nullptr-terminated. */
203 /* Include string termination. */
207 channel_comm
.name_len
= (uint32_t) name_len
;
208 channel_comm
.enabled
= channel
->enabled
;
211 channel_comm
.overwrite
= channel
->attr
.overwrite
;
212 channel_comm
.subbuf_size
= channel
->attr
.subbuf_size
;
213 channel_comm
.num_subbuf
= channel
->attr
.num_subbuf
;
214 channel_comm
.switch_timer_interval
= channel
->attr
.switch_timer_interval
;
215 channel_comm
.read_timer_interval
= channel
->attr
.read_timer_interval
;
216 channel_comm
.output
= channel
->attr
.output
;
217 channel_comm
.tracefile_size
= channel
->attr
.tracefile_size
;
218 channel_comm
.tracefile_count
= channel
->attr
.tracefile_count
;
219 channel_comm
.live_timer_interval
= channel
->attr
.live_timer_interval
;
221 /* Extended struct */
222 channel_comm
.discarded_events
= extended
->discarded_events
;
223 channel_comm
.lost_packets
= extended
->lost_packets
;
224 channel_comm
.monitor_timer_interval
= extended
->monitor_timer_interval
;
225 channel_comm
.blocking_timeout
= extended
->blocking_timeout
;
228 ret
= lttng_dynamic_buffer_append(buf
, &channel_comm
, sizeof(channel_comm
));
234 ret
= lttng_dynamic_buffer_append(buf
, channel
->name
, name_len
);
242 void lttng_channel_set_default_extended_attr(struct lttng_domain
*domain
,
243 struct lttng_channel_extended
*extended_attr
)
246 assert(extended_attr
);
248 memset(extended_attr
, 0, sizeof(*extended_attr
));
250 switch (domain
->type
) {
251 case LTTNG_DOMAIN_KERNEL
:
252 extended_attr
->monitor_timer_interval
= DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER
;
253 extended_attr
->blocking_timeout
= DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT
;
255 case LTTNG_DOMAIN_UST
:
256 switch (domain
->buf_type
) {
257 case LTTNG_BUFFER_PER_UID
:
258 extended_attr
->monitor_timer_interval
=
259 DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER
;
260 extended_attr
->blocking_timeout
= DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT
;
262 case LTTNG_BUFFER_PER_PID
:
265 extended_attr
->monitor_timer_interval
=
266 DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER
;
267 extended_attr
->blocking_timeout
=
268 DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT
;
273 /* Default behavior: leave set to 0. */
278 static enum lttng_error_code
279 channel_list_create_from_buffer(const struct lttng_buffer_view
*view
,
281 struct lttng_dynamic_pointer_array
*channel_list
)
283 enum lttng_error_code ret_code
;
288 assert(channel_list
);
290 for (i
= 0; i
< count
; i
++) {
291 ssize_t channel_size
;
292 struct lttng_channel
*channel
= nullptr;
293 const struct lttng_buffer_view channel_view
=
294 lttng_buffer_view_from_view(view
, offset
, -1);
296 channel_size
= lttng_channel_create_from_buffer(&channel_view
, &channel
);
297 if (channel_size
< 0) {
298 ret_code
= LTTNG_ERR_INVALID
;
302 /* Lifetime and management of the object is now bound to the array. */
303 ret
= lttng_dynamic_pointer_array_add_pointer(channel_list
, channel
);
305 lttng_channel_destroy(channel
);
306 ret_code
= LTTNG_ERR_NOMEM
;
309 offset
+= channel_size
;
312 if (view
->size
!= offset
) {
313 ret_code
= LTTNG_ERR_INVALID
;
323 static enum lttng_error_code
flatten_lttng_channels(struct lttng_dynamic_pointer_array
*channels
,
324 struct lttng_channel
**flattened_channels
)
326 enum lttng_error_code ret_code
;
328 size_t storage_req
= 0;
329 struct lttng_dynamic_buffer local_flattened_channels
;
333 assert(flattened_channels
);
335 lttng_dynamic_buffer_init(&local_flattened_channels
);
336 nb_channels
= lttng_dynamic_pointer_array_get_count(channels
);
338 storage_req
+= sizeof(struct lttng_channel
) * nb_channels
;
339 storage_req
+= sizeof(struct lttng_channel_extended
) * nb_channels
;
342 * We must ensure that "local_flattened_channels" is never resized so as
343 * to preserve the validity of the flattened objects.
345 ret
= lttng_dynamic_buffer_set_capacity(&local_flattened_channels
, storage_req
);
347 ret_code
= LTTNG_ERR_NOMEM
;
351 /* Start by laying the struct lttng_channel */
352 for (i
= 0; i
< nb_channels
; i
++) {
353 const auto *element
=
354 (const struct lttng_channel
*) lttng_dynamic_pointer_array_get_pointer(
358 ret_code
= LTTNG_ERR_FATAL
;
362 ret
= lttng_dynamic_buffer_append(
363 &local_flattened_channels
, element
, sizeof(struct lttng_channel
));
365 ret_code
= LTTNG_ERR_NOMEM
;
370 /* Flatten the extended data */
371 for (i
= 0; i
< nb_channels
; i
++) {
372 const auto *element
=
373 (const struct lttng_channel
*) lttng_dynamic_pointer_array_get_pointer(
376 * Sample the location of the flattened channel we are about
379 auto *channel
= (struct lttng_channel
*) (local_flattened_channels
.data
+
380 (sizeof(struct lttng_channel
) * i
));
382 * Sample the location of the extended attributes we are about
385 const auto *channel_extended
=
386 (struct lttng_channel_extended
*) (local_flattened_channels
.data
+
387 local_flattened_channels
.size
);
390 ret_code
= LTTNG_ERR_FATAL
;
394 ret
= lttng_dynamic_buffer_append(&local_flattened_channels
,
395 element
->attr
.extended
.ptr
,
396 sizeof(struct lttng_channel_extended
));
398 ret_code
= LTTNG_ERR_NOMEM
;
403 * Update the flattened lttng_channel object with its flattened
404 * extended object location.
406 channel
->attr
.extended
.ptr
= (void *) channel_extended
;
409 /* Don't reset local_flattened_channels buffer as we return its content. */
410 *flattened_channels
= (struct lttng_channel
*) local_flattened_channels
.data
;
411 lttng_dynamic_buffer_init(&local_flattened_channels
);
414 lttng_dynamic_buffer_reset(&local_flattened_channels
);
418 enum lttng_error_code
lttng_channels_create_and_flatten_from_buffer(
419 const struct lttng_buffer_view
*view
, uint32_t count
, struct lttng_channel
**channels
)
421 enum lttng_error_code ret_code
;
422 struct lttng_dynamic_pointer_array local_channels
;
424 lttng_dynamic_pointer_array_init(&local_channels
, channel_list_destructor
);
426 /* Deserialize the channels */
428 const struct lttng_buffer_view channels_view
=
429 lttng_buffer_view_from_view(view
, 0, -1);
431 ret_code
= channel_list_create_from_buffer(&channels_view
, count
, &local_channels
);
432 if (ret_code
!= LTTNG_OK
) {
437 ret_code
= flatten_lttng_channels(&local_channels
, channels
);
440 lttng_dynamic_pointer_array_reset(&local_channels
);