Add kernel and UST time namespace context
[lttng-tools.git] / src / bin / lttng-sessiond / ust-metadata.c
CommitLineData
d0b96690 1/*
d0b96690
DG
2 * Copyright (C) 2010-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
d0b96690 5 *
d0b96690
DG
6 */
7
6c1c0768 8#define _LGPL_SOURCE
d0b96690
DG
9#include <stdint.h>
10#include <string.h>
11#include <stdarg.h>
12#include <stdio.h>
13#include <limits.h>
14#include <unistd.h>
15#include <inttypes.h>
16#include <common/common.h>
395d6b02 17#include <common/time.h>
d0b96690
DG
18
19#include "ust-registry.h"
20#include "ust-clock.h"
21#include "ust-app.h"
22
23#ifndef max_t
24#define max_t(type, a, b) ((type) ((a) > (b) ? (a) : (b)))
25#endif
26
8c645bb0
MD
27#define NR_CLOCK_OFFSET_SAMPLES 10
28
29struct offset_sample {
c2636b57 30 int64_t offset; /* correlation offset */
8c645bb0
MD
31 uint64_t measure_delta; /* lower is better */
32};
33
da860cab
MD
34static
35int _lttng_field_statedump(struct ust_registry_session *session,
36 const struct ustctl_field *fields, size_t nr_fields,
37 size_t *iter_field, size_t nesting);
38
d0b96690
DG
39static inline
40int fls(unsigned int x)
41{
42 int r = 32;
43
44 if (!x)
45 return 0;
46 if (!(x & 0xFFFF0000U)) {
47 x <<= 16;
48 r -= 16;
49 }
50 if (!(x & 0xFF000000U)) {
51 x <<= 8;
52 r -= 8;
53 }
54 if (!(x & 0xF0000000U)) {
55 x <<= 4;
56 r -= 4;
57 }
58 if (!(x & 0xC0000000U)) {
59 x <<= 2;
60 r -= 2;
61 }
62 if (!(x & 0x80000000U)) {
d0b96690
DG
63 r -= 1;
64 }
65 return r;
66}
67
68static inline
69int get_count_order(unsigned int count)
70{
71 int order;
72
73 order = fls(count) - 1;
46b4dda6 74 if (count & (count - 1)) {
d0b96690 75 order++;
46b4dda6
JG
76 }
77 assert(order >= 0);
d0b96690
DG
78 return order;
79}
80
81/*
82 * Returns offset where to write in metadata array, or negative error value on error.
83 */
84static
85ssize_t metadata_reserve(struct ust_registry_session *session, size_t len)
86{
87 size_t new_len = session->metadata_len + len;
88 size_t new_alloc_len = new_len;
89 size_t old_alloc_len = session->metadata_alloc_len;
90 ssize_t ret;
91
92 if (new_alloc_len > (UINT32_MAX >> 1))
93 return -EINVAL;
94 if ((old_alloc_len << 1) > (UINT32_MAX >> 1))
95 return -EINVAL;
96
97 if (new_alloc_len > old_alloc_len) {
98 char *newptr;
99
100 new_alloc_len =
101 max_t(size_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1);
102 newptr = realloc(session->metadata, new_alloc_len);
103 if (!newptr)
104 return -ENOMEM;
105 session->metadata = newptr;
106 /* We zero directly the memory from start of allocation. */
107 memset(&session->metadata[old_alloc_len], 0, new_alloc_len - old_alloc_len);
108 session->metadata_alloc_len = new_alloc_len;
109 }
110 ret = session->metadata_len;
111 session->metadata_len += len;
112 return ret;
113}
114
d7ba1388
MD
115static
116int metadata_file_append(struct ust_registry_session *session,
117 const char *str, size_t len)
118{
119 ssize_t written;
120
121 if (session->metadata_fd < 0) {
122 return 0;
123 }
124 /* Write to metadata file */
125 written = lttng_write(session->metadata_fd, str, len);
126 if (written != len) {
127 return -1;
128 }
129 return 0;
130}
131
d0b96690
DG
132/*
133 * We have exclusive access to our metadata buffer (protected by the
134 * ust_lock), so we can do racy operations such as looking for
135 * remaining space left in packet and write, since mutual exclusion
136 * protects us from concurrent writes.
137 */
138static
139int lttng_metadata_printf(struct ust_registry_session *session,
140 const char *fmt, ...)
141{
142 char *str = NULL;
143 size_t len;
144 va_list ap;
145 ssize_t offset;
146 int ret;
147
148 va_start(ap, fmt);
149 ret = vasprintf(&str, fmt, ap);
150 va_end(ap);
151 if (ret < 0)
152 return -ENOMEM;
153
154 len = strlen(str);
155 offset = metadata_reserve(session, len);
156 if (offset < 0) {
157 ret = offset;
158 goto end;
159 }
160 memcpy(&session->metadata[offset], str, len);
d7ba1388
MD
161 ret = metadata_file_append(session, str, len);
162 if (ret) {
163 PERROR("Error appending to metadata file");
164 goto end;
165 }
d0b96690
DG
166 DBG3("Append to metadata: \"%s\"", str);
167 ret = 0;
168
169end:
170 free(str);
171 return ret;
172}
173
da860cab
MD
174static
175int print_tabs(struct ust_registry_session *session, size_t nesting)
176{
177 size_t i;
178
179 for (i = 0; i < nesting; i++) {
180 int ret;
181
182 ret = lttng_metadata_printf(session, " ");
183 if (ret) {
184 return ret;
185 }
186 }
187 return 0;
188}
189
a1f68b22
MD
190static
191void sanitize_ctf_identifier(char *out, const char *in)
192{
193 size_t i;
194
195 for (i = 0; i < LTTNG_UST_SYM_NAME_LEN; i++) {
196 switch (in[i]) {
197 case '.':
198 case '$':
199 case ':':
200 out[i] = '_';
201 break;
202 default:
203 out[i] = in[i];
204 }
205 }
206}
207
8de88061
JR
208static
209int print_escaped_ctf_string(struct ust_registry_session *session, const char *string)
210{
35c829f8 211 int ret = 0;
8de88061
JR
212 size_t i;
213 char cur;
214
215 i = 0;
216 cur = string[i];
217 while (cur != '\0') {
218 switch (cur) {
219 case '\n':
220 ret = lttng_metadata_printf(session, "%s", "\\n");
221 break;
222 case '\\':
223 case '"':
224 ret = lttng_metadata_printf(session, "%c", '\\');
225 if (ret) {
226 goto error;
227 }
228 /* We still print the current char */
229 /* Fallthrough */
230 default:
231 ret = lttng_metadata_printf(session, "%c", cur);
232 break;
233 }
234
235 if (ret) {
236 goto error;
237 }
238
239 cur = string[++i];
240 }
241error:
242 return ret;
243}
244
10b56aef
MD
245/* Called with session registry mutex held. */
246static
247int ust_metadata_enum_statedump(struct ust_registry_session *session,
248 const char *enum_name,
249 uint64_t enum_id,
250 const struct ustctl_integer_type *container_type,
da860cab 251 const char *field_name, size_t *iter_field, size_t nesting)
10b56aef
MD
252{
253 struct ust_registry_enum *reg_enum;
254 const struct ustctl_enum_entry *entries;
255 size_t nr_entries;
256 int ret = 0;
257 size_t i;
a1f68b22 258 char identifier[LTTNG_UST_SYM_NAME_LEN];
10b56aef
MD
259
260 rcu_read_lock();
261 reg_enum = ust_registry_lookup_enum_by_id(session, enum_name, enum_id);
262 rcu_read_unlock();
263 /* reg_enum can still be used because session registry mutex is held. */
264 if (!reg_enum) {
265 ret = -ENOENT;
266 goto end;
267 }
268 entries = reg_enum->entries;
269 nr_entries = reg_enum->nr_entries;
270
da860cab
MD
271 ret = print_tabs(session, nesting);
272 if (ret) {
273 goto end;
274 }
10b56aef 275 ret = lttng_metadata_printf(session,
da860cab 276 "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u; } {\n",
10b56aef
MD
277 container_type->size,
278 container_type->alignment,
279 container_type->signedness,
280 (container_type->encoding == ustctl_encode_none)
281 ? "none"
282 : (container_type->encoding == ustctl_encode_UTF8)
283 ? "UTF8"
284 : "ASCII",
285 container_type->base);
286 if (ret) {
287 goto end;
288 }
1ddb0e8a 289 nesting++;
10b56aef
MD
290 /* Dump all entries */
291 for (i = 0; i < nr_entries; i++) {
292 const struct ustctl_enum_entry *entry = &entries[i];
293 int j, len;
294
a1f68b22
MD
295 ret = print_tabs(session, nesting);
296 if (ret) {
297 goto end;
298 }
10b56aef 299 ret = lttng_metadata_printf(session,
a1f68b22 300 "\"");
10b56aef
MD
301 if (ret) {
302 goto end;
303 }
304 len = strlen(entry->string);
305 /* Escape the character '"' */
306 for (j = 0; j < len; j++) {
307 char c = entry->string[j];
308
309 switch (c) {
310 case '"':
311 ret = lttng_metadata_printf(session,
312 "\\\"");
313 break;
314 case '\\':
315 ret = lttng_metadata_printf(session,
316 "\\\\");
317 break;
318 default:
319 ret = lttng_metadata_printf(session,
320 "%c", c);
321 break;
322 }
323 if (ret) {
324 goto end;
325 }
326 }
e85e3723 327 ret = lttng_metadata_printf(session, "\"");
10b56aef
MD
328 if (ret) {
329 goto end;
330 }
3b016e58 331
9d27cec7
PP
332 if (entry->u.extra.options &
333 USTCTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
e85e3723
PP
334 ret = lttng_metadata_printf(session, ",\n");
335 if (ret) {
336 goto end;
337 }
10b56aef
MD
338 } else {
339 ret = lttng_metadata_printf(session,
e85e3723
PP
340 " = ");
341 if (ret) {
342 goto end;
343 }
3b016e58 344
e85e3723 345 if (entry->start.signedness) {
3b016e58 346 ret = lttng_metadata_printf(session,
e85e3723 347 "%lld", (long long) entry->start.value);
3b016e58
MD
348 } else {
349 ret = lttng_metadata_printf(session,
e85e3723
PP
350 "%llu", entry->start.value);
351 }
352 if (ret) {
353 goto end;
354 }
355
356 if (entry->start.signedness == entry->end.signedness &&
357 entry->start.value ==
358 entry->end.value) {
359 ret = lttng_metadata_printf(session, ",\n");
360 } else {
361 if (entry->end.signedness) {
362 ret = lttng_metadata_printf(session,
363 " ... %lld,\n",
364 (long long) entry->end.value);
365 } else {
366 ret = lttng_metadata_printf(session,
367 " ... %llu,\n",
368 entry->end.value);
369 }
370 }
371 if (ret) {
372 goto end;
3b016e58 373 }
10b56aef
MD
374 }
375 }
1ddb0e8a 376 nesting--;
a1f68b22
MD
377 sanitize_ctf_identifier(identifier, field_name);
378 ret = print_tabs(session, nesting);
379 if (ret) {
380 goto end;
381 }
382 ret = lttng_metadata_printf(session, "} _%s;\n",
383 identifier);
da860cab
MD
384end:
385 (*iter_field)++;
386 return ret;
387}
388
da860cab
MD
389static
390int _lttng_variant_statedump(struct ust_registry_session *session,
0d32d1a9
MD
391 uint32_t nr_choices, const char *tag_name,
392 uint32_t alignment,
da860cab
MD
393 const struct ustctl_field *fields, size_t nr_fields,
394 size_t *iter_field, size_t nesting)
395{
396 const struct ustctl_field *variant = &fields[*iter_field];
0d32d1a9 397 uint32_t i;
da860cab 398 int ret;
a1f68b22 399 char identifier[LTTNG_UST_SYM_NAME_LEN];
da860cab
MD
400
401 if (variant->type.atype != ustctl_atype_variant) {
402 ret = -EINVAL;
403 goto end;
404 }
da860cab 405 (*iter_field)++;
0d32d1a9
MD
406 sanitize_ctf_identifier(identifier, tag_name);
407 if (alignment) {
408 ret = print_tabs(session, nesting);
409 if (ret) {
410 goto end;
411 }
412 ret = lttng_metadata_printf(session,
413 "struct { } align(%u) _%s_padding;\n",
414 alignment * CHAR_BIT,
415 variant->name);
416 if (ret) {
417 goto end;
418 }
419 }
a1f68b22
MD
420 ret = print_tabs(session, nesting);
421 if (ret) {
422 goto end;
423 }
da860cab 424 ret = lttng_metadata_printf(session,
a1f68b22
MD
425 "variant <_%s> {\n",
426 identifier);
da860cab
MD
427 if (ret) {
428 goto end;
429 }
430
431 for (i = 0; i < nr_choices; i++) {
432 if (*iter_field >= nr_fields) {
433 ret = -EOVERFLOW;
434 goto end;
435 }
436 ret = _lttng_field_statedump(session,
437 fields, nr_fields,
438 iter_field, nesting + 1);
dc6403f3
JG
439 if (ret) {
440 goto end;
441 }
da860cab 442 }
a1f68b22
MD
443 sanitize_ctf_identifier(identifier, variant->name);
444 ret = print_tabs(session, nesting);
850c5d4a
JR
445 if (ret) {
446 goto end;
447 }
da860cab 448 ret = lttng_metadata_printf(session,
a1f68b22
MD
449 "} _%s;\n",
450 identifier);
da860cab
MD
451 if (ret) {
452 goto end;
453 }
10b56aef
MD
454end:
455 return ret;
456}
457
d0b96690
DG
458static
459int _lttng_field_statedump(struct ust_registry_session *session,
da860cab
MD
460 const struct ustctl_field *fields, size_t nr_fields,
461 size_t *iter_field, size_t nesting)
d0b96690
DG
462{
463 int ret = 0;
464 const char *bo_be = " byte_order = be;";
465 const char *bo_le = " byte_order = le;";
466 const char *bo_native = "";
467 const char *bo_reverse;
da860cab 468 const struct ustctl_field *field;
d0b96690 469
da860cab
MD
470 if (*iter_field >= nr_fields) {
471 ret = -EOVERFLOW;
472 goto end;
473 }
474 field = &fields[*iter_field];
475
476 if (session->byte_order == BIG_ENDIAN) {
d0b96690 477 bo_reverse = bo_le;
da860cab 478 } else {
d0b96690 479 bo_reverse = bo_be;
da860cab 480 }
d0b96690
DG
481
482 switch (field->type.atype) {
483 case ustctl_atype_integer:
da860cab
MD
484 ret = print_tabs(session, nesting);
485 if (ret) {
486 goto end;
487 }
d0b96690 488 ret = lttng_metadata_printf(session,
da860cab 489 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
0d32d1a9
MD
490 field->type.u.integer.size,
491 field->type.u.integer.alignment,
492 field->type.u.integer.signedness,
493 (field->type.u.integer.encoding == ustctl_encode_none)
d0b96690 494 ? "none"
0d32d1a9 495 : (field->type.u.integer.encoding == ustctl_encode_UTF8)
d0b96690
DG
496 ? "UTF8"
497 : "ASCII",
0d32d1a9
MD
498 field->type.u.integer.base,
499 field->type.u.integer.reverse_byte_order ? bo_reverse : bo_native,
d0b96690 500 field->name);
da860cab 501 (*iter_field)++;
d0b96690 502 break;
10b56aef
MD
503 case ustctl_atype_enum:
504 ret = ust_metadata_enum_statedump(session,
0d32d1a9
MD
505 field->type.u.legacy.basic.enumeration.name,
506 field->type.u.legacy.basic.enumeration.id,
507 &field->type.u.legacy.basic.enumeration.container_type,
da860cab 508 field->name, iter_field, nesting);
10b56aef 509 break;
d0b96690 510 case ustctl_atype_float:
da860cab
MD
511 ret = print_tabs(session, nesting);
512 if (ret) {
513 goto end;
514 }
d0b96690 515 ret = lttng_metadata_printf(session,
da860cab 516 "floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n",
0d32d1a9
MD
517 field->type.u._float.exp_dig,
518 field->type.u._float.mant_dig,
519 field->type.u._float.alignment,
520 field->type.u._float.reverse_byte_order ? bo_reverse : bo_native,
d0b96690 521 field->name);
da860cab 522 (*iter_field)++;
d0b96690 523 break;
d0b96690
DG
524 case ustctl_atype_array:
525 {
526 const struct ustctl_basic_type *elem_type;
527
da860cab
MD
528 ret = print_tabs(session, nesting);
529 if (ret) {
530 goto end;
531 }
0d32d1a9
MD
532 elem_type = &field->type.u.legacy.array.elem_type;
533 /* Only integers are currently supported in arrays. */
534 if (elem_type->atype != ustctl_atype_integer) {
535 ret = -EINVAL;
536 goto end;
537 }
d0b96690 538 ret = lttng_metadata_printf(session,
da860cab 539 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
d0b96690
DG
540 elem_type->u.basic.integer.size,
541 elem_type->u.basic.integer.alignment,
542 elem_type->u.basic.integer.signedness,
543 (elem_type->u.basic.integer.encoding == ustctl_encode_none)
544 ? "none"
545 : (elem_type->u.basic.integer.encoding == ustctl_encode_UTF8)
546 ? "UTF8"
547 : "ASCII",
548 elem_type->u.basic.integer.base,
549 elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
0d32d1a9
MD
550 field->name, field->type.u.legacy.array.length);
551 (*iter_field)++;
552 break;
553 }
554 case ustctl_atype_array_nestable:
555 {
556 uint32_t array_length;
557 const struct ustctl_field *array_nestable;
558 const struct ustctl_type *elem_type;
559
560 array_length = field->type.u.array_nestable.length;
561 (*iter_field)++;
562
563 if (*iter_field >= nr_fields) {
564 ret = -EOVERFLOW;
565 goto end;
566 }
567 array_nestable = &fields[*iter_field];
568 elem_type = &array_nestable->type;
569
570 /* Only integers are currently supported in arrays. */
571 if (elem_type->atype != ustctl_atype_integer) {
572 ret = -EINVAL;
573 goto end;
574 }
575
576 if (field->type.u.array_nestable.alignment) {
577 ret = print_tabs(session, nesting);
578 if (ret) {
579 goto end;
580 }
581 ret = lttng_metadata_printf(session,
582 "struct { } align(%u) _%s_padding;\n",
583 field->type.u.array_nestable.alignment * CHAR_BIT,
584 field->name);
585 if (ret) {
586 goto end;
587 }
588 }
589
590 ret = print_tabs(session, nesting);
591 if (ret) {
592 goto end;
593 }
594 ret = lttng_metadata_printf(session,
595 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
596 elem_type->u.integer.size,
597 elem_type->u.integer.alignment,
598 elem_type->u.integer.signedness,
599 (elem_type->u.integer.encoding == ustctl_encode_none)
600 ? "none"
601 : (elem_type->u.integer.encoding == ustctl_encode_UTF8)
602 ? "UTF8"
603 : "ASCII",
604 elem_type->u.integer.base,
605 elem_type->u.integer.reverse_byte_order ? bo_reverse : bo_native,
606 field->name, array_length);
da860cab 607 (*iter_field)++;
d0b96690
DG
608 break;
609 }
610 case ustctl_atype_sequence:
611 {
612 const struct ustctl_basic_type *elem_type;
613 const struct ustctl_basic_type *length_type;
614
0d32d1a9
MD
615 elem_type = &field->type.u.legacy.sequence.elem_type;
616 length_type = &field->type.u.legacy.sequence.length_type;
da860cab
MD
617 ret = print_tabs(session, nesting);
618 if (ret) {
619 goto end;
620 }
0d32d1a9
MD
621
622 /* Only integers are currently supported in sequences. */
623 if (elem_type->atype != ustctl_atype_integer) {
624 ret = -EINVAL;
625 goto end;
626 }
627
d0b96690 628 ret = lttng_metadata_printf(session,
da860cab 629 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
d0b96690
DG
630 length_type->u.basic.integer.size,
631 (unsigned int) length_type->u.basic.integer.alignment,
632 length_type->u.basic.integer.signedness,
633 (length_type->u.basic.integer.encoding == ustctl_encode_none)
634 ? "none"
635 : ((length_type->u.basic.integer.encoding == ustctl_encode_UTF8)
636 ? "UTF8"
637 : "ASCII"),
638 length_type->u.basic.integer.base,
639 length_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
640 field->name);
da860cab
MD
641 if (ret) {
642 goto end;
643 }
d0b96690 644
da860cab
MD
645 ret = print_tabs(session, nesting);
646 if (ret) {
647 goto end;
648 }
d0b96690 649 ret = lttng_metadata_printf(session,
da860cab 650 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
d0b96690
DG
651 elem_type->u.basic.integer.size,
652 (unsigned int) elem_type->u.basic.integer.alignment,
653 elem_type->u.basic.integer.signedness,
654 (elem_type->u.basic.integer.encoding == ustctl_encode_none)
655 ? "none"
656 : ((elem_type->u.basic.integer.encoding == ustctl_encode_UTF8)
657 ? "UTF8"
658 : "ASCII"),
659 elem_type->u.basic.integer.base,
660 elem_type->u.basic.integer.reverse_byte_order ? bo_reverse : bo_native,
661 field->name,
662 field->name);
da860cab 663 (*iter_field)++;
d0b96690
DG
664 break;
665 }
0d32d1a9
MD
666 case ustctl_atype_sequence_nestable:
667 {
668 const struct ustctl_field *sequence_nestable;
669 const struct ustctl_type *elem_type;
670
671 (*iter_field)++;
672 if (*iter_field >= nr_fields) {
673 ret = -EOVERFLOW;
674 goto end;
675 }
676 sequence_nestable = &fields[*iter_field];
677 elem_type = &sequence_nestable->type;
678
679 /* Only integers are currently supported in sequences. */
680 if (elem_type->atype != ustctl_atype_integer) {
681 ret = -EINVAL;
682 goto end;
683 }
684
685 if (field->type.u.sequence_nestable.alignment) {
686 ret = print_tabs(session, nesting);
687 if (ret) {
688 goto end;
689 }
690 ret = lttng_metadata_printf(session,
691 "struct { } align(%u) _%s_padding;\n",
692 field->type.u.sequence_nestable.alignment * CHAR_BIT,
693 field->name);
694 if (ret) {
695 goto end;
696 }
697 }
d0b96690 698
0d32d1a9
MD
699 ret = print_tabs(session, nesting);
700 if (ret) {
701 goto end;
702 }
703 ret = lttng_metadata_printf(session,
704 "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ _%s ];\n",
705 elem_type->u.integer.size,
706 (unsigned int) elem_type->u.integer.alignment,
707 elem_type->u.integer.signedness,
708 (elem_type->u.integer.encoding == ustctl_encode_none)
709 ? "none"
710 : ((elem_type->u.integer.encoding == ustctl_encode_UTF8)
711 ? "UTF8"
712 : "ASCII"),
713 elem_type->u.integer.base,
714 elem_type->u.integer.reverse_byte_order ? bo_reverse : bo_native,
715 field->name,
716 field->type.u.sequence_nestable.length_name);
717 (*iter_field)++;
718 break;
719 }
d0b96690
DG
720 case ustctl_atype_string:
721 /* Default encoding is UTF8 */
da860cab
MD
722 ret = print_tabs(session, nesting);
723 if (ret) {
724 goto end;
725 }
d0b96690 726 ret = lttng_metadata_printf(session,
da860cab 727 "string%s _%s;\n",
0d32d1a9 728 field->type.u.string.encoding == ustctl_encode_ASCII ?
d0b96690
DG
729 " { encoding = ASCII; }" : "",
730 field->name);
da860cab
MD
731 (*iter_field)++;
732 break;
733 case ustctl_atype_variant:
0d32d1a9
MD
734 ret = _lttng_variant_statedump(session,
735 field->type.u.legacy.variant.nr_choices,
736 field->type.u.legacy.variant.tag_name,
737 0,
738 fields, nr_fields, iter_field, nesting);
739 if (ret) {
740 goto end;
741 }
742 break;
743 case ustctl_atype_variant_nestable:
744 ret = _lttng_variant_statedump(session,
745 field->type.u.variant_nestable.nr_choices,
746 field->type.u.variant_nestable.tag_name,
747 field->type.u.variant_nestable.alignment,
748 fields, nr_fields, iter_field, nesting);
da860cab
MD
749 if (ret) {
750 goto end;
751 }
752 break;
753 case ustctl_atype_struct:
0d32d1a9
MD
754 if (field->type.u.legacy._struct.nr_fields != 0) {
755 /* Currently only 0-length structures are supported. */
756 ret = -EINVAL;
757 goto end;
758 }
da860cab
MD
759 ret = print_tabs(session, nesting);
760 if (ret) {
761 goto end;
762 }
763 ret = lttng_metadata_printf(session,
764 "struct {} _%s;\n",
765 field->name);
766 (*iter_field)++;
d0b96690 767 break;
0d32d1a9
MD
768 case ustctl_atype_struct_nestable:
769 if (field->type.u.struct_nestable.nr_fields != 0) {
770 /* Currently only 0-length structures are supported. */
771 ret = -EINVAL;
772 goto end;
773 }
774 ret = print_tabs(session, nesting);
775 if (ret) {
776 goto end;
777 }
778 if (field->type.u.struct_nestable.alignment) {
779 ret = lttng_metadata_printf(session,
780 "struct {} align(%u) _%s;\n",
781 field->type.u.struct_nestable.alignment * CHAR_BIT,
782 field->name);
783 if (ret) {
784 goto end;
785 }
786 } else {
787 ret = lttng_metadata_printf(session,
788 "struct {} _%s;\n",
789 field->name);
790 }
791 (*iter_field)++;
792 break;
793 case ustctl_atype_enum_nestable:
794 {
795 const struct ustctl_field *container_field;
796 const struct ustctl_type *container_type;
797
798 (*iter_field)++;
799 if (*iter_field >= nr_fields) {
800 ret = -EOVERFLOW;
801 goto end;
802 }
803 container_field = &fields[*iter_field];
804 container_type = &container_field->type;
805
806 /* Only integers are supported as container types. */
807 if (container_type->atype != ustctl_atype_integer) {
808 ret = -EINVAL;
809 goto end;
810 }
811 ret = ust_metadata_enum_statedump(session,
812 field->type.u.enum_nestable.name,
813 field->type.u.enum_nestable.id,
814 &container_type->u.integer,
815 field->name, iter_field, nesting);
816 break;
817 }
d0b96690 818 default:
da860cab 819 ret = -EINVAL;
d0b96690 820 }
da860cab 821end:
d0b96690
DG
822 return ret;
823}
824
825static
826int _lttng_context_metadata_statedump(struct ust_registry_session *session,
827 size_t nr_ctx_fields,
828 struct ustctl_field *ctx)
829{
830 int ret = 0;
da860cab 831 size_t i = 0;
d0b96690
DG
832
833 if (!ctx)
834 return 0;
da860cab
MD
835 for (;;) {
836 if (i >= nr_ctx_fields) {
837 break;
838 }
839 ret = _lttng_field_statedump(session, ctx,
840 nr_ctx_fields, &i, 2);
841 if (ret) {
842 break;
843 }
d0b96690
DG
844 }
845 return ret;
846}
847
848static
849int _lttng_fields_metadata_statedump(struct ust_registry_session *session,
850 struct ust_registry_event *event)
851{
852 int ret = 0;
da860cab 853 size_t i = 0;
d0b96690 854
da860cab
MD
855 for (;;) {
856 if (i >= event->nr_fields) {
857 break;
858 }
859 ret = _lttng_field_statedump(session, event->fields,
860 event->nr_fields, &i, 2);
861 if (ret) {
862 break;
863 }
d0b96690
DG
864 }
865 return ret;
866}
867
868/*
869 * Should be called with session registry mutex held.
870 */
871int ust_metadata_event_statedump(struct ust_registry_session *session,
872 struct ust_registry_channel *chan,
873 struct ust_registry_event *event)
874{
875 int ret = 0;
876
877 /* Don't dump metadata events */
878 if (chan->chan_id == -1U)
879 return 0;
880
881 ret = lttng_metadata_printf(session,
882 "event {\n"
883 " name = \"%s\";\n"
884 " id = %u;\n"
885 " stream_id = %u;\n",
886 event->name,
887 event->id,
888 chan->chan_id);
0d32d1a9 889 if (ret) {
d0b96690 890 goto end;
0d32d1a9 891 }
d0b96690
DG
892
893 ret = lttng_metadata_printf(session,
894 " loglevel = %d;\n",
2106efa0 895 event->loglevel_value);
0d32d1a9 896 if (ret) {
d0b96690 897 goto end;
0d32d1a9 898 }
d0b96690
DG
899
900 if (event->model_emf_uri) {
901 ret = lttng_metadata_printf(session,
902 " model.emf.uri = \"%s\";\n",
903 event->model_emf_uri);
0d32d1a9 904 if (ret) {
d0b96690 905 goto end;
0d32d1a9 906 }
d0b96690
DG
907 }
908
d0b96690
DG
909 ret = lttng_metadata_printf(session,
910 " fields := struct {\n"
911 );
0d32d1a9 912 if (ret) {
d0b96690 913 goto end;
0d32d1a9 914 }
d0b96690
DG
915
916 ret = _lttng_fields_metadata_statedump(session, event);
0d32d1a9 917 if (ret) {
d0b96690 918 goto end;
0d32d1a9 919 }
d0b96690
DG
920
921 ret = lttng_metadata_printf(session,
922 " };\n"
923 "};\n\n");
0d32d1a9 924 if (ret) {
d0b96690 925 goto end;
0d32d1a9 926 }
7972aab2 927 event->metadata_dumped = 1;
d0b96690
DG
928
929end:
930 return ret;
931}
932
933/*
934 * Should be called with session registry mutex held.
935 */
936int ust_metadata_channel_statedump(struct ust_registry_session *session,
937 struct ust_registry_channel *chan)
938{
939 int ret = 0;
940
941 /* Don't dump metadata events */
942 if (chan->chan_id == -1U)
943 return 0;
944
945 if (!chan->header_type)
946 return -EINVAL;
947
948 ret = lttng_metadata_printf(session,
949 "stream {\n"
950 " id = %u;\n"
951 " event.header := %s;\n"
952 " packet.context := struct packet_context;\n",
953 chan->chan_id,
954 chan->header_type == USTCTL_CHANNEL_HEADER_COMPACT ?
955 "struct event_header_compact" :
956 "struct event_header_large");
0d32d1a9 957 if (ret) {
d0b96690 958 goto end;
0d32d1a9 959 }
d0b96690
DG
960
961 if (chan->ctx_fields) {
962 ret = lttng_metadata_printf(session,
963 " event.context := struct {\n");
0d32d1a9 964 if (ret) {
d0b96690 965 goto end;
0d32d1a9 966 }
d0b96690
DG
967 }
968 ret = _lttng_context_metadata_statedump(session,
969 chan->nr_ctx_fields,
970 chan->ctx_fields);
0d32d1a9 971 if (ret) {
d0b96690 972 goto end;
0d32d1a9 973 }
d0b96690
DG
974 if (chan->ctx_fields) {
975 ret = lttng_metadata_printf(session,
976 " };\n");
0d32d1a9 977 if (ret) {
d0b96690 978 goto end;
0d32d1a9 979 }
d0b96690
DG
980 }
981
982 ret = lttng_metadata_printf(session,
983 "};\n\n");
7972aab2
DG
984 /* Flag success of metadata dump. */
985 chan->metadata_dumped = 1;
d0b96690
DG
986
987end:
988 return ret;
989}
990
991static
992int _lttng_stream_packet_context_declare(struct ust_registry_session *session)
993{
994 return lttng_metadata_printf(session,
995 "struct packet_context {\n"
996 " uint64_clock_monotonic_t timestamp_begin;\n"
997 " uint64_clock_monotonic_t timestamp_end;\n"
998 " uint64_t content_size;\n"
999 " uint64_t packet_size;\n"
0793bcc6 1000 " uint64_t packet_seq_num;\n"
d0b96690
DG
1001 " unsigned long events_discarded;\n"
1002 " uint32_t cpu_id;\n"
1003 "};\n\n"
1004 );
1005}
1006
1007/*
1008 * Compact header:
1009 * id: range: 0 - 30.
1010 * id 31 is reserved to indicate an extended header.
1011 *
1012 * Large header:
1013 * id: range: 0 - 65534.
1014 * id 65535 is reserved to indicate an extended header.
1015 */
1016static
1017int _lttng_event_header_declare(struct ust_registry_session *session)
1018{
1019 return lttng_metadata_printf(session,
1020 "struct event_header_compact {\n"
1021 " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
1022 " variant <id> {\n"
1023 " struct {\n"
1024 " uint27_clock_monotonic_t timestamp;\n"
1025 " } compact;\n"
1026 " struct {\n"
1027 " uint32_t id;\n"
1028 " uint64_clock_monotonic_t timestamp;\n"
1029 " } extended;\n"
1030 " } v;\n"
1031 "} align(%u);\n"
1032 "\n"
1033 "struct event_header_large {\n"
1034 " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n"
1035 " variant <id> {\n"
1036 " struct {\n"
1037 " uint32_clock_monotonic_t timestamp;\n"
1038 " } compact;\n"
1039 " struct {\n"
1040 " uint32_t id;\n"
1041 " uint64_clock_monotonic_t timestamp;\n"
1042 " } extended;\n"
1043 " } v;\n"
1044 "} align(%u);\n\n",
1045 session->uint32_t_alignment,
1046 session->uint16_t_alignment
1047 );
1048}
1049
dc113ec7
MD
1050/*
1051 * The offset between monotonic and realtime clock can be negative if
1052 * the system sets the REALTIME clock to 0 after boot.
dc113ec7 1053 */
d0b96690 1054static
8c645bb0 1055int measure_single_clock_offset(struct offset_sample *sample)
d0b96690 1056{
dc113ec7 1057 uint64_t monotonic_avg, monotonic[2], measure_delta, realtime;
fc0bb9fa 1058 uint64_t tcf = trace_clock_freq();
d0b96690
DG
1059 struct timespec rts = { 0, 0 };
1060 int ret;
1061
1062 monotonic[0] = trace_clock_read64();
389fbf04 1063 ret = lttng_clock_gettime(CLOCK_REALTIME, &rts);
8c645bb0
MD
1064 if (ret < 0) {
1065 return ret;
1066 }
d0b96690 1067 monotonic[1] = trace_clock_read64();
8c645bb0
MD
1068 measure_delta = monotonic[1] - monotonic[0];
1069 if (measure_delta > sample->measure_delta) {
1070 /*
1071 * Discard value if it took longer to read than the best
1072 * sample so far.
1073 */
1074 return 0;
1075 }
dc113ec7 1076 monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
6e1b0543
MD
1077 realtime = (uint64_t) rts.tv_sec * tcf;
1078 if (tcf == NSEC_PER_SEC) {
1079 realtime += rts.tv_nsec;
1080 } else {
1081 realtime += (uint64_t) rts.tv_nsec * tcf / NSEC_PER_SEC;
fc0bb9fa 1082 }
c2636b57 1083 sample->offset = (int64_t) realtime - monotonic_avg;
8c645bb0
MD
1084 sample->measure_delta = measure_delta;
1085 return 0;
d0b96690
DG
1086}
1087
8c645bb0
MD
1088/*
1089 * Approximation of NTP time of day to clock monotonic correlation,
1090 * taken at start of trace. Keep the measurement that took the less time
1091 * to complete, thus removing imprecision caused by preemption.
c2636b57 1092 * May return a negative offset.
8c645bb0
MD
1093 */
1094static
c2636b57 1095int64_t measure_clock_offset(void)
8c645bb0
MD
1096{
1097 int i;
1098 struct offset_sample offset_best_sample = {
1099 .offset = 0,
1100 .measure_delta = UINT64_MAX,
1101 };
1102
1103 for (i = 0; i < NR_CLOCK_OFFSET_SAMPLES; i++) {
1104 if (measure_single_clock_offset(&offset_best_sample)) {
1105 return 0;
1106 }
1107 }
1108 return offset_best_sample.offset;
1109}
d0b96690 1110
8de88061
JR
1111static
1112int print_metadata_session_information(struct ust_registry_session *registry)
1113{
1114 int ret;
1115 struct ltt_session *session = NULL;
1116 char creation_datetime[ISO8601_STR_LEN];
1117
1118 rcu_read_lock();
1119 session = session_find_by_id(registry->tracing_id);
1120 if (!session) {
1121 ret = -1;
1122 goto error;
1123 }
1124
1125 /* Print the trace name */
1126 ret = lttng_metadata_printf(registry, " trace_name = \"");
1127 if (ret) {
1128 goto error;
1129 }
1130
1131 /*
1132 * This is necessary since the creation time is present in the session
1133 * name when it is generated.
1134 */
1135 if (session->has_auto_generated_name) {
1136 ret = print_escaped_ctf_string(registry, DEFAULT_SESSION_NAME);
1137 } else {
1138 ret = print_escaped_ctf_string(registry, session->name);
1139 }
1140 if (ret) {
1141 goto error;
1142 }
1143
1144 ret = lttng_metadata_printf(registry, "\";\n");
1145 if (ret) {
1146 goto error;
1147 }
1148
1149 /* Prepare creation time */
1150 ret = time_to_iso8601_str(session->creation_time, creation_datetime,
1151 sizeof(creation_datetime));
1152 if (ret) {
1153 goto error;
1154 }
1155
1156 /* Output the reste of the information */
1157 ret = lttng_metadata_printf(registry,
1158 " trace_creation_datetime = \"%s\";\n"
1159 " hostname = \"%s\";\n",
1160 creation_datetime, session->hostname);
1161 if (ret) {
1162 goto error;
1163 }
1164
1165error:
1166 if (session) {
1167 session_put(session);
1168 }
1169 rcu_read_unlock();
1170 return ret;
1171}
1172
1173static
1174int print_metadata_app_information(struct ust_registry_session *registry,
1175 struct ust_app *app)
1176{
1177 int ret;
1178 char datetime[ISO8601_STR_LEN];
1179
1180 if (!app) {
1181 ret = 0;
1182 goto end;
1183 }
1184
1185 ret = time_to_iso8601_str(
1186 app->registration_time, datetime, sizeof(datetime));
1187 if (ret) {
1188 goto end;
1189 }
1190
1191 ret = lttng_metadata_printf(registry,
1192 " tracer_patchlevel = %u;\n"
1193 " vpid = %d;\n"
1194 " procname = \"%s\";\n"
1195 " vpid_datetime = \"%s\";\n",
1196 app->version.patchlevel, (int) app->pid, app->name,
1197 datetime);
1198
1199end:
1200 return ret;
1201}
1202
d0b96690
DG
1203/*
1204 * Should be called with session registry mutex held.
1205 */
1206int ust_metadata_session_statedump(struct ust_registry_session *session,
af6142cf
MD
1207 struct ust_app *app,
1208 uint32_t major,
1209 uint32_t minor)
d0b96690 1210{
c70636a7
MJ
1211 char uuid_s[LTTNG_UUID_STR_LEN],
1212 clock_uuid_s[LTTNG_UUID_STR_LEN];
d0b96690 1213 int ret = 0;
d0b96690 1214
7972aab2 1215 assert(session);
7972aab2 1216
c8e0c5f5 1217 lttng_uuid_to_str(session->uuid, uuid_s);
d0b96690 1218
d7ba1388
MD
1219 /* For crash ABI */
1220 ret = lttng_metadata_printf(session,
1221 "/* CTF %u.%u */\n\n",
1222 CTF_SPEC_MAJOR,
1223 CTF_SPEC_MINOR);
1224 if (ret) {
1225 goto end;
1226 }
1227
d0b96690
DG
1228 ret = lttng_metadata_printf(session,
1229 "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n"
1230 "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n"
1231 "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n"
1232 "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n"
1233 "typealias integer { size = %u; align = %u; signed = false; } := unsigned long;\n"
1234 "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
1235 "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n"
1236 "\n"
1237 "trace {\n"
1238 " major = %u;\n"
1239 " minor = %u;\n"
1240 " uuid = \"%s\";\n"
1241 " byte_order = %s;\n"
1242 " packet.header := struct {\n"
1243 " uint32_t magic;\n"
1244 " uint8_t uuid[16];\n"
1245 " uint32_t stream_id;\n"
0793bcc6 1246 " uint64_t stream_instance_id;\n"
d0b96690
DG
1247 " };\n"
1248 "};\n\n",
1249 session->uint8_t_alignment,
1250 session->uint16_t_alignment,
1251 session->uint32_t_alignment,
1252 session->uint64_t_alignment,
1253 session->bits_per_long,
1254 session->long_alignment,
1255 CTF_SPEC_MAJOR,
1256 CTF_SPEC_MINOR,
1257 uuid_s,
1258 session->byte_order == BIG_ENDIAN ? "be" : "le"
1259 );
0d32d1a9 1260 if (ret) {
d0b96690 1261 goto end;
0d32d1a9 1262 }
d0b96690 1263
d0b96690
DG
1264 ret = lttng_metadata_printf(session,
1265 "env {\n"
d0b96690
DG
1266 " domain = \"ust\";\n"
1267 " tracer_name = \"lttng-ust\";\n"
1268 " tracer_major = %u;\n"
8de88061
JR
1269 " tracer_minor = %u;\n"
1270 " tracer_buffering_scheme = \"%s\";\n"
1271 " tracer_buffering_id = %u;\n"
1272 " architecture_bit_width = %u;\n",
af6142cf 1273 major,
8de88061
JR
1274 minor,
1275 app ? "pid" : "uid",
1276 app ? (int) app->pid : (int) session->tracing_uid,
1277 session->bits_per_long);
1278 if (ret) {
1279 goto end;
1280 }
1281
1282 ret = print_metadata_session_information(session);
1283 if (ret) {
d0b96690 1284 goto end;
8de88061 1285 }
d0b96690
DG
1286
1287 /*
1288 * If per-application registry, we can output extra information
1289 * about the application.
1290 */
8de88061
JR
1291 ret = print_metadata_app_information(session, app);
1292 if (ret) {
1293 goto end;
d0b96690
DG
1294 }
1295
1296 ret = lttng_metadata_printf(session,
1297 "};\n\n"
1298 );
0d32d1a9 1299 if (ret) {
d0b96690 1300 goto end;
0d32d1a9 1301 }
d0b96690
DG
1302
1303 ret = lttng_metadata_printf(session,
1304 "clock {\n"
fc0bb9fa
MD
1305 " name = \"%s\";\n",
1306 trace_clock_name()
d0b96690 1307 );
0d32d1a9 1308 if (ret) {
d0b96690 1309 goto end;
0d32d1a9 1310 }
d0b96690
DG
1311
1312 if (!trace_clock_uuid(clock_uuid_s)) {
1313 ret = lttng_metadata_printf(session,
1314 " uuid = \"%s\";\n",
1315 clock_uuid_s
1316 );
0d32d1a9 1317 if (ret) {
d0b96690 1318 goto end;
0d32d1a9 1319 }
d0b96690
DG
1320 }
1321
1322 ret = lttng_metadata_printf(session,
fc0bb9fa 1323 " description = \"%s\";\n"
d0b96690
DG
1324 " freq = %" PRIu64 "; /* Frequency, in Hz */\n"
1325 " /* clock value offset from Epoch is: offset * (1/freq) */\n"
c2636b57 1326 " offset = %" PRId64 ";\n"
d0b96690 1327 "};\n\n",
fc0bb9fa 1328 trace_clock_description(),
d0b96690
DG
1329 trace_clock_freq(),
1330 measure_clock_offset()
1331 );
0d32d1a9 1332 if (ret) {
d0b96690 1333 goto end;
0d32d1a9 1334 }
d0b96690
DG
1335
1336 ret = lttng_metadata_printf(session,
1337 "typealias integer {\n"
1338 " size = 27; align = 1; signed = false;\n"
fc0bb9fa 1339 " map = clock.%s.value;\n"
d0b96690
DG
1340 "} := uint27_clock_monotonic_t;\n"
1341 "\n"
1342 "typealias integer {\n"
1343 " size = 32; align = %u; signed = false;\n"
fc0bb9fa 1344 " map = clock.%s.value;\n"
d0b96690
DG
1345 "} := uint32_clock_monotonic_t;\n"
1346 "\n"
1347 "typealias integer {\n"
1348 " size = 64; align = %u; signed = false;\n"
fc0bb9fa 1349 " map = clock.%s.value;\n"
d0b96690 1350 "} := uint64_clock_monotonic_t;\n\n",
fc0bb9fa 1351 trace_clock_name(),
d0b96690 1352 session->uint32_t_alignment,
fc0bb9fa
MD
1353 trace_clock_name(),
1354 session->uint64_t_alignment,
1355 trace_clock_name()
d0b96690 1356 );
0d32d1a9 1357 if (ret) {
d0b96690 1358 goto end;
0d32d1a9 1359 }
d0b96690
DG
1360
1361 ret = _lttng_stream_packet_context_declare(session);
0d32d1a9 1362 if (ret) {
d0b96690 1363 goto end;
0d32d1a9 1364 }
d0b96690
DG
1365
1366 ret = _lttng_event_header_declare(session);
0d32d1a9 1367 if (ret) {
d0b96690 1368 goto end;
0d32d1a9 1369 }
d0b96690
DG
1370
1371end:
1372 return ret;
1373}
This page took 0.111102 seconds and 4 git commands to generate.