0ec0b94bb529a99b2af32833df0869d19d057ce3
[deliverable/lttng-modules.git] / src / ctf2.c
1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
2 *
3 * src/ctf2.c
4 *
5 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * Copyright (C) 2021 Francis Deslauriers <francis.deslauriers@efficios.com>
7 */
8
9 #include <linux/dmi.h>
10 #include <linux/ktime.h>
11 #include <linux/list.h>
12 #include <linux/math64.h>
13 #include <linux/slab.h>
14 #include <linux/timekeeping.h>
15 #include <linux/utsname.h>
16
17 #include <lttng/events.h>
18 #include <lttng/events-internal.h>
19 #include <lttng/uuid.h>
20
21 #include <wrapper/time.h>
22
23 #include "clock-utils.h"
24 #include "field-path-resolving.h"
25 #include "metadata-printer.h"
26
27 #if __BYTE_ORDER == __BIG_ENDIAN
28 #define NATIVE_BYTEORDER "\"big-endian\""
29 #define REVERSE_BYTEORDER "\"little-endian\""
30 #else
31 #define NATIVE_BYTEORDER "\"little-endian\""
32 #define REVERSE_BYTEORDER "\"big-endian\""
33 #endif
34
35 struct ctf2_enum_mapping_range {
36 struct list_head node;
37 struct lttng_kernel_enum_value start;
38 struct lttng_kernel_enum_value end;
39 };
40
41 struct ctf2_enum_mapping {
42 struct list_head node;
43 const char *name;
44 struct list_head ranges;
45 unsigned int nr_ranges;
46 };
47
48 struct ctf2_enum {
49 struct list_head mappings;
50 unsigned int nr_mappings;
51 };
52
53 static int
54 ctf2_metadata_write_field(struct lttng_kernel_session *session,
55 const struct lttng_kernel_event_field *field,
56 struct field_location_ctx *field_location_ctx);
57 static int
58 ctf2_metadata_write_field_class(struct lttng_kernel_session *session,
59 const struct lttng_kernel_type_common *type,
60 struct field_location_ctx *field_location_ctx);
61
62 static int
63 ctf2_metadata_write_record_separator(struct lttng_kernel_session *session)
64 {
65 return lttng_metadata_printf(session, "%c\n", 0x1E);
66 }
67
68 static int ctf2_metadata_write_uuid(struct lttng_kernel_session *session,
69 unsigned char *uuid)
70 {
71 unsigned int i, uuid_len = 16;
72 int ret;
73
74 ret = lttng_metadata_printf(session, "[");
75 if (ret)
76 goto end;
77
78 for (i = 0; i < uuid_len; i++) {
79 ret = lttng_metadata_printf(session, "%hhu", uuid[i]);
80 if (ret)
81 goto end;
82
83 if (i < uuid_len - 1) {
84 ret = lttng_metadata_printf(session, ",");
85 if (ret)
86 goto end;
87 }
88 }
89
90 ret = lttng_metadata_printf(session, "]");
91
92 end:
93 return ret;
94 }
95
96 static int
97 ctf2_metadata_write_preamble_fragment(struct lttng_kernel_session *session)
98 {
99 unsigned char *session_uuid = session->priv->uuid.b;
100 int ret;
101
102 ret = ctf2_metadata_write_record_separator(session);
103 if (ret)
104 goto error;
105
106 /* Write the preamble */
107 ret = lttng_metadata_printf(session, "{\n\"type\":\"preamble\",\n"
108 "\"version\":2,\n"
109 "\"uuid\":");
110 if (ret)
111 goto error;
112
113 ret = ctf2_metadata_write_uuid(session, session_uuid);
114 if (ret) {
115 printk(KERN_WARNING
116 "LTTng: CTF2: error producing metadata trace class UUID\n");
117 goto error;
118 }
119
120 ret = lttng_metadata_printf(session, "}\n");
121 error:
122 return ret;
123 }
124
125 static int
126 ctf2_metadata_write_clock_class_fragment(struct lttng_kernel_session *session)
127 {
128 unsigned char clock_uuid_str[37] = { 0 };
129 const char *clock_name, *clock_desc;
130 long long offset, offset_seconds;
131 unsigned long long freq;
132 int offset_cycles, ret;
133
134 ret = ctf2_metadata_write_record_separator(session);
135 if (ret)
136 goto end;
137
138 clock_name = trace_clock_name();
139 clock_desc = trace_clock_description();
140 freq = trace_clock_freq();
141 offset = trace_clock_measure_offset();
142 offset_seconds = div_s64_rem(offset, freq, &offset_cycles);
143
144 ret = lttng_metadata_printf(
145 session,
146 "{\n"
147 "\"type\":\"clock-class\",\n"
148 "\"name\":\"%s\",\n"
149 "\"description\" : \"%s\",\n"
150 "\"frequency\" : %llu,\n"
151 "\"offset\" : { \"seconds\": %llu, \"cycles\":%lu}\n",
152 clock_name, clock_desc, freq, offset_seconds, offset_cycles);
153 if (ret)
154 goto end;
155
156 if (!trace_clock_uuid(clock_uuid_str)) {
157 lttng_uuid clock_uuid;
158
159 ret = lttng_metadata_printf(session, ",\n\"uuid\": ");
160 if (ret)
161 goto end;
162
163 ret = lttng_uuid_from_str(clock_uuid_str, clock_uuid);
164 if (ret) {
165 printk(KERN_WARNING
166 "LTTng: CTF2: error creating UUID from string\n");
167 goto end;
168 }
169
170 ret = ctf2_metadata_write_uuid(session, clock_uuid);
171 if (ret)
172 goto end;
173
174 ret = lttng_metadata_printf(session, "}\n");
175 }
176
177 end:
178 return ret;
179 }
180
181 static int ctf2_metadata_write_packet_header_field_class(
182 struct lttng_kernel_session *session)
183 {
184 int ret;
185
186 ret = lttng_metadata_printf(
187 session,
188 "{"
189 " \"type\": \"structure\","
190 " \"member-classes\": ["
191 " {"
192 " \"name\": \"magic\","
193 " \"field-class\": {"
194 " \"type\": \"fixed-length-unsigned-integer\","
195 " \"alignment\": %u,"
196 " \"length\": 32,"
197 " \"byte-order\": " NATIVE_BYTEORDER ","
198 " \"preferred-display-base\": 16,"
199 " \"roles\": [\"packet-magic-number\"]"
200 " }"
201 " },"
202 " {"
203 " \"name\": \"uuid\","
204 " \"field-class\": {"
205 " \"type\": \"static-length-blob\","
206 " \"length\": 16,"
207 " \"roles\": [\"metadata-stream-uuid\"]"
208 " }"
209 " },"
210 " {"
211 " \"name\": \"stream_id\","
212 " \"field-class\": {"
213 " \"type\": \"fixed-length-unsigned-integer\","
214 " \"alignment\": %u,"
215 " \"length\": 32,"
216 " \"byte-order\": " NATIVE_BYTEORDER ","
217 " \"roles\": [\"data-stream-class-id\"]"
218 " }"
219 " },"
220 " {"
221 " \"name\": \"stream_instance_id\","
222 " \"field-class\": {"
223 " \"type\": \"fixed-length-unsigned-integer\","
224 " \"alignment\": %u,"
225 " \"length\": 64,"
226 " \"byte-order\": " NATIVE_BYTEORDER ","
227 " \"roles\": [\"data-stream-id\"]"
228 " }"
229 " }"
230 " ]"
231 "}",
232 lttng_alignof(uint32_t) * CHAR_BIT,
233 lttng_alignof(uint32_t) * CHAR_BIT,
234 lttng_alignof(uint64_t) * CHAR_BIT);
235
236 return ret;
237 }
238
239 static int ctf2_metadata_write_environment(struct lttng_kernel_session *session)
240 {
241 int ret;
242
243 ret = lttng_metadata_printf(
244 session,
245 "{\n"
246 " \"hostname\": \"%s\",\n"
247 " \"domain\": \"kernel\",\n"
248 " \"sysname\": \"%s\",\n"
249 " \"kernel_release\": \"%s\",\n"
250 " \"kernel_version\": \"%s\",\n"
251 " \"tracer_name\": \"lttng-modules\",\n"
252 " \"tracer_major\": %d,\n"
253 " \"tracer_minor\": %d,\n"
254 " \"tracer_patchlevel\": %d,\n"
255 " \"trace_buffering_scheme\": \"global\"\n"
256 "}\n",
257 current->nsproxy->uts_ns->name.nodename, utsname()->sysname,
258 utsname()->release, utsname()->version,
259 LTTNG_MODULES_MAJOR_VERSION, LTTNG_MODULES_MINOR_VERSION,
260 LTTNG_MODULES_PATCHLEVEL_VERSION);
261
262 return ret;
263 }
264
265 static int
266 ctf2_metadata_write_trace_class_fragment(struct lttng_kernel_session *session)
267 {
268 int ret;
269
270 ret = ctf2_metadata_write_record_separator(session);
271 if (ret)
272 goto end;
273
274 ret = lttng_metadata_printf(session, "{\n\"type\":\"trace-class\"");
275 if (ret)
276 goto end;
277
278 ret = lttng_metadata_printf(session, ",\n\"environment\":");
279 if (ret)
280 goto end;
281
282 ret = ctf2_metadata_write_environment(session);
283 if (ret)
284 goto end;
285
286 ret = lttng_metadata_printf(session, ",\n\"packet-header-field-class\":");
287 if (ret)
288 goto end;
289
290 ret = ctf2_metadata_write_packet_header_field_class(session);
291 if (ret) {
292 printk(KERN_WARNING
293 "LTTng: CTF2: error producing metadata trace class packet header field class\n");
294 goto end;
295 }
296
297 ret = lttng_metadata_printf(session, "}\n");
298 end:
299 return ret;
300 }
301
302 static int ctf2_metadata_write_packet_context_field_class(
303 struct lttng_kernel_session *session,
304 struct lttng_kernel_channel_buffer *chan)
305 {
306 int ret;
307 ret = lttng_metadata_printf(
308 session,
309 " {"
310 " \"type\": \"structure\","
311 " \"member-classes\": ["
312 " {"
313 " \"name\": \"timestamp_begin\","
314 " \"field-class\": {"
315 " \"type\": \"fixed-length-unsigned-integer\","
316 " \"alignment\": %u,"
317 " \"length\": 64,"
318 " \"byte-order\": " NATIVE_BYTEORDER ","
319 " \"roles\": [\"default-clock-timestamp\"]"
320 " }"
321 " },"
322 " {"
323 " \"name\": \"timestamp_end\","
324 " \"field-class\": {"
325 " \"type\": \"fixed-length-unsigned-integer\","
326 " \"alignment\": %u,"
327 " \"length\": 64,"
328 " \"byte-order\": " NATIVE_BYTEORDER ","
329 " \"roles\": [\"packet-end-default-clock-timestamp\"]"
330 " }"
331 " },"
332 " {"
333 " \"name\": \"content_size\","
334 " \"field-class\": {"
335 " \"type\": \"fixed-length-unsigned-integer\","
336 " \"alignment\": %u,"
337 " \"length\": 64,"
338 " \"byte-order\": " NATIVE_BYTEORDER ","
339 " \"roles\": [\"packet-content-length\"]"
340 " }"
341 " },"
342 " {"
343 " \"name\": \"packet_size\","
344 " \"field-class\": {"
345 " \"type\": \"fixed-length-unsigned-integer\","
346 " \"alignment\": %u,"
347 " \"length\": 64,"
348 " \"byte-order\": " NATIVE_BYTEORDER ","
349 " \"roles\": [\"packet-total-length\"]"
350 " }"
351 " },"
352 " {"
353 " \"name\": \"packet_seq_num\","
354 " \"field-class\": {"
355 " \"type\": \"fixed-length-unsigned-integer\","
356 " \"alignment\": %u,"
357 " \"length\": 64,"
358 " \"byte-order\": " NATIVE_BYTEORDER ","
359 " \"roles\": [\"packet-sequence-number\" ]"
360 " }"
361 " },"
362 " {"
363 " \"name\": \"events_discarded\","
364 " \"field-class\": {"
365 " \"type\": \"fixed-length-unsigned-integer\","
366 " \"alignment\": %u,"
367 " \"byte-order\": " NATIVE_BYTEORDER ","
368 " \"length\": %u,"
369 " \"roles\": [\"discarded-event-record-counter-snapshot\"]"
370 " }"
371 " },"
372 " {"
373 " \"name\": \"cpu_id\","
374 " \"field-class\": {"
375 " \"type\": \"fixed-length-unsigned-integer\","
376 " \"alignment\": 8,"
377 " \"byte-order\": " NATIVE_BYTEORDER ","
378 " \"length\": 32"
379 " }"
380 " }"
381 " ]"
382 "}",
383 lttng_alignof(uint64_t) * CHAR_BIT,
384 lttng_alignof(uint64_t) * CHAR_BIT,
385 lttng_alignof(uint64_t) * CHAR_BIT,
386 lttng_alignof(uint64_t) * CHAR_BIT,
387 lttng_alignof(uint64_t) * CHAR_BIT,
388 lttng_alignof(unsigned long) * CHAR_BIT,
389 sizeof(unsigned long) * CHAR_BIT);
390 return 0;
391 }
392
393 static int ctf2_metadata_write_common_context_field_class(
394 struct lttng_kernel_session *session, struct lttng_kernel_ctx *ctx)
395 {
396 struct field_location_ctx *field_location_ctx;
397 int ret = 0, i;
398
399 if (!ctx)
400 return 0;
401
402 ret = lttng_metadata_printf(session, "{\n"
403 "\"type\": \"structure\",\n"
404 "\"member-classes\": [");
405 if (ret)
406 goto end;
407
408 field_location_ctx = field_location_ctx_create();
409 if (!field_location_ctx) {
410 ret = -ENOMEM;
411 printk(KERN_WARNING
412 "LTTng: CTF2: error allocating field location context\n");
413 goto end;
414 }
415
416 ret = field_location_stack_push(field_location_ctx,
417 SCOPE_STACK_NODE_TYPE_SCOPE,
418 "event-record-common-context", NULL);
419 if (ret) {
420 printk(KERN_WARNING
421 "LTTng: CTF2: error pushing new scope on scope stack\n");
422 goto destroy_field_loc;
423 }
424
425 for (i = 0; i < ctx->nr_fields; i++) {
426 const struct lttng_kernel_ctx_field *iter_field =
427 &ctx->fields[i];
428
429 ret = ctf2_metadata_write_field(
430 session, iter_field->event_field, field_location_ctx);
431 if (ret)
432 goto destroy_field_loc;
433
434 ret = field_location_stack_push(field_location_ctx,
435 SCOPE_STACK_NODE_TYPE_FIELD,
436 iter_field->event_field->name,
437 iter_field->event_field);
438 if (ret) {
439 printk(KERN_WARNING
440 "LTTng: CTF2: error pushing new field on scope stack\n");
441 goto destroy_field_loc;
442 }
443
444 if (i < ctx->nr_fields - 1) {
445 ret = lttng_metadata_printf(session, ", ");
446 if (ret)
447 goto destroy_field_loc;
448 }
449 }
450
451 field_location_stack_pop_n_elem(field_location_ctx, ctx->nr_fields + 1);
452
453 ret = lttng_metadata_printf(session, "]\n}\n");
454
455 destroy_field_loc:
456 field_location_ctx_destroy(field_location_ctx);
457 end:
458 return ret;
459 }
460
461 static int ctf2_metadata_write_compact_event_header_field_class(
462 struct lttng_kernel_session *session)
463 {
464 int ret;
465 ret = lttng_metadata_printf(
466 session,
467 "{"
468 " \"type\": \"structure\","
469 " \"minimum-alignment\": 8,"
470 " \"member-classes\": ["
471 " {"
472 " \"name\": \"id\","
473 " \"field-class\": {"
474 " \"type\": \"fixed-length-unsigned-enumeration\","
475 " \"length\": 5,"
476 " \"byte-order\": " NATIVE_BYTEORDER ","
477 " \"mappings\": {"
478 " \"compact\": [[0,30]],"
479 " \"extended\": [[31,31]]"
480 " },"
481 " \"roles\": [\"event-record-class-id\"]"
482 " }"
483 " },"
484 " {"
485 " \"name\": \"v\","
486 " \"field-class\": {"
487 " \"type\": \"variant\","
488 " \"selector-field-location\": ["
489 " \"event-record-header\","
490 " \"id\""
491 " ],"
492 " \"options\": ["
493 " {"
494 " \"selector-field-ranges\": [[0, 30]],"
495 " \"field-class\": {"
496 " \"type\": \"structure\","
497 " \"member-classes\": ["
498 " {"
499 " \"name\": \"timestamp\","
500 " \"field-class\":{"
501 " \"type\": \"fixed-length-unsigned-integer\","
502 " \"byte-order\": " NATIVE_BYTEORDER ","
503 " \"length\": 27,"
504 " \"roles\": [\"default-clock-timestamp\"]"
505 " }"
506 " }"
507 " ]"
508 " }"
509 " },"
510 " {"
511 " \"selector-field-ranges\": [[31, 31]],"
512 " \"field-class\": {"
513 " \"type\": \"structure\","
514 " \"member-classes\": ["
515 " {"
516 " \"name\": \"id\","
517 " \"field-class\": {"
518 " \"type\": \"fixed-length-unsigned-integer\","
519 " \"length\": 32,"
520 " \"alignment\": %u,"
521 " \"byte-order\": " NATIVE_BYTEORDER ","
522 " \"roles\": [\"event-record-class-id\" ]"
523 " }"
524 " },"
525 " {"
526 " \"name\": \"timestamp\","
527 " \"field-class\": {"
528 " \"type\": \"fixed-length-unsigned-integer\","
529 " \"alignment\": %u,"
530 " \"length\": 64,"
531 " \"byte-order\": " NATIVE_BYTEORDER ","
532 " \"roles\": [\"default-clock-timestamp\"]"
533 " }"
534 " }"
535 " ]"
536 " }"
537 " }"
538 " ]"
539 " }"
540 " }"
541 " ]"
542 "}",
543 lttng_alignof(uint32_t) * CHAR_BIT,
544 lttng_alignof(uint64_t) * CHAR_BIT);
545 return ret;
546 }
547
548 static int ctf2_metadata_write_large_event_header_field_class(
549 struct lttng_kernel_session *session)
550 {
551 int ret;
552 ret = lttng_metadata_printf(
553 session,
554 " {"
555 " \"type\": \"structure\","
556 " \"minimum-alignment\": 8,"
557 " \"member-classes\": ["
558 " {"
559 " \"name\": \"id\","
560 " \"field-class\": {"
561 " \"type\": \"fixed-length-unsigned-enumeration\","
562 " \"length\": 16,"
563 " \"alignment\": %u,"
564 " \"byte-order\": " NATIVE_BYTEORDER ","
565 " \"mappings\": {"
566 " \"compact\": [[0,65534]],"
567 " \"extended\": [[65535,65535]]"
568 " },"
569 " \"roles\": [\"event-record-class-id\"]"
570 " }"
571 " },"
572 " {"
573 " \"name\": \"v\","
574 " \"field-class\": {"
575 " \"type\": \"variant\","
576 " \"selector-field-location\": ["
577 " \"event-record-header\","
578 " \"id\""
579 " ],"
580 " \"options\": ["
581 " {"
582 " \"selector-field-ranges\": [[0,65534]],"
583 " \"field-class\": {"
584 " \"type\": \"structure\","
585 " \"member-classes\": ["
586 " {"
587 " \"name\": \"timestamp\","
588 " \"field-class\": {"
589 " \"type\": \"fixed-length-unsigned-integer\","
590 " \"alignment\": %u,"
591 " \"byte-order\": " NATIVE_BYTEORDER ","
592 " \"length\": 32,"
593 " \"roles\": [\"default-clock-timestamp\"]"
594 " }"
595 " }"
596 " ]"
597 " }"
598 " },"
599 " {"
600 " \"selector-field-ranges\": [ [65525,65535] ],"
601 " \"field-class\": {"
602 " \"type\": \"structure\","
603 " \"member-classes\": ["
604 " {"
605 " \"name\": \"id\","
606 " \"field-class\": {"
607 " \"type\": \"fixed-length-unsigned-integer\","
608 " \"length\": 32,"
609 " \"alignment\": %u,"
610 " \"byte-order\": " NATIVE_BYTEORDER ","
611 " \"roles\": [\"event-record-class-id\" ]"
612 " }"
613 " },"
614 " {"
615 " \"name\": \"timestamp\","
616 " \"field-class\": {"
617 " \"type\": \"fixed-length-unsigned-integer\","
618 " \"length\": 64,"
619 " \"alignment\": %u,"
620 " \"byte-order\": " NATIVE_BYTEORDER ","
621 " \"roles\": [\"default-clock-timestamp\"]"
622 " }"
623 " }"
624 " ]"
625 " }"
626 " }"
627 " ]"
628 " }"
629 " }"
630 " ]"
631 "}",
632 lttng_alignof(uint16_t) * CHAR_BIT,
633 lttng_alignof(uint32_t) * CHAR_BIT,
634 lttng_alignof(uint32_t) * CHAR_BIT,
635 lttng_alignof(uint64_t) * CHAR_BIT);
636 return ret;
637 }
638
639 static int ctf2_metadata_write_integer_field_class(
640 struct lttng_kernel_session *session,
641 const struct lttng_kernel_type_integer *type)
642 {
643 char *enum_type_name, *byte_order;
644 int ret;
645
646 if (type->signedness) {
647 enum_type_name = "fixed-length-signed-integer";
648 } else {
649 enum_type_name = "fixed-length-unsigned-integer";
650 }
651
652 byte_order =
653 type->reverse_byte_order ? REVERSE_BYTEORDER : NATIVE_BYTEORDER;
654
655 ret = lttng_metadata_printf(session,
656 "{"
657 "\n\"type\": \"%s\","
658 "\n\"length\": %u,"
659 "\n\"byte-order\": %s",
660 enum_type_name, type->size, byte_order);
661 if (ret)
662 goto end;
663
664 if (type->alignment != 1) {
665 ret = lttng_metadata_printf(session, ",\n\"alignment\": %u",
666 type->alignment);
667 if (ret)
668 goto end;
669 }
670
671 if (type->base != 10) {
672 ret = lttng_metadata_printf(session,
673 ",\n\"preferred-display-base\": %u",
674 type->base);
675 if (ret)
676 goto end;
677 }
678
679 ret = lttng_metadata_printf(session, "\n}");
680 if (ret)
681 goto end;
682 end:
683 return ret;
684 }
685
686 static void
687 ctf2_enum_mapping_destroy(struct ctf2_enum_mapping *ctf2_enum_mapping)
688 {
689 struct ctf2_enum_mapping_range *range, *tmp;
690
691 if (!ctf2_enum_mapping) {
692 return;
693 }
694
695 list_for_each_entry_safe (range, tmp, &ctf2_enum_mapping->ranges,
696 node) {
697 kfree(range);
698 }
699
700 kfree(ctf2_enum_mapping->name);
701 kfree(ctf2_enum_mapping);
702 }
703
704 static void ctf2_enum_destroy(struct ctf2_enum *ctf2_enum)
705 {
706 struct ctf2_enum_mapping *mapping, *tmp;
707
708 if (!ctf2_enum) {
709 return;
710 }
711
712 list_for_each_entry_safe (mapping, tmp, &ctf2_enum->mappings, node) {
713 ctf2_enum_mapping_destroy(mapping);
714 }
715
716 kfree(ctf2_enum);
717 }
718
719 static struct ctf2_enum *
720 ctf2_enum_create_from_type_enum(const struct lttng_kernel_type_enum *cur_enum)
721 {
722 struct ctf2_enum *ctf2_enum;
723 const struct lttng_kernel_enum_desc *enum_desc;
724 unsigned int i, nr_entries;
725 struct ctf2_enum_mapping *mapping;
726 struct lttng_kernel_enum_value next_value = { .value = 0,
727 .signedness = false };
728
729 nr_entries = cur_enum->desc->nr_entries;
730 enum_desc = cur_enum->desc;
731
732 ctf2_enum = kzalloc(sizeof(*ctf2_enum), GFP_KERNEL);
733 if (!ctf2_enum)
734 goto end;
735
736 INIT_LIST_HEAD(&ctf2_enum->mappings);
737
738 for (i = 0; i < nr_entries; i++) {
739 const struct lttng_kernel_enum_entry *entry =
740 enum_desc->entries[i];
741 struct ctf2_enum_mapping_range *mapping_range;
742 bool found = false;
743
744 list_for_each_entry (mapping, &ctf2_enum->mappings, node) {
745 if (strcmp(mapping->name, entry->string) == 0) {
746 found = true;
747 break;
748 }
749 }
750
751 mapping_range = kzalloc(sizeof(*mapping_range), GFP_KERNEL);
752 if (!mapping_range)
753 goto destroy_ctf2_enum;
754
755 if (entry->options.is_auto) {
756 mapping_range->start.value = next_value.value;
757 mapping_range->start.signedness = next_value.signedness;
758 mapping_range->end.value = next_value.value;
759 mapping_range->end.signedness = next_value.signedness;
760
761 next_value.value++;
762 } else {
763 mapping_range->start.value = entry->start.value;
764 mapping_range->start.signedness =
765 entry->start.signedness;
766 mapping_range->end.value = entry->end.value;
767 mapping_range->end.signedness = entry->end.signedness;
768
769 next_value.value = entry->end.value + 1;
770 next_value.signedness = entry->end.signedness;
771 }
772
773 if (found) {
774 /*
775 * We already have a mapping with that name, add the
776 * new range to the range list.
777 */
778 list_add_tail(&mapping_range->node, &mapping->ranges);
779 } else {
780 /*
781 * Allocate the new mapping, add its range to the range
782 * list, and add the mapping to the mapping list
783 */
784 mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
785 if (!mapping) {
786 kfree(mapping_range);
787 goto destroy_ctf2_enum;
788 }
789
790 mapping->name = kstrdup(entry->string, GFP_KERNEL);
791
792 INIT_LIST_HEAD(&mapping->ranges);
793
794 list_add_tail(&mapping->node, &ctf2_enum->mappings);
795 ctf2_enum->nr_mappings++;
796
797 list_add_tail(&mapping_range->node, &mapping->ranges);
798 }
799
800 mapping->nr_ranges++;
801 }
802
803 goto end;
804
805 destroy_ctf2_enum:
806 ctf2_enum_destroy(ctf2_enum);
807 ctf2_enum = NULL;
808 end:
809 return ctf2_enum;
810 }
811
812 static int
813 ctf2_metadata_write_enum_mapping_ranges(struct lttng_kernel_session *session,
814 struct ctf2_enum_mapping *mapping)
815 {
816 unsigned int range_idx;
817 struct ctf2_enum_mapping_range *mapping_range;
818 int ret;
819
820 range_idx = 0;
821
822 list_for_each_entry (mapping_range, &mapping->ranges, node) {
823 if (mapping_range->start.signedness)
824 ret = lttng_metadata_printf(
825 session, "[%lld, ",
826 (long long)mapping_range->start.value);
827 else
828 ret = lttng_metadata_printf(session, "[%llu, ",
829 mapping_range->start.value);
830 if (ret)
831 goto end;
832
833 if (mapping_range->end.signedness)
834 ret = lttng_metadata_printf(
835 session, "%lld]",
836 (long long)mapping_range->end.value);
837 else
838 ret = lttng_metadata_printf(session, "%llu]",
839 mapping_range->end.value);
840 if (ret)
841 goto end;
842
843 if (range_idx < mapping->nr_ranges - 1) {
844 ret = lttng_metadata_printf(session, ",\n");
845 if (ret)
846 goto end;
847 }
848
849 range_idx++;
850 }
851
852 end:
853 return ret;
854 }
855
856 static int ctf2_metadata_write_enum_field_class(
857 struct lttng_kernel_session *session,
858 const struct lttng_kernel_type_enum *enum_type)
859 {
860 const struct lttng_kernel_enum_desc *enum_desc;
861 const struct lttng_kernel_type_common *container_type;
862 const struct lttng_kernel_type_integer *base_type;
863 struct ctf2_enum *ctf2_enum;
864 struct ctf2_enum_mapping *mapping;
865 unsigned int mapping_idx, nr_entries;
866 const char *byte_order;
867 char *enum_type_name;
868 int ret;
869
870 enum_desc = enum_type->desc;
871 container_type = enum_type->container_type;
872 nr_entries = enum_desc->nr_entries;
873
874 if (container_type->type != lttng_kernel_type_integer) {
875 ret = -EINVAL;
876 goto end;
877 }
878
879 base_type = lttng_kernel_get_type_integer(container_type);
880
881 if (base_type->signedness) {
882 enum_type_name = "fixed-length-signed-enumeration";
883 } else {
884 enum_type_name = "fixed-length-unsigned-enumeration";
885 }
886
887 byte_order = base_type->reverse_byte_order ? REVERSE_BYTEORDER :
888 NATIVE_BYTEORDER;
889
890 ret = lttng_metadata_printf(session,
891 "{"
892 " \"type\": \"%s\","
893 " \"length\": %u,"
894 " \"byte-order\": %s",
895 enum_type_name, base_type->size,
896 byte_order);
897 if (ret)
898 goto end;
899
900 if (base_type->alignment != 1) {
901 ret = lttng_metadata_printf(session, ", \"alignment\": %u",
902 base_type->alignment);
903 if (ret)
904 goto end;
905 }
906
907 if (base_type->base != 10) {
908 ret = lttng_metadata_printf(session,
909 ", \"preferred-display-base\": %u",
910 base_type->base);
911 if (ret)
912 goto end;
913 }
914
915 ret = lttng_metadata_printf(session, ", \"mappings\": {");
916 if (ret)
917 goto end;
918
919 ctf2_enum = ctf2_enum_create_from_type_enum(enum_type);
920 mapping_idx = 0;
921 list_for_each_entry (mapping, &ctf2_enum->mappings, node) {
922 ret = lttng_metadata_printf(session, " \"%s\": [",
923 mapping->name);
924 if (ret)
925 goto end;
926
927 ret = ctf2_metadata_write_enum_mapping_ranges(session, mapping);
928 if (ret)
929 goto end;
930
931 ret = lttng_metadata_printf(session, " ]");
932 if (ret)
933 goto end;
934
935 if (mapping_idx < ctf2_enum->nr_mappings - 1) {
936 ret = lttng_metadata_printf(session, ",\n");
937 if (ret)
938 goto end;
939 }
940
941 mapping_idx++;
942 }
943 ret = lttng_metadata_printf(session, "}}");
944
945 end:
946 ctf2_enum_destroy(ctf2_enum);
947 return ret;
948 }
949
950 static int ctf2_metadata_write_string_field_class(
951 struct lttng_kernel_session *session,
952 const struct lttng_kernel_type_string *type)
953 {
954 int ret = 0;
955
956 ret = lttng_metadata_printf(session,
957 "{\"type\": \"null-terminated-string\"}");
958 return ret;
959 }
960
961 static int ctf2_metadata_write_struct_field_class(
962 struct lttng_kernel_session *session,
963 const struct lttng_kernel_type_struct *type,
964 struct field_location_ctx *field_location_ctx)
965 {
966 unsigned int nr_fields;
967 int ret = 0;
968
969 ret = lttng_metadata_printf(session, "{\"type\": \"structure\"");
970 if (ret)
971 goto end;
972
973 if (type->alignment != 0 && type->alignment != 1) {
974 ret = lttng_metadata_printf(session,
975 ", \"minimum-alignment\": %u",
976 type->alignment);
977 if (ret)
978 goto end;
979 }
980
981 nr_fields = type->nr_fields;
982
983 if (nr_fields) {
984 unsigned int i;
985
986 ret = lttng_metadata_printf(session, ", \"member-classes\":[ ");
987
988 for (i = 0; i < nr_fields; i++) {
989 const struct lttng_kernel_event_field *iter_field;
990
991 iter_field = type->fields[i];
992
993 ret = ctf2_metadata_write_field(session, iter_field,
994 field_location_ctx);
995 if (ret)
996 goto end;
997
998 if (field_location_ctx) {
999 ret = field_location_stack_push(
1000 field_location_ctx,
1001 SCOPE_STACK_NODE_TYPE_FIELD,
1002 iter_field->name, iter_field);
1003 if (ret)
1004 goto end;
1005 }
1006
1007 if (i < nr_fields - 1) {
1008 ret = lttng_metadata_printf(session, ", ");
1009 if (ret)
1010 goto end;
1011 }
1012 }
1013
1014 /*
1015 * We are done visiting the struct field class. Remove all the
1016 * concrete fields of that scope.
1017 */
1018 if (field_location_ctx) {
1019 field_location_stack_pop_n_elem(field_location_ctx,
1020 nr_fields);
1021 }
1022
1023 ret = lttng_metadata_printf(session, "]");
1024 if (ret)
1025 goto end;
1026 }
1027 ret = lttng_metadata_printf(session, "}");
1028 end:
1029 return ret;
1030 }
1031
1032 static int ctf2_metadata_write_static_length_array_field_class(
1033 struct lttng_kernel_session *session,
1034 const struct lttng_kernel_type_array *type)
1035 {
1036 int ret;
1037 const struct lttng_kernel_type_common *elem_type = type->elem_type;
1038
1039 /*
1040 * If it's an array of integer encoded as characters, we translate it
1041 * as a static-length-string.
1042 */
1043 if (elem_type->type == lttng_kernel_type_integer &&
1044 (type->encoding == lttng_kernel_string_encoding_ASCII ||
1045 type->encoding == lttng_kernel_string_encoding_UTF8)) {
1046 ret = lttng_metadata_printf(
1047 session,
1048 "{"
1049 " \"type\": \"static-length-string\","
1050 " \"length\": %u }",
1051 type->length);
1052 } else {
1053 ret = lttng_metadata_printf(
1054 session,
1055 "{"
1056 " \"type\": \"static-length-array\","
1057 " \"length\": %u",
1058 type->length);
1059 if (ret)
1060 goto end;
1061
1062 if (type->alignment != 0 && type->alignment != 1) {
1063 ret = lttng_metadata_printf(
1064 session, ", \"minimum-alignment\": %u",
1065 type->alignment * CHAR_BIT);
1066 if (ret)
1067 goto end;
1068 }
1069
1070 ret = lttng_metadata_printf(session,
1071 ", \"element-field-class\":");
1072 if (ret)
1073 goto end;
1074
1075 /*
1076 * Nested compound types: Only array of integers, structures,
1077 * and variants are currently supported.
1078 */
1079 switch (elem_type->type) {
1080 case lttng_kernel_type_integer:
1081 case lttng_kernel_type_struct:
1082 case lttng_kernel_type_variant:
1083 ret = ctf2_metadata_write_field_class(session,
1084 elem_type, NULL);
1085 if (ret)
1086 goto end;
1087 break;
1088
1089 default:
1090 ret = -EINVAL;
1091 goto end;
1092 }
1093
1094 ret = lttng_metadata_printf(session, "}");
1095 }
1096
1097 end:
1098 return ret;
1099 }
1100
1101 static int print_field_location(struct lttng_kernel_session *session,
1102 struct field_path *field_path)
1103 {
1104 struct field_path_node *field_path_node;
1105 unsigned int entry_idx = 0;
1106 int ret;
1107
1108 ret = lttng_metadata_printf(session, "[");
1109 if (ret)
1110 goto end;
1111
1112 list_for_each_entry (field_path_node, &(field_path->path), node) {
1113 ret = lttng_metadata_printf(session, "\"%s\"",
1114 field_path_node->name);
1115 if (ret)
1116 goto end;
1117
1118 if (entry_idx < field_path->path_entry_count - 1) {
1119 ret = lttng_metadata_printf(session, ", ");
1120 if (ret)
1121 goto end;
1122 }
1123
1124 entry_idx++;
1125 }
1126 ret = lttng_metadata_printf(session, "]");
1127
1128 end:
1129 return ret;
1130 }
1131
1132 static int ctf2_metadata_write_dynamic_length_array_field_class(
1133 struct lttng_kernel_session *session,
1134 const struct lttng_kernel_type_sequence *type,
1135 struct field_location_ctx *field_location_ctx)
1136 {
1137 const struct lttng_kernel_type_common *elem_type;
1138 struct field_path *field_path;
1139 int ret;
1140
1141 field_path = field_path_resolve(field_location_ctx, type->length_name);
1142 if (!field_path) {
1143 ret = -1;
1144 goto end;
1145 }
1146
1147 /*
1148 * Nested compound types: Only array of integers, structures, and
1149 * variants are currently supported.
1150 */
1151 ret = lttng_metadata_printf(session,
1152 "{\n"
1153 " \"type\": \"dynamic-length-array\",\n"
1154 " \"length-field-location\": ");
1155 if (ret)
1156 goto end;
1157
1158 ret = print_field_location(session, field_path);
1159 if (ret)
1160 goto end;
1161
1162 if (type->alignment != 0 && type->alignment != 1) {
1163 ret = lttng_metadata_printf(session,
1164 ",\n\"minimum-alignment\": %u",
1165 type->alignment * CHAR_BIT);
1166 if (ret)
1167 goto end;
1168 }
1169
1170 ret = lttng_metadata_printf(session, ",\n\"element-field-class\":");
1171 if (ret)
1172 goto end;
1173
1174 elem_type = type->elem_type;
1175 switch (elem_type->type) {
1176 case lttng_kernel_type_integer:
1177 case lttng_kernel_type_struct:
1178 case lttng_kernel_type_variant:
1179 ret = ctf2_metadata_write_field_class(session, elem_type, NULL);
1180 if (ret)
1181 goto end;
1182 break;
1183
1184 default:
1185 return -EINVAL;
1186 }
1187
1188 ret = lttng_metadata_printf(session, "}\n");
1189 end:
1190 field_path_destroy(field_path);
1191 return ret;
1192 }
1193
1194 static int ctf2_metadata_write_variant_field_class(
1195 struct lttng_kernel_session *session,
1196 const struct lttng_kernel_type_variant *variant_type,
1197 struct field_location_ctx *field_location_ctx)
1198 {
1199 const char *tag_name;
1200 struct field_path *field_path = NULL;
1201 struct field_path_node *field_path_node;
1202 const struct lttng_kernel_type_enum *enum_type;
1203 struct ctf2_enum *ctf2_enum = NULL;
1204 unsigned int variant_choice_idx, variant_nr_choices, enum_nr_entries;
1205 int ret = 0;
1206
1207 tag_name = variant_type->tag_name;
1208
1209 field_path = field_path_resolve(field_location_ctx, tag_name);
1210 if (!field_path) {
1211 ret = -1;
1212 goto end;
1213 }
1214
1215 ret = lttng_metadata_printf(session, "{"
1216 "\n\"type\": \"variant\","
1217 "\n\"selector-field-location\":");
1218 if (ret)
1219 goto end;
1220
1221 ret = print_field_location(session, field_path);
1222 if (ret)
1223 goto end;
1224
1225 ret = lttng_metadata_printf(session, ",\n\"options\": [");
1226 if (ret)
1227 goto end;
1228
1229 field_path_node = list_last_entry(&(field_path->path),
1230 struct field_path_node, node);
1231 if (!field_path_node) {
1232 ret = -1;
1233 goto end;
1234 }
1235
1236 enum_type = lttng_kernel_get_type_enum(field_path_node->field->type);
1237 enum_nr_entries = enum_type->desc->nr_entries;
1238
1239 variant_nr_choices = variant_type->nr_choices;
1240
1241 if (enum_nr_entries != variant_nr_choices) {
1242 ret = -1;
1243 goto end;
1244 }
1245
1246 ctf2_enum = ctf2_enum_create_from_type_enum(enum_type);
1247
1248 /*
1249 * Iterate over all the options of the variant, find the mapping matching
1250 * the option name in the selector enum. Once found, print all ranges
1251 * and the field class of this option.
1252 */
1253 for (variant_choice_idx = 0; variant_choice_idx < variant_nr_choices;
1254 variant_choice_idx++) {
1255 const struct lttng_kernel_event_field *var_opt;
1256 struct ctf2_enum_mapping *mapping;
1257
1258 var_opt = variant_type->choices[variant_choice_idx];
1259
1260 list_for_each_entry (mapping, &ctf2_enum->mappings, node) {
1261 struct ctf2_enum_mapping_range *mapping_range;
1262 unsigned int range_idx;
1263
1264 /*
1265 * Omit the leading underscore when comparing enum
1266 * mappings.
1267 */
1268 if (strcmp(var_opt->name, &mapping->name[1]) != 0) {
1269 continue;
1270 }
1271
1272 ret = lttng_metadata_printf(
1273 session,
1274 "{"
1275 "\n\"name\": \"_%s\","
1276 "\n\"selector-field-ranges\": [",
1277 var_opt->name);
1278 if (ret)
1279 goto end;
1280
1281 range_idx = 0;
1282 list_for_each_entry (mapping_range, &mapping->ranges,
1283 node) {
1284 if (mapping_range->start.signedness)
1285 ret = lttng_metadata_printf(
1286 session, "[%lld, ",
1287 (long long)mapping_range->start
1288 .value);
1289 else
1290 ret = lttng_metadata_printf(
1291 session, "[%llu, ",
1292 mapping_range->start.value);
1293
1294 if (ret)
1295 goto end;
1296
1297 if (mapping_range->end.signedness)
1298 ret = lttng_metadata_printf(
1299 session, "%lld]",
1300 (long long)mapping_range->end
1301 .value);
1302 else
1303 ret = lttng_metadata_printf(
1304 session, "%llu]",
1305 mapping_range->end.value);
1306 if (ret)
1307 goto end;
1308
1309 if (range_idx < mapping->nr_ranges - 1) {
1310 ret = lttng_metadata_printf(session,
1311 ",\n");
1312 if (ret)
1313 goto end;
1314 }
1315
1316 range_idx++;
1317 }
1318
1319 ret = lttng_metadata_printf(session,
1320 " ], \"field-class\": ");
1321 if (ret)
1322 goto end;
1323
1324 ret = ctf2_metadata_write_field_class(
1325 session, var_opt->type, field_location_ctx);
1326 if (ret)
1327 goto end;
1328
1329 ret = lttng_metadata_printf(session, "}");
1330 if (ret)
1331 goto end;
1332
1333 /* Was it the last one ? */
1334 if (variant_choice_idx < variant_nr_choices - 1) {
1335 ret = lttng_metadata_printf(session, ",");
1336 if (ret)
1337 goto end;
1338 }
1339 }
1340 }
1341 ret = lttng_metadata_printf(session, "] }");
1342
1343 end:
1344 ctf2_enum_destroy(ctf2_enum);
1345 field_path_destroy(field_path);
1346 return ret;
1347 }
1348
1349 /*
1350 * Must be called with sessions_mutex held.
1351 */
1352 static int
1353 ctf2_metadata_write_field_class(struct lttng_kernel_session *session,
1354 const struct lttng_kernel_type_common *type,
1355 struct field_location_ctx *field_location_ctx)
1356 {
1357 int ret = 0;
1358
1359 switch (type->type) {
1360 case lttng_kernel_type_integer:
1361 ret = ctf2_metadata_write_integer_field_class(
1362 session, lttng_kernel_get_type_integer(type));
1363 break;
1364 case lttng_kernel_type_enum:
1365 ret = ctf2_metadata_write_enum_field_class(
1366 session, lttng_kernel_get_type_enum(type));
1367 break;
1368 case lttng_kernel_type_string:
1369 ret = ctf2_metadata_write_string_field_class(
1370 session, lttng_kernel_get_type_string(type));
1371 break;
1372 case lttng_kernel_type_struct:
1373 ret = ctf2_metadata_write_struct_field_class(
1374 session, lttng_kernel_get_type_struct(type),
1375 field_location_ctx);
1376 break;
1377 case lttng_kernel_type_array:
1378 ret = ctf2_metadata_write_static_length_array_field_class(
1379 session, lttng_kernel_get_type_array(type));
1380 break;
1381 case lttng_kernel_type_sequence:
1382 ret = ctf2_metadata_write_dynamic_length_array_field_class(
1383 session, lttng_kernel_get_type_sequence(type),
1384 field_location_ctx);
1385 break;
1386 case lttng_kernel_type_variant:
1387 ret = ctf2_metadata_write_variant_field_class(
1388 session, lttng_kernel_get_type_variant(type),
1389 field_location_ctx);
1390 break;
1391 default:
1392 WARN_ON_ONCE(1);
1393 return -EINVAL;
1394 }
1395
1396 return ret;
1397 }
1398
1399 /*
1400 * Must be called with sessions_mutex held.
1401 */
1402 static int
1403 ctf2_metadata_write_field(struct lttng_kernel_session *session,
1404 const struct lttng_kernel_event_field *field,
1405 struct field_location_ctx *field_location_ctx)
1406 {
1407 int ret = 0;
1408
1409 ret = lttng_metadata_printf(session,
1410 "{"
1411 "\n\"name\": \"%s\","
1412 "\n\"field-class\":",
1413 field->name);
1414 if (ret)
1415 goto end;
1416
1417 /*
1418 * Push a new scope only if we are entering a variant or struct field
1419 * class.
1420 */
1421 if (field_location_ctx &&
1422 (field->type->type == lttng_kernel_type_struct ||
1423 field->type->type == lttng_kernel_type_variant)) {
1424 ret = field_location_stack_push(field_location_ctx,
1425 SCOPE_STACK_NODE_TYPE_SCOPE,
1426 field->name, field);
1427 if (ret)
1428 goto end;
1429 }
1430
1431 ret = ctf2_metadata_write_field_class(session, field->type,
1432 field_location_ctx);
1433 if (ret) {
1434 printk(KERN_WARNING
1435 "LTTng: CTF2: error producing metadata for field class \"%s\"\n",
1436 field->name);
1437 goto end;
1438 }
1439
1440 if (field_location_ctx &&
1441 (field->type->type == lttng_kernel_type_struct ||
1442 field->type->type == lttng_kernel_type_variant)) {
1443 field_location_stack_pop_n_elem(field_location_ctx, 1);
1444 }
1445
1446 ret = lttng_metadata_printf(session, "\n}\n");
1447
1448 end:
1449 return ret;
1450 }
1451
1452 static int ctf2_metadata_write_payload_field_class(
1453 struct lttng_kernel_session *session,
1454 struct lttng_kernel_event_recorder *event_recorder)
1455 {
1456 const struct lttng_kernel_event_desc *desc =
1457 event_recorder->priv->parent.desc;
1458 struct field_location_ctx *field_location_ctx;
1459 unsigned int i;
1460 int ret = 0;
1461
1462 ret = lttng_metadata_printf(session, "{"
1463 "\n\"type\": \"structure\","
1464 "\n\"member-classes\": [");
1465 if (ret)
1466 goto end;
1467
1468 field_location_ctx = field_location_ctx_create();
1469 if (!field_location_ctx) {
1470 ret = -ENOMEM;
1471 printk(KERN_WARNING
1472 "LTTng: CTF2: error allocating field location context\n");
1473 goto end;
1474 }
1475
1476 ret = field_location_stack_push(field_location_ctx,
1477 SCOPE_STACK_NODE_TYPE_SCOPE,
1478 "event-record-payload", NULL);
1479 if (ret)
1480 goto destroy_field_loc;
1481
1482 for (i = 0; i < desc->tp_class->nr_fields; i++) {
1483 const struct lttng_kernel_event_field *field =
1484 desc->tp_class->fields[i];
1485
1486 ret = ctf2_metadata_write_field(session, field,
1487 field_location_ctx);
1488 if (ret)
1489 goto destroy_field_loc;
1490
1491 ret = field_location_stack_push(field_location_ctx,
1492 SCOPE_STACK_NODE_TYPE_FIELD,
1493 field->name, field);
1494 if (ret)
1495 goto destroy_field_loc;
1496
1497 if (i < desc->tp_class->nr_fields - 1) {
1498 ret = lttng_metadata_printf(session, ", ");
1499 if (ret)
1500 goto destroy_field_loc;
1501 }
1502 }
1503
1504 field_location_stack_pop_n_elem(field_location_ctx,
1505 desc->tp_class->nr_fields + 1);
1506
1507 ret = lttng_metadata_printf(session, "]\n}\n");
1508
1509 destroy_field_loc:
1510 field_location_ctx_destroy(field_location_ctx);
1511 end:
1512 return ret;
1513 }
1514
1515 int ctf2_metadata_write_event_record_class_fragment(
1516 struct lttng_kernel_event_common *event)
1517 {
1518 struct lttng_kernel_event_recorder *event_recorder;
1519 struct lttng_kernel_channel_buffer *chan;
1520 struct lttng_kernel_session *session;
1521 unsigned int nr_fields;
1522 int ret = 0;
1523
1524 if (event->type != LTTNG_KERNEL_EVENT_TYPE_RECORDER)
1525 return 0;
1526
1527 event_recorder =
1528 container_of(event, struct lttng_kernel_event_recorder, parent);
1529 chan = event_recorder->chan;
1530 session = chan->parent.session;
1531
1532 if (event_recorder->priv->metadata_dumped ||
1533 !LTTNG_READ_ONCE(session->active))
1534 return 0;
1535
1536 if (chan->priv->channel_type == METADATA_CHANNEL)
1537 return 0;
1538
1539 lttng_metadata_begin(session);
1540
1541 ret = ctf2_metadata_write_record_separator(session);
1542 if (ret)
1543 goto end;
1544
1545 ret = lttng_metadata_printf(
1546 session,
1547 "{"
1548 "\n\"type\": \"event-record-class\","
1549 "\n\"id\": %u,"
1550 "\n\"name\": \"%s\","
1551 "\n\"data-stream-class-id\":%u",
1552 event_recorder->priv->id,
1553 event_recorder->priv->parent.desc->event_name,
1554 event_recorder->chan->priv->id);
1555 if (ret)
1556 goto end;
1557
1558 nr_fields = event_recorder->priv->parent.desc->tp_class->nr_fields;
1559 if (nr_fields) {
1560 ret = lttng_metadata_printf(session,
1561 ",\n\"payload-field-class\":");
1562 if (ret)
1563 goto end;
1564
1565 ret = ctf2_metadata_write_payload_field_class(session,
1566 event_recorder);
1567 if (ret) {
1568 printk(KERN_WARNING
1569 "LTTng: CTF2: error producing metadata event record payload field class\n");
1570 goto end;
1571 }
1572 }
1573
1574 ret = lttng_metadata_printf(session, "\n}\n");
1575 if (ret)
1576 goto end;
1577
1578 event_recorder->priv->metadata_dumped = 1;
1579
1580 end:
1581 lttng_metadata_end(session);
1582 return ret;
1583 }
1584
1585 static int ctf2_metadata_write_data_stream_class_fragment(
1586 struct lttng_kernel_session *session,
1587 struct lttng_kernel_channel_buffer *chan)
1588 {
1589 int ret;
1590
1591 if (chan->priv->metadata_dumped || !LTTNG_READ_ONCE(session->active))
1592 return 0;
1593
1594 if (chan->priv->channel_type == METADATA_CHANNEL)
1595 return 0;
1596
1597 lttng_metadata_begin(session);
1598
1599 ret = ctf2_metadata_write_record_separator(session);
1600 if (ret)
1601 goto end;
1602
1603 ret = lttng_metadata_printf(session,
1604 "{"
1605 "\n\"type\":\"data-stream-class\","
1606 "\n\"id\": %u,"
1607 "\n\"default-clock-class-name\": \"%s\","
1608 "\n\"packet-context-field-class\":",
1609 chan->priv->id, trace_clock_name());
1610 if (ret)
1611 goto end;
1612
1613 ret = ctf2_metadata_write_packet_context_field_class(session, chan);
1614 if (ret) {
1615 printk(KERN_WARNING
1616 "LTTng: CTF2: error producing metadata stream class packet context field class\n");
1617 goto end;
1618 }
1619
1620 ret = lttng_metadata_printf(session,
1621 ",\n\"event-record-header-field-class\":");
1622 if (ret)
1623 goto end;
1624
1625 if (chan->priv->header_type == 1) {
1626 ret = ctf2_metadata_write_compact_event_header_field_class(
1627 session);
1628 if (ret) {
1629 printk(KERN_WARNING
1630 "LTTng: CTF2: error producing metadata stream class compact event header field class\n");
1631 goto end;
1632 }
1633 } else {
1634 ret = ctf2_metadata_write_large_event_header_field_class(
1635 session);
1636 if (ret) {
1637 printk(KERN_WARNING
1638 "LTTng: CTF2: error producing metadata stream class large event header field class\n");
1639 goto end;
1640 }
1641 }
1642
1643 if (chan->priv->ctx) {
1644 ret = lttng_metadata_printf(
1645 session,
1646 ",\n\"event-record-common-context-field-class\":\n");
1647 if (ret)
1648 goto end;
1649
1650 ret = ctf2_metadata_write_common_context_field_class(
1651 session, chan->priv->ctx);
1652 if (ret) {
1653 printk(KERN_WARNING
1654 "LTTng: CTF2: error producing metadata stream class common context field class\n");
1655 goto end;
1656 }
1657 }
1658
1659 ret = lttng_metadata_printf(session, "\n}\n");
1660
1661 chan->priv->metadata_dumped = 1;
1662
1663 end:
1664 lttng_metadata_end(session);
1665 return ret;
1666 }
1667
1668 int ctf2_metadata_write(struct lttng_kernel_session *session)
1669 {
1670 struct lttng_kernel_channel_buffer_private *chan_priv;
1671 struct lttng_kernel_event_recorder_private *event_recorder_priv;
1672 int ret;
1673
1674 if (!LTTNG_READ_ONCE(session->active))
1675 return 0;
1676
1677 lttng_metadata_begin(session);
1678
1679 if (session->priv->metadata_dumped)
1680 goto skip_session;
1681
1682 ret = ctf2_metadata_write_preamble_fragment(session);
1683 if (ret) {
1684 printk(KERN_WARNING
1685 "LTTng: CTF2: error producing metadata preamble fragment\n");
1686 goto end;
1687 }
1688
1689 ret = ctf2_metadata_write_trace_class_fragment(session);
1690 if (ret) {
1691 printk(KERN_WARNING
1692 "LTTng: CTF2: error producing metadata trace class fragment\n");
1693 goto end;
1694 }
1695
1696 ret = ctf2_metadata_write_clock_class_fragment(session);
1697 if (ret) {
1698 printk(KERN_WARNING
1699 "LTTng: CTF2: error producing metadata clock class fragment\n");
1700 goto end;
1701 }
1702
1703 skip_session:
1704 list_for_each_entry (chan_priv, &session->priv->chan, node) {
1705 ret = ctf2_metadata_write_data_stream_class_fragment(
1706 session, chan_priv->pub);
1707 if (ret) {
1708 printk(KERN_WARNING
1709 "LTTng: CTF2: error producing metadata stream class fragment\n");
1710 goto end;
1711 }
1712 }
1713 list_for_each_entry (event_recorder_priv, &session->priv->events,
1714 parent.node) {
1715 ret = ctf2_metadata_write_event_record_class_fragment(
1716 &event_recorder_priv->pub->parent);
1717 if (ret) {
1718 printk(KERN_WARNING
1719 "LTTng: CTF2: error producing metadata event class fragment\n");
1720 goto end;
1721 }
1722 }
1723 session->priv->metadata_dumped = 1;
1724
1725 end:
1726 lttng_metadata_end(session);
1727 return ret;
1728 }
This page took 0.064075 seconds and 4 git commands to generate.