1
2
3
4
5
6
7
8
9
10#include <linux/compiler.h>
11#include <babeltrace/ctf-writer/writer.h>
12#include <babeltrace/ctf-writer/clock.h>
13#include <babeltrace/ctf-writer/stream.h>
14#include <babeltrace/ctf-writer/event.h>
15#include <babeltrace/ctf-writer/event-types.h>
16#include <babeltrace/ctf-writer/event-fields.h>
17#include <babeltrace/ctf/events.h>
18#include <traceevent/event-parse.h>
19#include "asm/bug.h"
20#include "data-convert-bt.h"
21#include "session.h"
22#include "util.h"
23#include "debug.h"
24#include "tool.h"
25#include "evlist.h"
26#include "evsel.h"
27#include "machine.h"
28
29#define pr_N(n, fmt, ...) \
30 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
31
32#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
33#define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
34
35#define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
36
37struct evsel_priv {
38 struct bt_ctf_event_class *event_class;
39};
40
41struct ctf_writer {
42
43 struct bt_ctf_writer *writer;
44 struct bt_ctf_stream *stream;
45 struct bt_ctf_stream_class *stream_class;
46 struct bt_ctf_clock *clock;
47
48
49 union {
50 struct {
51 struct bt_ctf_field_type *s64;
52 struct bt_ctf_field_type *u64;
53 struct bt_ctf_field_type *s32;
54 struct bt_ctf_field_type *u32;
55 struct bt_ctf_field_type *string;
56 struct bt_ctf_field_type *u64_hex;
57 };
58 struct bt_ctf_field_type *array[6];
59 } data;
60};
61
62struct convert {
63 struct perf_tool tool;
64 struct ctf_writer writer;
65
66 u64 events_size;
67 u64 events_count;
68};
69
70static int value_set(struct bt_ctf_field_type *type,
71 struct bt_ctf_event *event,
72 const char *name, u64 val)
73{
74 struct bt_ctf_field *field;
75 bool sign = bt_ctf_field_type_integer_get_signed(type);
76 int ret;
77
78 field = bt_ctf_field_create(type);
79 if (!field) {
80 pr_err("failed to create a field %s\n", name);
81 return -1;
82 }
83
84 if (sign) {
85 ret = bt_ctf_field_signed_integer_set_value(field, val);
86 if (ret) {
87 pr_err("failed to set field value %s\n", name);
88 goto err;
89 }
90 } else {
91 ret = bt_ctf_field_unsigned_integer_set_value(field, val);
92 if (ret) {
93 pr_err("failed to set field value %s\n", name);
94 goto err;
95 }
96 }
97
98 ret = bt_ctf_event_set_payload(event, name, field);
99 if (ret) {
100 pr_err("failed to set payload %s\n", name);
101 goto err;
102 }
103
104 pr2(" SET [%s = %" PRIu64 "]\n", name, val);
105
106err:
107 bt_ctf_field_put(field);
108 return ret;
109}
110
111#define __FUNC_VALUE_SET(_name, _val_type) \
112static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \
113 struct bt_ctf_event *event, \
114 const char *name, \
115 _val_type val) \
116{ \
117 struct bt_ctf_field_type *type = cw->data._name; \
118 return value_set(type, event, name, (u64) val); \
119}
120
121#define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
122
123FUNC_VALUE_SET(s32)
124FUNC_VALUE_SET(u32)
125FUNC_VALUE_SET(s64)
126FUNC_VALUE_SET(u64)
127__FUNC_VALUE_SET(u64_hex, u64)
128
129static struct bt_ctf_field_type*
130get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
131{
132 unsigned long flags = field->flags;
133
134 if (flags & FIELD_IS_STRING)
135 return cw->data.string;
136
137 if (!(flags & FIELD_IS_SIGNED)) {
138
139 if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
140 return cw->data.u64_hex;
141 }
142
143 if (flags & FIELD_IS_SIGNED) {
144 if (field->size == 8)
145 return cw->data.s64;
146 else
147 return cw->data.s32;
148 }
149
150 if (field->size == 8)
151 return cw->data.u64;
152 else
153 return cw->data.u32;
154}
155
156static int add_tracepoint_field_value(struct ctf_writer *cw,
157 struct bt_ctf_event_class *event_class,
158 struct bt_ctf_event *event,
159 struct perf_sample *sample,
160 struct format_field *fmtf)
161{
162 struct bt_ctf_field_type *type;
163 struct bt_ctf_field *array_field;
164 struct bt_ctf_field *field;
165 const char *name = fmtf->name;
166 void *data = sample->raw_data;
167 unsigned long long value_int;
168 unsigned long flags = fmtf->flags;
169 unsigned int n_items;
170 unsigned int i;
171 unsigned int offset;
172 unsigned int len;
173 int ret;
174
175 offset = fmtf->offset;
176 len = fmtf->size;
177 if (flags & FIELD_IS_STRING)
178 flags &= ~FIELD_IS_ARRAY;
179
180 if (flags & FIELD_IS_DYNAMIC) {
181 unsigned long long tmp_val;
182
183 tmp_val = pevent_read_number(fmtf->event->pevent,
184 data + offset, len);
185 offset = tmp_val;
186 len = offset >> 16;
187 offset &= 0xffff;
188 }
189
190 if (flags & FIELD_IS_ARRAY) {
191
192 type = bt_ctf_event_class_get_field_by_name(
193 event_class, name);
194 array_field = bt_ctf_field_create(type);
195 bt_ctf_field_type_put(type);
196 if (!array_field) {
197 pr_err("Failed to create array type %s\n", name);
198 return -1;
199 }
200
201 len = fmtf->size / fmtf->arraylen;
202 n_items = fmtf->arraylen;
203 } else {
204 n_items = 1;
205 array_field = NULL;
206 }
207
208 type = get_tracepoint_field_type(cw, fmtf);
209
210 for (i = 0; i < n_items; i++) {
211 if (!(flags & FIELD_IS_STRING))
212 value_int = pevent_read_number(
213 fmtf->event->pevent,
214 data + offset + i * len, len);
215
216 if (flags & FIELD_IS_ARRAY)
217 field = bt_ctf_field_array_get_field(array_field, i);
218 else
219 field = bt_ctf_field_create(type);
220
221 if (!field) {
222 pr_err("failed to create a field %s\n", name);
223 return -1;
224 }
225
226 if (flags & FIELD_IS_STRING)
227 ret = bt_ctf_field_string_set_value(field,
228 data + offset + i * len);
229 else if (!(flags & FIELD_IS_SIGNED))
230 ret = bt_ctf_field_unsigned_integer_set_value(
231 field, value_int);
232 else
233 ret = bt_ctf_field_signed_integer_set_value(
234 field, value_int);
235 if (ret) {
236 pr_err("failed to set file value %s\n", name);
237 goto err_put_field;
238 }
239 if (!(flags & FIELD_IS_ARRAY)) {
240 ret = bt_ctf_event_set_payload(event, name, field);
241 if (ret) {
242 pr_err("failed to set payload %s\n", name);
243 goto err_put_field;
244 }
245 }
246 bt_ctf_field_put(field);
247 }
248 if (flags & FIELD_IS_ARRAY) {
249 ret = bt_ctf_event_set_payload(event, name, array_field);
250 if (ret) {
251 pr_err("Failed add payload array %s\n", name);
252 return -1;
253 }
254 bt_ctf_field_put(array_field);
255 }
256 return 0;
257
258err_put_field:
259 bt_ctf_field_put(field);
260 return -1;
261}
262
263static int add_tracepoint_fields_values(struct ctf_writer *cw,
264 struct bt_ctf_event_class *event_class,
265 struct bt_ctf_event *event,
266 struct format_field *fields,
267 struct perf_sample *sample)
268{
269 struct format_field *field;
270 int ret;
271
272 for (field = fields; field; field = field->next) {
273 ret = add_tracepoint_field_value(cw, event_class, event, sample,
274 field);
275 if (ret)
276 return -1;
277 }
278 return 0;
279}
280
281static int add_tracepoint_values(struct ctf_writer *cw,
282 struct bt_ctf_event_class *event_class,
283 struct bt_ctf_event *event,
284 struct perf_evsel *evsel,
285 struct perf_sample *sample)
286{
287 struct format_field *common_fields = evsel->tp_format->format.common_fields;
288 struct format_field *fields = evsel->tp_format->format.fields;
289 int ret;
290
291 ret = add_tracepoint_fields_values(cw, event_class, event,
292 common_fields, sample);
293 if (!ret)
294 ret = add_tracepoint_fields_values(cw, event_class, event,
295 fields, sample);
296
297 return ret;
298}
299
300static int add_generic_values(struct ctf_writer *cw,
301 struct bt_ctf_event *event,
302 struct perf_evsel *evsel,
303 struct perf_sample *sample)
304{
305 u64 type = evsel->attr.sample_type;
306 int ret;
307
308
309
310
311
312
313
314
315
316
317
318
319
320 if (type & PERF_SAMPLE_IP) {
321 ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
322 if (ret)
323 return -1;
324 }
325
326 if (type & PERF_SAMPLE_TID) {
327 ret = value_set_s32(cw, event, "perf_tid", sample->tid);
328 if (ret)
329 return -1;
330
331 ret = value_set_s32(cw, event, "perf_pid", sample->pid);
332 if (ret)
333 return -1;
334 }
335
336 if ((type & PERF_SAMPLE_ID) ||
337 (type & PERF_SAMPLE_IDENTIFIER)) {
338 ret = value_set_u64(cw, event, "perf_id", sample->id);
339 if (ret)
340 return -1;
341 }
342
343 if (type & PERF_SAMPLE_STREAM_ID) {
344 ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
345 if (ret)
346 return -1;
347 }
348
349 if (type & PERF_SAMPLE_CPU) {
350 ret = value_set_u32(cw, event, "perf_cpu", sample->cpu);
351 if (ret)
352 return -1;
353 }
354
355 if (type & PERF_SAMPLE_PERIOD) {
356 ret = value_set_u64(cw, event, "perf_period", sample->period);
357 if (ret)
358 return -1;
359 }
360
361 if (type & PERF_SAMPLE_WEIGHT) {
362 ret = value_set_u64(cw, event, "perf_weight", sample->weight);
363 if (ret)
364 return -1;
365 }
366
367 if (type & PERF_SAMPLE_DATA_SRC) {
368 ret = value_set_u64(cw, event, "perf_data_src",
369 sample->data_src);
370 if (ret)
371 return -1;
372 }
373
374 if (type & PERF_SAMPLE_TRANSACTION) {
375 ret = value_set_u64(cw, event, "perf_transaction",
376 sample->transaction);
377 if (ret)
378 return -1;
379 }
380
381 return 0;
382}
383
384static int process_sample_event(struct perf_tool *tool,
385 union perf_event *_event __maybe_unused,
386 struct perf_sample *sample,
387 struct perf_evsel *evsel,
388 struct machine *machine __maybe_unused)
389{
390 struct convert *c = container_of(tool, struct convert, tool);
391 struct evsel_priv *priv = evsel->priv;
392 struct ctf_writer *cw = &c->writer;
393 struct bt_ctf_event_class *event_class;
394 struct bt_ctf_event *event;
395 int ret;
396
397 if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
398 return 0;
399
400 event_class = priv->event_class;
401
402
403 c->events_count++;
404 c->events_size += _event->header.size;
405
406 pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
407
408 event = bt_ctf_event_create(event_class);
409 if (!event) {
410 pr_err("Failed to create an CTF event\n");
411 return -1;
412 }
413
414 bt_ctf_clock_set_time(cw->clock, sample->time);
415
416 ret = add_generic_values(cw, event, evsel, sample);
417 if (ret)
418 return -1;
419
420 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
421 ret = add_tracepoint_values(cw, event_class, event,
422 evsel, sample);
423 if (ret)
424 return -1;
425 }
426
427 bt_ctf_stream_append_event(cw->stream, event);
428 bt_ctf_event_put(event);
429 return 0;
430}
431
432static int add_tracepoint_fields_types(struct ctf_writer *cw,
433 struct format_field *fields,
434 struct bt_ctf_event_class *event_class)
435{
436 struct format_field *field;
437 int ret;
438
439 for (field = fields; field; field = field->next) {
440 struct bt_ctf_field_type *type;
441 unsigned long flags = field->flags;
442
443 pr2(" field '%s'\n", field->name);
444
445 type = get_tracepoint_field_type(cw, field);
446 if (!type)
447 return -1;
448
449
450
451
452
453
454 if (flags & FIELD_IS_STRING)
455 flags &= ~FIELD_IS_ARRAY;
456
457 if (flags & FIELD_IS_ARRAY)
458 type = bt_ctf_field_type_array_create(type, field->arraylen);
459
460 ret = bt_ctf_event_class_add_field(event_class, type,
461 field->name);
462
463 if (flags & FIELD_IS_ARRAY)
464 bt_ctf_field_type_put(type);
465
466 if (ret) {
467 pr_err("Failed to add field '%s\n", field->name);
468 return -1;
469 }
470 }
471
472 return 0;
473}
474
475static int add_tracepoint_types(struct ctf_writer *cw,
476 struct perf_evsel *evsel,
477 struct bt_ctf_event_class *class)
478{
479 struct format_field *common_fields = evsel->tp_format->format.common_fields;
480 struct format_field *fields = evsel->tp_format->format.fields;
481 int ret;
482
483 ret = add_tracepoint_fields_types(cw, common_fields, class);
484 if (!ret)
485 ret = add_tracepoint_fields_types(cw, fields, class);
486
487 return ret;
488}
489
490static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
491 struct bt_ctf_event_class *event_class)
492{
493 u64 type = evsel->attr.sample_type;
494
495
496
497
498
499
500
501
502
503
504
505
506
507#define ADD_FIELD(cl, t, n) \
508 do { \
509 pr2(" field '%s'\n", n); \
510 if (bt_ctf_event_class_add_field(cl, t, n)) { \
511 pr_err("Failed to add field '%s;\n", n); \
512 return -1; \
513 } \
514 } while (0)
515
516 if (type & PERF_SAMPLE_IP)
517 ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
518
519 if (type & PERF_SAMPLE_TID) {
520 ADD_FIELD(event_class, cw->data.s32, "perf_tid");
521 ADD_FIELD(event_class, cw->data.s32, "perf_pid");
522 }
523
524 if ((type & PERF_SAMPLE_ID) ||
525 (type & PERF_SAMPLE_IDENTIFIER))
526 ADD_FIELD(event_class, cw->data.u64, "perf_id");
527
528 if (type & PERF_SAMPLE_STREAM_ID)
529 ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
530
531 if (type & PERF_SAMPLE_CPU)
532 ADD_FIELD(event_class, cw->data.u32, "perf_cpu");
533
534 if (type & PERF_SAMPLE_PERIOD)
535 ADD_FIELD(event_class, cw->data.u64, "perf_period");
536
537 if (type & PERF_SAMPLE_WEIGHT)
538 ADD_FIELD(event_class, cw->data.u64, "perf_weight");
539
540 if (type & PERF_SAMPLE_DATA_SRC)
541 ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
542
543 if (type & PERF_SAMPLE_TRANSACTION)
544 ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
545
546#undef ADD_FIELD
547 return 0;
548}
549
550static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
551{
552 struct bt_ctf_event_class *event_class;
553 struct evsel_priv *priv;
554 const char *name = perf_evsel__name(evsel);
555 int ret;
556
557 pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
558
559 event_class = bt_ctf_event_class_create(name);
560 if (!event_class)
561 return -1;
562
563 ret = add_generic_types(cw, evsel, event_class);
564 if (ret)
565 goto err;
566
567 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
568 ret = add_tracepoint_types(cw, evsel, event_class);
569 if (ret)
570 goto err;
571 }
572
573 ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
574 if (ret) {
575 pr("Failed to add event class into stream.\n");
576 goto err;
577 }
578
579 priv = malloc(sizeof(*priv));
580 if (!priv)
581 goto err;
582
583 priv->event_class = event_class;
584 evsel->priv = priv;
585 return 0;
586
587err:
588 bt_ctf_event_class_put(event_class);
589 pr_err("Failed to add event '%s'.\n", name);
590 return -1;
591}
592
593static int setup_events(struct ctf_writer *cw, struct perf_session *session)
594{
595 struct perf_evlist *evlist = session->evlist;
596 struct perf_evsel *evsel;
597 int ret;
598
599 evlist__for_each(evlist, evsel) {
600 ret = add_event(cw, evsel);
601 if (ret)
602 return ret;
603 }
604 return 0;
605}
606
607static int ctf_writer__setup_env(struct ctf_writer *cw,
608 struct perf_session *session)
609{
610 struct perf_header *header = &session->header;
611 struct bt_ctf_writer *writer = cw->writer;
612
613#define ADD(__n, __v) \
614do { \
615 if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \
616 return -1; \
617} while (0)
618
619 ADD("host", header->env.hostname);
620 ADD("sysname", "Linux");
621 ADD("release", header->env.os_release);
622 ADD("version", header->env.version);
623 ADD("machine", header->env.arch);
624 ADD("domain", "kernel");
625 ADD("tracer_name", "perf");
626
627#undef ADD
628 return 0;
629}
630
631static int ctf_writer__setup_clock(struct ctf_writer *cw)
632{
633 struct bt_ctf_clock *clock = cw->clock;
634
635 bt_ctf_clock_set_description(clock, "perf clock");
636
637#define SET(__n, __v) \
638do { \
639 if (bt_ctf_clock_set_##__n(clock, __v)) \
640 return -1; \
641} while (0)
642
643 SET(frequency, 1000000000);
644 SET(offset_s, 0);
645 SET(offset, 0);
646 SET(precision, 10);
647 SET(is_absolute, 0);
648
649#undef SET
650 return 0;
651}
652
653static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
654{
655 struct bt_ctf_field_type *type;
656
657 type = bt_ctf_field_type_integer_create(size);
658 if (!type)
659 return NULL;
660
661 if (sign &&
662 bt_ctf_field_type_integer_set_signed(type, 1))
663 goto err;
664
665 if (hex &&
666 bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
667 goto err;
668
669 pr2("Created type: INTEGER %d-bit %ssigned %s\n",
670 size, sign ? "un" : "", hex ? "hex" : "");
671 return type;
672
673err:
674 bt_ctf_field_type_put(type);
675 return NULL;
676}
677
678static void ctf_writer__cleanup_data(struct ctf_writer *cw)
679{
680 unsigned int i;
681
682 for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
683 bt_ctf_field_type_put(cw->data.array[i]);
684}
685
686static int ctf_writer__init_data(struct ctf_writer *cw)
687{
688#define CREATE_INT_TYPE(type, size, sign, hex) \
689do { \
690 (type) = create_int_type(size, sign, hex); \
691 if (!(type)) \
692 goto err; \
693} while (0)
694
695 CREATE_INT_TYPE(cw->data.s64, 64, true, false);
696 CREATE_INT_TYPE(cw->data.u64, 64, false, false);
697 CREATE_INT_TYPE(cw->data.s32, 32, true, false);
698 CREATE_INT_TYPE(cw->data.u32, 32, false, false);
699 CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
700
701 cw->data.string = bt_ctf_field_type_string_create();
702 if (cw->data.string)
703 return 0;
704
705err:
706 ctf_writer__cleanup_data(cw);
707 pr_err("Failed to create data types.\n");
708 return -1;
709}
710
711static void ctf_writer__cleanup(struct ctf_writer *cw)
712{
713 ctf_writer__cleanup_data(cw);
714
715 bt_ctf_clock_put(cw->clock);
716 bt_ctf_stream_put(cw->stream);
717 bt_ctf_stream_class_put(cw->stream_class);
718 bt_ctf_writer_put(cw->writer);
719
720
721 memset(cw, 0, sizeof(*cw));
722}
723
724static int ctf_writer__init(struct ctf_writer *cw, const char *path)
725{
726 struct bt_ctf_writer *writer;
727 struct bt_ctf_stream_class *stream_class;
728 struct bt_ctf_stream *stream;
729 struct bt_ctf_clock *clock;
730
731
732 writer = bt_ctf_writer_create(path);
733 if (!writer)
734 goto err;
735
736 cw->writer = writer;
737
738
739 clock = bt_ctf_clock_create("perf_clock");
740 if (!clock) {
741 pr("Failed to create CTF clock.\n");
742 goto err_cleanup;
743 }
744
745 cw->clock = clock;
746
747 if (ctf_writer__setup_clock(cw)) {
748 pr("Failed to setup CTF clock.\n");
749 goto err_cleanup;
750 }
751
752
753 stream_class = bt_ctf_stream_class_create("perf_stream");
754 if (!stream_class) {
755 pr("Failed to create CTF stream class.\n");
756 goto err_cleanup;
757 }
758
759 cw->stream_class = stream_class;
760
761
762 if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
763 pr("Failed to assign CTF clock to stream class.\n");
764 goto err_cleanup;
765 }
766
767 if (ctf_writer__init_data(cw))
768 goto err_cleanup;
769
770
771 stream = bt_ctf_writer_create_stream(writer, stream_class);
772 if (!stream) {
773 pr("Failed to create CTF stream.\n");
774 goto err_cleanup;
775 }
776
777 cw->stream = stream;
778
779
780 if (bt_ctf_writer_add_clock(writer, clock)) {
781 pr("Failed to assign CTF clock to writer.\n");
782 goto err_cleanup;
783 }
784
785 return 0;
786
787err_cleanup:
788 ctf_writer__cleanup(cw);
789err:
790 pr_err("Failed to setup CTF writer.\n");
791 return -1;
792}
793
794int bt_convert__perf2ctf(const char *input, const char *path, bool force)
795{
796 struct perf_session *session;
797 struct perf_data_file file = {
798 .path = input,
799 .mode = PERF_DATA_MODE_READ,
800 .force = force,
801 };
802 struct convert c = {
803 .tool = {
804 .sample = process_sample_event,
805 .mmap = perf_event__process_mmap,
806 .mmap2 = perf_event__process_mmap2,
807 .comm = perf_event__process_comm,
808 .exit = perf_event__process_exit,
809 .fork = perf_event__process_fork,
810 .lost = perf_event__process_lost,
811 .tracing_data = perf_event__process_tracing_data,
812 .build_id = perf_event__process_build_id,
813 .ordered_events = true,
814 .ordering_requires_timestamps = true,
815 },
816 };
817 struct ctf_writer *cw = &c.writer;
818 int err = -1;
819
820
821 if (ctf_writer__init(cw, path))
822 return -1;
823
824
825 session = perf_session__new(&file, 0, &c.tool);
826 if (!session)
827 goto free_writer;
828
829
830 if (ctf_writer__setup_env(cw, session))
831 goto free_session;
832
833
834 if (setup_events(cw, session))
835 goto free_session;
836
837 err = perf_session__process_events(session);
838 if (!err)
839 err = bt_ctf_stream_flush(cw->stream);
840
841 fprintf(stderr,
842 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
843 file.path, path);
844
845 fprintf(stderr,
846 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n",
847 (double) c.events_size / 1024.0 / 1024.0,
848 c.events_count);
849
850
851free_session:
852 perf_session__delete(session);
853
854free_writer:
855 ctf_writer__cleanup(cw);
856 return err;
857}
858