2 * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include <common/macros.h>
9 #include <lttng/channel.h>
10 #include <lttng/constant.h>
11 #include <lttng/channel-internal.h>
12 #include <lttng/userspace-probe-internal.h>
13 #include <common/dynamic-buffer.h>
14 #include <common/error.h>
17 #include <common/sessiond-comm/sessiond-comm.h>
18 #include <common/dynamic-array.h>
19 #include <common/buffer-view.h>
21 static enum lttng_error_code
flatten_lttng_channels(
22 struct lttng_dynamic_pointer_array
*channels
,
23 struct lttng_channel
**flattened_channels
);
25 static enum lttng_error_code
channel_list_create_from_buffer(
26 const struct lttng_buffer_view
*buffer
,
28 struct lttng_dynamic_pointer_array
*channel_list
);
30 static void channel_list_destructor(void *ptr
)
32 struct lttng_channel
*element
= (struct lttng_channel
*) ptr
;
34 lttng_channel_destroy(element
);
37 struct lttng_channel
*lttng_channel_copy(const struct lttng_channel
*src
)
39 struct lttng_channel_extended
*extended
= nullptr;
40 struct lttng_channel
*channel
= nullptr, *ret
= nullptr;
42 channel
= (struct lttng_channel
*) zmalloc(sizeof(*channel
));
49 if (src
->attr
.extended
.ptr
) {
50 extended
= (struct lttng_channel_extended
*) zmalloc(
55 memcpy(extended
, src
->attr
.extended
.ptr
, sizeof(*extended
));
56 channel
->attr
.extended
.ptr
= extended
;
69 * The channel object is NOT populated.
71 struct lttng_channel
*lttng_channel_create_internal(void)
73 struct lttng_channel
*local_channel
= nullptr, *ret
= nullptr;
74 struct lttng_channel_extended
*extended
= nullptr;
76 local_channel
= (struct lttng_channel
*) zmalloc(
77 sizeof(struct lttng_channel
));
83 extended
= (struct lttng_channel_extended
*) zmalloc(
89 local_channel
->attr
.extended
.ptr
= extended
;
93 local_channel
= nullptr;
100 ssize_t
lttng_channel_create_from_buffer(const struct lttng_buffer_view
*view
,
101 struct lttng_channel
**channel
)
103 ssize_t ret
, offset
= 0;
104 struct lttng_channel
*local_channel
= nullptr;
105 const struct lttng_channel_comm
*channel_comm
;
106 struct lttng_channel_extended
*extended
= nullptr;
110 if (!view
|| !channel
) {
116 * Create an 'internal' channel since `lttng_create_channel` requires a
117 * domain and we cannot infer the domain from the payload.
119 local_channel
= lttng_channel_create_internal();
120 if (!local_channel
) {
125 extended
= (typeof(extended
)) local_channel
->attr
.extended
.ptr
;
127 /* lttng_trigger_comm header */
129 const struct lttng_buffer_view comm_view
=
130 lttng_buffer_view_from_view(view
, offset
,
131 sizeof(*channel_comm
));
133 if (!lttng_buffer_view_is_valid(&comm_view
)) {
138 channel_comm
= (const struct lttng_channel_comm
*)
140 offset
+= sizeof(*channel_comm
);
145 const struct lttng_buffer_view name_view
=
146 lttng_buffer_view_from_view(view
, offset
,
147 channel_comm
->name_len
);
149 if (channel_comm
->name_len
> LTTNG_SYMBOL_NAME_LEN
- 1) {
154 name
= name_view
.data
;
155 if (!lttng_buffer_view_contains_string(
156 &name_view
, name
, channel_comm
->name_len
)) {
161 strcpy(local_channel
->name
, name
);
162 offset
+= channel_comm
->name_len
;
165 /* Populate the channel */
166 local_channel
->enabled
= channel_comm
->enabled
;
169 local_channel
->attr
.overwrite
= channel_comm
->overwrite
;
170 local_channel
->attr
.subbuf_size
= channel_comm
->subbuf_size
;
171 local_channel
->attr
.num_subbuf
= channel_comm
->num_subbuf
;
172 local_channel
->attr
.switch_timer_interval
=
173 channel_comm
->switch_timer_interval
;
174 local_channel
->attr
.read_timer_interval
=
175 channel_comm
->read_timer_interval
;
176 local_channel
->attr
.output
= (enum lttng_event_output
) channel_comm
->output
;
177 local_channel
->attr
.tracefile_size
= channel_comm
->tracefile_size
;
178 local_channel
->attr
.tracefile_count
= channel_comm
->tracefile_count
;
179 local_channel
->attr
.live_timer_interval
=
180 channel_comm
->live_timer_interval
;
182 extended
->discarded_events
= channel_comm
->discarded_events
;
183 extended
->lost_packets
= channel_comm
->lost_packets
;
184 extended
->monitor_timer_interval
= channel_comm
->monitor_timer_interval
;
185 extended
->blocking_timeout
= channel_comm
->blocking_timeout
;
187 *channel
= local_channel
;
188 local_channel
= nullptr;
192 lttng_channel_destroy(local_channel
);
196 int lttng_channel_serialize(
197 struct lttng_channel
*channel
, struct lttng_dynamic_buffer
*buf
)
201 struct lttng_channel_comm channel_comm
= { 0 };
202 struct lttng_channel_extended
*extended
;
207 extended
= (struct lttng_channel_extended
*) channel
->attr
.extended
.ptr
;
209 name_len
= lttng_strnlen(channel
->name
, LTTNG_SYMBOL_NAME_LEN
);
210 if (name_len
== LTTNG_SYMBOL_NAME_LEN
) {
211 /* channel name is not nullptr-terminated. */
216 /* Include string termination. */
220 channel_comm
.name_len
= (uint32_t) name_len
;
221 channel_comm
.enabled
= channel
->enabled
;
224 channel_comm
.overwrite
= channel
->attr
.overwrite
;
225 channel_comm
.subbuf_size
= channel
->attr
.subbuf_size
;
226 channel_comm
.num_subbuf
= channel
->attr
.num_subbuf
;
227 channel_comm
.switch_timer_interval
=
228 channel
->attr
.switch_timer_interval
;
229 channel_comm
.read_timer_interval
= channel
->attr
.read_timer_interval
;
230 channel_comm
.output
= channel
->attr
.output
;
231 channel_comm
.tracefile_size
= channel
->attr
.tracefile_size
;
232 channel_comm
.tracefile_count
= channel
->attr
.tracefile_count
;
233 channel_comm
.live_timer_interval
= channel
->attr
.live_timer_interval
;
235 /* Extended struct */
236 channel_comm
.discarded_events
= extended
->discarded_events
;
237 channel_comm
.lost_packets
= extended
->lost_packets
;
238 channel_comm
.monitor_timer_interval
= extended
->monitor_timer_interval
;
239 channel_comm
.blocking_timeout
= extended
->blocking_timeout
;
242 ret
= lttng_dynamic_buffer_append(
243 buf
, &channel_comm
, sizeof(channel_comm
));
249 ret
= lttng_dynamic_buffer_append(buf
, channel
->name
, name_len
);
257 void lttng_channel_set_default_extended_attr(struct lttng_domain
*domain
,
258 struct lttng_channel_extended
*extended_attr
)
261 assert(extended_attr
);
263 memset(extended_attr
, 0, sizeof(*extended_attr
));
265 switch (domain
->type
) {
266 case LTTNG_DOMAIN_KERNEL
:
267 extended_attr
->monitor_timer_interval
=
268 DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER
;
269 extended_attr
->blocking_timeout
=
270 DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT
;
272 case LTTNG_DOMAIN_UST
:
273 switch (domain
->buf_type
) {
274 case LTTNG_BUFFER_PER_UID
:
275 extended_attr
->monitor_timer_interval
=
276 DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER
;
277 extended_attr
->blocking_timeout
=
278 DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT
;
280 case LTTNG_BUFFER_PER_PID
:
283 extended_attr
->monitor_timer_interval
=
284 DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER
;
285 extended_attr
->blocking_timeout
=
286 DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT
;
291 /* Default behavior: leave set to 0. */
296 static enum lttng_error_code
channel_list_create_from_buffer(
297 const struct lttng_buffer_view
*view
,
299 struct lttng_dynamic_pointer_array
*channel_list
)
301 enum lttng_error_code ret_code
;
306 assert(channel_list
);
308 for (i
= 0; i
< count
; i
++) {
309 ssize_t channel_size
;
310 struct lttng_channel
*channel
= nullptr;
311 const struct lttng_buffer_view channel_view
=
312 lttng_buffer_view_from_view(view
, offset
, -1);
314 channel_size
= lttng_channel_create_from_buffer(
315 &channel_view
, &channel
);
316 if (channel_size
< 0) {
317 ret_code
= LTTNG_ERR_INVALID
;
321 /* Lifetime and management of the object is now bound to the array. */
322 ret
= lttng_dynamic_pointer_array_add_pointer(channel_list
, channel
);
324 lttng_channel_destroy(channel
);
325 ret_code
= LTTNG_ERR_NOMEM
;
328 offset
+= channel_size
;
331 if (view
->size
!= offset
) {
332 ret_code
= LTTNG_ERR_INVALID
;
342 static enum lttng_error_code
flatten_lttng_channels(struct lttng_dynamic_pointer_array
*channels
,
343 struct lttng_channel
**flattened_channels
)
345 enum lttng_error_code ret_code
;
347 size_t storage_req
= 0;
348 struct lttng_dynamic_buffer local_flattened_channels
;
352 assert(flattened_channels
);
354 lttng_dynamic_buffer_init(&local_flattened_channels
);
355 nb_channels
= lttng_dynamic_pointer_array_get_count(channels
);
357 storage_req
+= sizeof(struct lttng_channel
) * nb_channels
;
358 storage_req
+= sizeof(struct lttng_channel_extended
) * nb_channels
;
361 * We must ensure that "local_flattened_channels" is never resized so as
362 * to preserve the validity of the flattened objects.
364 ret
= lttng_dynamic_buffer_set_capacity(
365 &local_flattened_channels
, storage_req
);
367 ret_code
= LTTNG_ERR_NOMEM
;
371 /* Start by laying the struct lttng_channel */
372 for (i
= 0; i
< nb_channels
; i
++) {
373 const auto *element
= (const struct lttng_channel
*)
374 lttng_dynamic_pointer_array_get_pointer(
378 ret_code
= LTTNG_ERR_FATAL
;
382 ret
= lttng_dynamic_buffer_append(&local_flattened_channels
,
383 element
, sizeof(struct lttng_channel
));
385 ret_code
= LTTNG_ERR_NOMEM
;
390 /* Flatten the extended data */
391 for (i
= 0; i
< nb_channels
; i
++) {
392 const auto *element
= (const struct lttng_channel
*)
393 lttng_dynamic_pointer_array_get_pointer(
396 * Sample the location of the flattened channel we are about
399 auto *channel
= (struct lttng_channel
*)
400 (local_flattened_channels
.data
+ (sizeof(struct lttng_channel
) * i
));
402 * Sample the location of the extended attributes we are about
405 const auto *channel_extended
= (struct lttng_channel_extended
*)
406 (local_flattened_channels
.data
+ local_flattened_channels
.size
);
409 ret_code
= LTTNG_ERR_FATAL
;
413 ret
= lttng_dynamic_buffer_append(&local_flattened_channels
,
414 element
->attr
.extended
.ptr
,
415 sizeof(struct lttng_channel_extended
));
417 ret_code
= LTTNG_ERR_NOMEM
;
422 * Update the flattened lttng_channel object with its flattened
423 * extended object location.
425 channel
->attr
.extended
.ptr
= (void *) channel_extended
;
428 /* Don't reset local_flattened_channels buffer as we return its content. */
429 *flattened_channels
= (struct lttng_channel
*) local_flattened_channels
.data
;
430 lttng_dynamic_buffer_init(&local_flattened_channels
);
433 lttng_dynamic_buffer_reset(&local_flattened_channels
);
437 enum lttng_error_code
lttng_channels_create_and_flatten_from_buffer(
438 const struct lttng_buffer_view
*view
,
440 struct lttng_channel
**channels
)
442 enum lttng_error_code ret_code
;
443 struct lttng_dynamic_pointer_array local_channels
;
445 lttng_dynamic_pointer_array_init(&local_channels
, channel_list_destructor
);
447 /* Deserialize the channels */
449 const struct lttng_buffer_view channels_view
=
450 lttng_buffer_view_from_view(view
, 0, -1);
452 ret_code
= channel_list_create_from_buffer(
453 &channels_view
, count
, &local_channels
);
454 if (ret_code
!= LTTNG_OK
) {
459 ret_code
= flatten_lttng_channels(&local_channels
, channels
);
462 lttng_dynamic_pointer_array_reset(&local_channels
);