utils: Allow users to define LTTNG_MANPATH
[lttng-tools.git] / src / common / channel.cpp
1 /*
2 * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
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>
15
16 #include <lttng/channel-internal.hpp>
17 #include <lttng/channel.h>
18 #include <lttng/constant.h>
19 #include <lttng/userspace-probe-internal.hpp>
20
21 static enum lttng_error_code flatten_lttng_channels(struct lttng_dynamic_pointer_array *channels,
22 struct lttng_channel **flattened_channels);
23
24 static enum lttng_error_code
25 channel_list_create_from_buffer(const struct lttng_buffer_view *buffer,
26 uint32_t count,
27 struct lttng_dynamic_pointer_array *channel_list);
28
29 static void channel_list_destructor(void *ptr)
30 {
31 struct lttng_channel *element = (struct lttng_channel *) ptr;
32
33 lttng_channel_destroy(element);
34 }
35
36 struct lttng_channel *lttng_channel_copy(const struct lttng_channel *src)
37 {
38 struct lttng_channel_extended *extended = nullptr;
39 struct lttng_channel *channel = nullptr, *ret = nullptr;
40
41 channel = zmalloc<lttng_channel>();
42 if (!channel) {
43 goto end;
44 }
45
46 *channel = *src;
47
48 if (src->attr.extended.ptr) {
49 extended = zmalloc<lttng_channel_extended>();
50 if (!extended) {
51 goto end;
52 }
53 memcpy(extended, src->attr.extended.ptr, sizeof(*extended));
54 channel->attr.extended.ptr = extended;
55 extended = nullptr;
56 }
57
58 ret = channel;
59 channel = nullptr;
60 end:
61 free(channel);
62 free(extended);
63 return ret;
64 }
65
66 /*
67 * The channel object is NOT populated.
68 */
69 struct lttng_channel *lttng_channel_create_internal()
70 {
71 struct lttng_channel *local_channel = nullptr, *ret = nullptr;
72 struct lttng_channel_extended *extended = nullptr;
73
74 local_channel = zmalloc<lttng_channel>();
75 if (!local_channel) {
76 goto end;
77 }
78
79 /* Extended struct */
80 extended = zmalloc<lttng_channel_extended>();
81 if (!extended) {
82 goto end;
83 }
84
85 local_channel->attr.extended.ptr = extended;
86 extended = nullptr;
87
88 ret = local_channel;
89 local_channel = nullptr;
90 end:
91 free(extended);
92 free(local_channel);
93 return ret;
94 }
95
96 ssize_t lttng_channel_create_from_buffer(const struct lttng_buffer_view *view,
97 struct lttng_channel **channel)
98 {
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;
103
104 assert(channel);
105
106 if (!view || !channel) {
107 ret = -1;
108 goto end;
109 }
110
111 /*
112 * Create an 'internal' channel since `lttng_create_channel` requires a
113 * domain and we cannot infer the domain from the payload.
114 */
115 local_channel = lttng_channel_create_internal();
116 if (!local_channel) {
117 ret = -1;
118 goto end;
119 }
120
121 extended = (typeof(extended)) local_channel->attr.extended.ptr;
122
123 /* lttng_trigger_comm header */
124 {
125 const struct lttng_buffer_view comm_view =
126 lttng_buffer_view_from_view(view, offset, sizeof(*channel_comm));
127
128 if (!lttng_buffer_view_is_valid(&comm_view)) {
129 ret = -1;
130 goto end;
131 }
132
133 channel_comm = (const struct lttng_channel_comm *) comm_view.data;
134 offset += sizeof(*channel_comm);
135 }
136
137 {
138 const char *name;
139 const struct lttng_buffer_view name_view =
140 lttng_buffer_view_from_view(view, offset, channel_comm->name_len);
141
142 name = name_view.data;
143 if (!lttng_buffer_view_contains_string(&name_view, name, channel_comm->name_len)) {
144 ret = -1;
145 goto end;
146 }
147
148 ret = lttng_strncpy(local_channel->name, name, sizeof(local_channel->name));
149 if (ret) {
150 goto end;
151 }
152
153 offset += channel_comm->name_len;
154 }
155
156 /* Populate the channel */
157 local_channel->enabled = channel_comm->enabled;
158
159 /* attr */
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;
169
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;
174
175 *channel = local_channel;
176 local_channel = nullptr;
177
178 ret = offset;
179 end:
180 lttng_channel_destroy(local_channel);
181 return ret;
182 }
183
184 int lttng_channel_serialize(struct lttng_channel *channel, struct lttng_dynamic_buffer *buf)
185 {
186 int ret;
187 size_t name_len;
188 struct lttng_channel_comm channel_comm = {};
189 struct lttng_channel_extended *extended;
190
191 assert(channel);
192 assert(buf);
193
194 extended = (struct lttng_channel_extended *) channel->attr.extended.ptr;
195
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. */
199 ret = -1;
200 goto end;
201 }
202
203 /* Include string termination. */
204 name_len += 1;
205
206 /* Base field */
207 channel_comm.name_len = (uint32_t) name_len;
208 channel_comm.enabled = channel->enabled;
209
210 /* attr */
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;
220
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;
226
227 /* Header */
228 ret = lttng_dynamic_buffer_append(buf, &channel_comm, sizeof(channel_comm));
229 if (ret) {
230 goto end;
231 }
232
233 /* channel name */
234 ret = lttng_dynamic_buffer_append(buf, channel->name, name_len);
235 if (ret) {
236 goto end;
237 }
238 end:
239 return ret;
240 }
241
242 void lttng_channel_set_default_extended_attr(struct lttng_domain *domain,
243 struct lttng_channel_extended *extended_attr)
244 {
245 assert(domain);
246 assert(extended_attr);
247
248 memset(extended_attr, 0, sizeof(*extended_attr));
249
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;
254 break;
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;
261 break;
262 case LTTNG_BUFFER_PER_PID:
263 default:
264 if (extended_attr) {
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;
269 }
270 break;
271 }
272 default:
273 /* Default behavior: leave set to 0. */
274 break;
275 }
276 }
277
278 static enum lttng_error_code
279 channel_list_create_from_buffer(const struct lttng_buffer_view *view,
280 unsigned int count,
281 struct lttng_dynamic_pointer_array *channel_list)
282 {
283 enum lttng_error_code ret_code;
284 int ret, i;
285 int offset = 0;
286
287 assert(view);
288 assert(channel_list);
289
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);
295
296 channel_size = lttng_channel_create_from_buffer(&channel_view, &channel);
297 if (channel_size < 0) {
298 ret_code = LTTNG_ERR_INVALID;
299 goto end;
300 }
301
302 /* Lifetime and management of the object is now bound to the array. */
303 ret = lttng_dynamic_pointer_array_add_pointer(channel_list, channel);
304 if (ret) {
305 lttng_channel_destroy(channel);
306 ret_code = LTTNG_ERR_NOMEM;
307 goto end;
308 }
309 offset += channel_size;
310 }
311
312 if (view->size != offset) {
313 ret_code = LTTNG_ERR_INVALID;
314 goto end;
315 }
316
317 ret_code = LTTNG_OK;
318
319 end:
320 return ret_code;
321 }
322
323 static enum lttng_error_code flatten_lttng_channels(struct lttng_dynamic_pointer_array *channels,
324 struct lttng_channel **flattened_channels)
325 {
326 enum lttng_error_code ret_code;
327 int ret, i;
328 size_t storage_req = 0;
329 struct lttng_dynamic_buffer local_flattened_channels;
330 int nb_channels;
331
332 assert(channels);
333 assert(flattened_channels);
334
335 lttng_dynamic_buffer_init(&local_flattened_channels);
336 nb_channels = lttng_dynamic_pointer_array_get_count(channels);
337
338 storage_req += sizeof(struct lttng_channel) * nb_channels;
339 storage_req += sizeof(struct lttng_channel_extended) * nb_channels;
340
341 /*
342 * We must ensure that "local_flattened_channels" is never resized so as
343 * to preserve the validity of the flattened objects.
344 */
345 ret = lttng_dynamic_buffer_set_capacity(&local_flattened_channels, storage_req);
346 if (ret) {
347 ret_code = LTTNG_ERR_NOMEM;
348 goto end;
349 }
350
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(
355 channels, i);
356
357 if (!element) {
358 ret_code = LTTNG_ERR_FATAL;
359 goto end;
360 }
361
362 ret = lttng_dynamic_buffer_append(
363 &local_flattened_channels, element, sizeof(struct lttng_channel));
364 if (ret) {
365 ret_code = LTTNG_ERR_NOMEM;
366 goto end;
367 }
368 }
369
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(
374 channels, i);
375 /*
376 * Sample the location of the flattened channel we are about
377 * to modify.
378 */
379 auto *channel = (struct lttng_channel *) (local_flattened_channels.data +
380 (sizeof(struct lttng_channel) * i));
381 /*
382 * Sample the location of the extended attributes we are about
383 * to add.
384 */
385 const auto *channel_extended =
386 (struct lttng_channel_extended *) (local_flattened_channels.data +
387 local_flattened_channels.size);
388
389 if (!element) {
390 ret_code = LTTNG_ERR_FATAL;
391 goto end;
392 }
393
394 ret = lttng_dynamic_buffer_append(&local_flattened_channels,
395 element->attr.extended.ptr,
396 sizeof(struct lttng_channel_extended));
397 if (ret) {
398 ret_code = LTTNG_ERR_NOMEM;
399 goto end;
400 }
401
402 /*
403 * Update the flattened lttng_channel object with its flattened
404 * extended object location.
405 */
406 channel->attr.extended.ptr = (void *) channel_extended;
407 }
408
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);
412 ret_code = LTTNG_OK;
413 end:
414 lttng_dynamic_buffer_reset(&local_flattened_channels);
415 return ret_code;
416 }
417
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)
420 {
421 enum lttng_error_code ret_code;
422 struct lttng_dynamic_pointer_array local_channels;
423
424 lttng_dynamic_pointer_array_init(&local_channels, channel_list_destructor);
425
426 /* Deserialize the channels */
427 {
428 const struct lttng_buffer_view channels_view =
429 lttng_buffer_view_from_view(view, 0, -1);
430
431 ret_code = channel_list_create_from_buffer(&channels_view, count, &local_channels);
432 if (ret_code != LTTNG_OK) {
433 goto end;
434 }
435 }
436
437 ret_code = flatten_lttng_channels(&local_channels, channels);
438
439 end:
440 lttng_dynamic_pointer_array_reset(&local_channels);
441 return ret_code;
442 }
This page took 0.049261 seconds and 4 git commands to generate.