a6fea46ce55e5e9d3dcca669bf4bd1d8839ce1f4
[lttng-tools.git] / src / bin / lttng-sessiond / save.c
1 /*
2 * Copyright (C) 2014 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #define _LGPL_SOURCE
19 #include <assert.h>
20 #include <inttypes.h>
21 #include <string.h>
22 #include <urcu/uatomic.h>
23 #include <unistd.h>
24
25 #include <common/defaults.h>
26 #include <common/error.h>
27 #include <common/config/session-config.h>
28 #include <common/utils.h>
29 #include <common/runas.h>
30 #include <lttng/save-internal.h>
31
32 #include "kernel.h"
33 #include "save.h"
34 #include "session.h"
35 #include "syscall.h"
36 #include "trace-ust.h"
37 #include "agent.h"
38
39 static
40 int save_kernel_channel_attributes(struct config_writer *writer,
41 struct lttng_channel_attr *attr)
42 {
43 int ret;
44
45 ret = config_writer_write_element_string(writer,
46 config_element_overwrite_mode,
47 attr->overwrite ? config_overwrite_mode_overwrite :
48 config_overwrite_mode_discard);
49 if (ret) {
50 goto end;
51 }
52
53 ret = config_writer_write_element_unsigned_int(writer,
54 config_element_subbuf_size, attr->subbuf_size);
55 if (ret) {
56 goto end;
57 }
58
59 ret = config_writer_write_element_unsigned_int(writer,
60 config_element_num_subbuf,
61 attr->num_subbuf);
62 if (ret) {
63 goto end;
64 }
65
66 ret = config_writer_write_element_unsigned_int(writer,
67 config_element_switch_timer_interval,
68 attr->switch_timer_interval);
69 if (ret) {
70 goto end;
71 }
72
73 ret = config_writer_write_element_unsigned_int(writer,
74 config_element_read_timer_interval,
75 attr->read_timer_interval);
76 if (ret) {
77 goto end;
78 }
79
80 ret = config_writer_write_element_string(writer,
81 config_element_output_type,
82 attr->output == LTTNG_EVENT_SPLICE ?
83 config_output_type_splice : config_output_type_mmap);
84 if (ret) {
85 goto end;
86 }
87
88 ret = config_writer_write_element_unsigned_int(writer,
89 config_element_tracefile_size, attr->tracefile_size);
90 if (ret) {
91 goto end;
92 }
93
94 ret = config_writer_write_element_unsigned_int(writer,
95 config_element_tracefile_count,
96 attr->tracefile_count);
97 if (ret) {
98 goto end;
99 }
100
101 ret = config_writer_write_element_unsigned_int(writer,
102 config_element_live_timer_interval,
103 attr->live_timer_interval);
104 if (ret) {
105 goto end;
106 }
107 end:
108 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
109 }
110
111 static
112 int save_ust_channel_attributes(struct config_writer *writer,
113 struct lttng_ust_channel_attr *attr)
114 {
115 int ret;
116
117 ret = config_writer_write_element_string(writer,
118 config_element_overwrite_mode,
119 attr->overwrite ? config_overwrite_mode_overwrite :
120 config_overwrite_mode_discard);
121 if (ret) {
122 goto end;
123 }
124
125 ret = config_writer_write_element_unsigned_int(writer,
126 config_element_subbuf_size, attr->subbuf_size);
127 if (ret) {
128 goto end;
129 }
130
131 ret = config_writer_write_element_unsigned_int(writer,
132 config_element_num_subbuf,
133 attr->num_subbuf);
134 if (ret) {
135 goto end;
136 }
137
138 ret = config_writer_write_element_unsigned_int(writer,
139 config_element_switch_timer_interval,
140 attr->switch_timer_interval);
141 if (ret) {
142 goto end;
143 }
144
145 ret = config_writer_write_element_unsigned_int(writer,
146 config_element_read_timer_interval,
147 attr->read_timer_interval);
148 if (ret) {
149 goto end;
150 }
151
152 ret = config_writer_write_element_string(writer,
153 config_element_output_type,
154 attr->output == LTTNG_UST_MMAP ?
155 config_output_type_mmap : config_output_type_splice);
156 if (ret) {
157 goto end;
158 }
159 end:
160 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
161 }
162
163 static
164 const char *get_kernel_instrumentation_string(
165 enum lttng_kernel_instrumentation instrumentation)
166 {
167 const char *instrumentation_string;
168
169 switch (instrumentation) {
170 case LTTNG_KERNEL_ALL:
171 instrumentation_string = config_event_type_all;
172 break;
173 case LTTNG_KERNEL_TRACEPOINT:
174 instrumentation_string = config_event_type_tracepoint;
175 break;
176 case LTTNG_KERNEL_KPROBE:
177 instrumentation_string = config_event_type_kprobe;
178 break;
179 case LTTNG_KERNEL_FUNCTION:
180 instrumentation_string = config_event_type_function;
181 break;
182 case LTTNG_KERNEL_KRETPROBE:
183 instrumentation_string = config_event_type_kretprobe;
184 break;
185 case LTTNG_KERNEL_NOOP:
186 instrumentation_string = config_event_type_noop;
187 break;
188 case LTTNG_KERNEL_SYSCALL:
189 instrumentation_string = config_event_type_syscall;
190 break;
191 default:
192 instrumentation_string = NULL;
193 }
194
195 return instrumentation_string;
196 }
197
198 static
199 const char *get_kernel_context_type_string(
200 enum lttng_kernel_context_type context_type)
201 {
202 const char *context_type_string;
203
204 switch (context_type) {
205 case LTTNG_KERNEL_CONTEXT_PID:
206 context_type_string = config_event_context_pid;
207 break;
208 case LTTNG_KERNEL_CONTEXT_PROCNAME:
209 context_type_string = config_event_context_procname;
210 break;
211 case LTTNG_KERNEL_CONTEXT_PRIO:
212 context_type_string = config_event_context_prio;
213 break;
214 case LTTNG_KERNEL_CONTEXT_NICE:
215 context_type_string = config_event_context_nice;
216 break;
217 case LTTNG_KERNEL_CONTEXT_VPID:
218 context_type_string = config_event_context_vpid;
219 break;
220 case LTTNG_KERNEL_CONTEXT_TID:
221 context_type_string = config_event_context_tid;
222 break;
223 case LTTNG_KERNEL_CONTEXT_VTID:
224 context_type_string = config_event_context_vtid;
225 break;
226 case LTTNG_KERNEL_CONTEXT_PPID:
227 context_type_string = config_event_context_ppid;
228 break;
229 case LTTNG_KERNEL_CONTEXT_VPPID:
230 context_type_string = config_event_context_vppid;
231 break;
232 case LTTNG_KERNEL_CONTEXT_HOSTNAME:
233 context_type_string = config_event_context_hostname;
234 break;
235 default:
236 context_type_string = NULL;
237 }
238
239 return context_type_string;
240 }
241
242 static
243 const char *get_ust_context_type_string(
244 enum lttng_ust_context_type context_type)
245 {
246 const char *context_type_string;
247
248 switch (context_type) {
249 case LTTNG_UST_CONTEXT_PROCNAME:
250 context_type_string = config_event_context_procname;
251 break;
252 case LTTNG_UST_CONTEXT_VPID:
253 context_type_string = config_event_context_vpid;
254 break;
255 case LTTNG_UST_CONTEXT_VTID:
256 context_type_string = config_event_context_vtid;
257 break;
258 case LTTNG_UST_CONTEXT_IP:
259 context_type_string = config_event_context_ip;
260 break;
261 case LTTNG_UST_CONTEXT_PTHREAD_ID:
262 context_type_string = config_event_context_pthread_id;
263 break;
264 case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
265 /*
266 * Error, should not be stored in the XML, perf contexts
267 * are stored as a node of type event_perf_context_type.
268 */
269 default:
270 context_type_string = NULL;
271 break;
272 }
273
274 return context_type_string;
275 }
276
277 static
278 const char *get_buffer_type_string(
279 enum lttng_buffer_type buffer_type)
280 {
281 const char *buffer_type_string;
282
283 switch (buffer_type) {
284 case LTTNG_BUFFER_PER_PID:
285 buffer_type_string = config_buffer_type_per_pid;
286 break;
287 case LTTNG_BUFFER_PER_UID:
288 buffer_type_string = config_buffer_type_per_uid;
289 break;
290 case LTTNG_BUFFER_GLOBAL:
291 buffer_type_string = config_buffer_type_global;
292 break;
293 default:
294 buffer_type_string = NULL;
295 }
296
297 return buffer_type_string;
298 }
299
300 static
301 const char *get_loglevel_type_string(
302 enum lttng_ust_loglevel_type loglevel_type)
303 {
304 const char *loglevel_type_string;
305
306 switch (loglevel_type) {
307 case LTTNG_UST_LOGLEVEL_ALL:
308 loglevel_type_string = config_loglevel_type_all;
309 break;
310 case LTTNG_UST_LOGLEVEL_RANGE:
311 loglevel_type_string = config_loglevel_type_range;
312 break;
313 case LTTNG_UST_LOGLEVEL_SINGLE:
314 loglevel_type_string = config_loglevel_type_single;
315 break;
316 default:
317 loglevel_type_string = NULL;
318 }
319
320 return loglevel_type_string;
321 }
322
323 static
324 int save_kernel_event(struct config_writer *writer,
325 struct ltt_kernel_event *event)
326 {
327 int ret;
328 const char *instrumentation_type;
329
330 ret = config_writer_open_element(writer, config_element_event);
331 if (ret) {
332 ret = LTTNG_ERR_SAVE_IO_FAIL;
333 goto end;
334 }
335
336 if (event->event->name[0]) {
337 ret = config_writer_write_element_string(writer,
338 config_element_name, event->event->name);
339 if (ret) {
340 ret = LTTNG_ERR_SAVE_IO_FAIL;
341 goto end;
342 }
343 }
344
345 ret = config_writer_write_element_bool(writer, config_element_enabled,
346 event->enabled);
347 if (ret) {
348 ret = LTTNG_ERR_SAVE_IO_FAIL;
349 goto end;
350 }
351
352 instrumentation_type = get_kernel_instrumentation_string(
353 event->event->instrumentation);
354 if (!instrumentation_type) {
355 ret = LTTNG_ERR_INVALID;
356 goto end;
357 }
358
359 ret = config_writer_write_element_string(writer, config_element_type,
360 instrumentation_type);
361 if (ret) {
362 ret = LTTNG_ERR_SAVE_IO_FAIL;
363 goto end;
364 }
365
366 if (event->filter_expression) {
367 ret = config_writer_write_element_string(writer,
368 config_element_filter,
369 event->filter_expression);
370 if (ret) {
371 ret = LTTNG_ERR_SAVE_IO_FAIL;
372 goto end;
373 }
374 }
375
376 if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
377 event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
378 event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
379
380 ret = config_writer_open_element(writer,
381 config_element_attributes);
382 if (ret) {
383 ret = LTTNG_ERR_SAVE_IO_FAIL;
384 goto end;
385 }
386
387 switch (event->event->instrumentation) {
388 case LTTNG_KERNEL_SYSCALL:
389 case LTTNG_KERNEL_FUNCTION:
390 ret = config_writer_open_element(writer,
391 config_element_function_attributes);
392 if (ret) {
393 ret = LTTNG_ERR_SAVE_IO_FAIL;
394 goto end;
395 }
396
397 ret = config_writer_write_element_string(writer,
398 config_element_name,
399 event->event->u.ftrace.symbol_name);
400 if (ret) {
401 ret = LTTNG_ERR_SAVE_IO_FAIL;
402 goto end;
403 }
404
405 /* /function attributes */
406 ret = config_writer_close_element(writer);
407 if (ret) {
408 ret = LTTNG_ERR_SAVE_IO_FAIL;
409 goto end;
410 }
411 break;
412 case LTTNG_KERNEL_KPROBE:
413 case LTTNG_KERNEL_KRETPROBE:
414 {
415 const char *symbol_name;
416 uint64_t addr;
417 uint64_t offset;
418
419 if (event->event->instrumentation ==
420 LTTNG_KERNEL_KPROBE) {
421 /*
422 * Comments in lttng-kernel.h mention that
423 * either addr or symbol_name are set, not both.
424 */
425 addr = event->event->u.kprobe.addr;
426 offset = event->event->u.kprobe.offset;
427 symbol_name = addr ? NULL :
428 event->event->u.kprobe.symbol_name;
429 } else {
430 symbol_name =
431 event->event->u.kretprobe.symbol_name;
432 addr = event->event->u.kretprobe.addr;
433 offset = event->event->u.kretprobe.offset;
434 }
435
436 ret = config_writer_open_element(writer,
437 config_element_probe_attributes);
438 if (ret) {
439 ret = LTTNG_ERR_SAVE_IO_FAIL;
440 goto end;
441 }
442
443 if (symbol_name) {
444 ret = config_writer_write_element_string(writer,
445 config_element_symbol_name,
446 symbol_name);
447 if (ret) {
448 ret = LTTNG_ERR_SAVE_IO_FAIL;
449 goto end;
450 }
451 }
452
453 if (addr) {
454 ret = config_writer_write_element_unsigned_int(
455 writer, config_element_address, addr);
456 if (ret) {
457 ret = LTTNG_ERR_SAVE_IO_FAIL;
458 goto end;
459 }
460 }
461
462 if (offset) {
463 ret = config_writer_write_element_unsigned_int(
464 writer, config_element_offset, offset);
465 if (ret) {
466 ret = LTTNG_ERR_SAVE_IO_FAIL;
467 goto end;
468 }
469 }
470
471 ret = config_writer_close_element(writer);
472 if (ret) {
473 ret = LTTNG_ERR_SAVE_IO_FAIL;
474 goto end;
475 }
476 break;
477 }
478 default:
479 ERR("Unsupported kernel instrumentation type.");
480 ret = LTTNG_ERR_INVALID;
481 goto end;
482 }
483
484 /* /attributes */
485 ret = config_writer_close_element(writer);
486 if (ret) {
487 ret = LTTNG_ERR_SAVE_IO_FAIL;
488 goto end;
489 }
490 }
491
492 /* /event */
493 ret = config_writer_close_element(writer);
494 if (ret) {
495 ret = LTTNG_ERR_SAVE_IO_FAIL;
496 goto end;
497 }
498 end:
499 return ret;
500 }
501
502 static
503 int save_kernel_syscall(struct config_writer *writer,
504 struct ltt_kernel_channel *kchan)
505 {
506 int ret, i;
507 ssize_t count;
508 struct lttng_event *events = NULL;
509
510 assert(writer);
511 assert(kchan);
512
513 count = syscall_list_channel(kchan, &events, 0);
514 if (!count) {
515 /* No syscalls, just gracefully return. */
516 ret = 0;
517 goto end;
518 }
519
520 for (i = 0; i < count; i++) {
521 struct ltt_kernel_event *kevent;
522
523 /* Create a temporary kevent in order to save it. */
524 /*
525 * TODO: struct lttng_event does not really work for a filter,
526 * but unfortunately, it is exposed as external API (and used as
527 * internal representation. Using NULL meanwhile.
528 */
529 kevent = trace_kernel_create_event(&events[i],
530 NULL, NULL);
531 if (!kevent) {
532 ret = -ENOMEM;
533 goto end;
534 }
535 /* Init list in order so the destroy call can del the node. */
536 CDS_INIT_LIST_HEAD(&kevent->list);
537
538 ret = save_kernel_event(writer, kevent);
539 trace_kernel_destroy_event(kevent);
540 if (ret) {
541 goto end;
542 }
543 }
544
545 /* Everything went well */
546 ret = 0;
547
548 end:
549 free(events);
550 return ret;
551 }
552
553 static
554 int save_kernel_events(struct config_writer *writer,
555 struct ltt_kernel_channel *kchan)
556 {
557 int ret;
558 struct ltt_kernel_event *event;
559
560 ret = config_writer_open_element(writer, config_element_events);
561 if (ret) {
562 ret = LTTNG_ERR_SAVE_IO_FAIL;
563 goto end;
564 }
565
566 cds_list_for_each_entry(event, &kchan->events_list.head, list) {
567 ret = save_kernel_event(writer, event);
568 if (ret) {
569 goto end;
570 }
571 }
572
573 /* Save syscalls if any. */
574 ret = save_kernel_syscall(writer, kchan);
575 if (ret) {
576 goto end;
577 }
578
579 /* /events */
580 ret = config_writer_close_element(writer);
581 if (ret) {
582 ret = LTTNG_ERR_SAVE_IO_FAIL;
583 goto end;
584 }
585 end:
586 return ret;
587 }
588
589 static
590 int save_ust_event(struct config_writer *writer,
591 struct ltt_ust_event *event)
592 {
593 int ret;
594 const char *loglevel_type_string;
595
596 ret = config_writer_open_element(writer, config_element_event);
597 if (ret) {
598 ret = LTTNG_ERR_SAVE_IO_FAIL;
599 goto end;
600 }
601
602 if (event->attr.name[0]) {
603 ret = config_writer_write_element_string(writer,
604 config_element_name, event->attr.name);
605 if (ret) {
606 ret = LTTNG_ERR_SAVE_IO_FAIL;
607 goto end;
608 }
609 }
610
611 ret = config_writer_write_element_bool(writer, config_element_enabled,
612 event->enabled);
613 if (ret) {
614 ret = LTTNG_ERR_SAVE_IO_FAIL;
615 goto end;
616 }
617
618 if (event->attr.instrumentation != LTTNG_UST_TRACEPOINT) {
619 ERR("Unsupported UST instrumentation type.");
620 ret = LTTNG_ERR_INVALID;
621 goto end;
622 }
623 ret = config_writer_write_element_string(writer, config_element_type,
624 config_event_type_tracepoint);
625 if (ret) {
626 ret = LTTNG_ERR_SAVE_IO_FAIL;
627 goto end;
628 }
629
630 loglevel_type_string = get_loglevel_type_string(
631 event->attr.loglevel_type);
632 if (!loglevel_type_string) {
633 ERR("Unsupported UST loglevel type.");
634 ret = LTTNG_ERR_INVALID;
635 goto end;
636 }
637
638 ret = config_writer_write_element_string(writer,
639 config_element_loglevel_type, loglevel_type_string);
640 if (ret) {
641 ret = LTTNG_ERR_SAVE_IO_FAIL;
642 goto end;
643 }
644
645 /* The log level is irrelevant if no "filtering" is enabled */
646 if (event->attr.loglevel_type != LTTNG_UST_LOGLEVEL_ALL) {
647 ret = config_writer_write_element_signed_int(writer,
648 config_element_loglevel, event->attr.loglevel);
649 if (ret) {
650 ret = LTTNG_ERR_SAVE_IO_FAIL;
651 goto end;
652 }
653 }
654
655 if (event->filter_expression) {
656 ret = config_writer_write_element_string(writer,
657 config_element_filter, event->filter_expression);
658 if (ret) {
659 ret = LTTNG_ERR_SAVE_IO_FAIL;
660 goto end;
661 }
662 }
663
664 if (event->exclusion && event->exclusion->count) {
665 uint32_t i;
666
667 ret = config_writer_open_element(writer,
668 config_element_exclusions);
669 if (ret) {
670 ret = LTTNG_ERR_SAVE_IO_FAIL;
671 goto end;
672 }
673
674 for (i = 0; i < event->exclusion->count; i++) {
675 ret = config_writer_write_element_string(writer,
676 config_element_exclusion,
677 LTTNG_EVENT_EXCLUSION_NAME_AT(
678 event->exclusion, i));
679 if (ret) {
680 ret = LTTNG_ERR_SAVE_IO_FAIL;
681 goto end;
682 }
683 }
684
685 /* /exclusions */
686 ret = config_writer_close_element(writer);
687 if (ret) {
688 ret = LTTNG_ERR_SAVE_IO_FAIL;
689 goto end;
690 }
691 }
692
693 /* /event */
694 ret = config_writer_close_element(writer);
695 if (ret) {
696 ret = LTTNG_ERR_SAVE_IO_FAIL;
697 goto end;
698 }
699 end:
700 return ret;
701 }
702
703 static
704 int save_ust_events(struct config_writer *writer,
705 struct lttng_ht *events)
706 {
707 int ret;
708 struct ltt_ust_event *event;
709 struct lttng_ht_node_str *node;
710 struct lttng_ht_iter iter;
711
712 ret = config_writer_open_element(writer, config_element_events);
713 if (ret) {
714 ret = LTTNG_ERR_SAVE_IO_FAIL;
715 goto end;
716 }
717
718 rcu_read_lock();
719 cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) {
720 event = caa_container_of(node, struct ltt_ust_event, node);
721
722 if (event->internal) {
723 /* Internal events must not be exposed to clients */
724 continue;
725 }
726 ret = save_ust_event(writer, event);
727 if (ret) {
728 rcu_read_unlock();
729 goto end;
730 }
731 }
732 rcu_read_unlock();
733
734 /* /events */
735 ret = config_writer_close_element(writer);
736 if (ret) {
737 ret = LTTNG_ERR_SAVE_IO_FAIL;
738 goto end;
739 }
740 end:
741 return ret;
742 }
743
744 static
745 int init_ust_event_from_agent_event(struct ltt_ust_event *ust_event,
746 struct agent_event *agent_event)
747 {
748 int ret = 0;
749 enum lttng_ust_loglevel_type ust_loglevel_type;
750
751 ust_event->enabled = agent_event->enabled;
752 ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT;
753 strncpy(ust_event->attr.name, agent_event->name, LTTNG_SYMBOL_NAME_LEN);
754 switch (agent_event->loglevel_type) {
755 case LTTNG_EVENT_LOGLEVEL_ALL:
756 ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
757 break;
758 case LTTNG_EVENT_LOGLEVEL_SINGLE:
759 ust_loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE;
760 break;
761 case LTTNG_EVENT_LOGLEVEL_RANGE:
762 ust_loglevel_type = LTTNG_UST_LOGLEVEL_RANGE;
763 break;
764 default:
765 ERR("Invalid agent_event loglevel_type.");
766 ret = -1;
767 goto end;
768 }
769
770 ust_event->attr.loglevel_type = ust_loglevel_type;
771 ust_event->attr.loglevel = agent_event->loglevel_value;
772 ust_event->filter_expression = agent_event->filter_expression;
773 ust_event->exclusion = agent_event->exclusion;
774 end:
775 return ret;
776 }
777
778 static
779 int save_agent_events(struct config_writer *writer,
780 struct ltt_ust_channel *chan,
781 struct agent *agent)
782 {
783 int ret;
784 struct lttng_ht_iter iter;
785 struct lttng_ht_node_str *node;
786
787 ret = config_writer_open_element(writer, config_element_events);
788 if (ret) {
789 ret = LTTNG_ERR_SAVE_IO_FAIL;
790 goto end;
791 }
792
793 rcu_read_lock();
794 cds_lfht_for_each_entry(agent->events->ht, &iter.iter, node, node) {
795 int ret;
796 struct agent_event *agent_event;
797 struct ltt_ust_event fake_event;
798
799 memset(&fake_event, 0, sizeof(fake_event));
800 agent_event = caa_container_of(node, struct agent_event, node);
801
802 /*
803 * Initialize a fake ust event to reuse the same serialization
804 * function since UST and agent events contain the same info
805 * (and one could wonder why they don't reuse the same
806 * structures...).
807 */
808 ret = init_ust_event_from_agent_event(&fake_event, agent_event);
809 if (ret) {
810 rcu_read_unlock();
811 goto end;
812 }
813 ret = save_ust_event(writer, &fake_event);
814 if (ret) {
815 rcu_read_unlock();
816 goto end;
817 }
818 }
819 rcu_read_unlock();
820
821 /* /events */
822 ret = config_writer_close_element(writer);
823 if (ret) {
824 ret = LTTNG_ERR_SAVE_IO_FAIL;
825 goto end;
826 }
827 end:
828 return ret;
829 }
830
831 static
832 int save_kernel_context(struct config_writer *writer,
833 struct lttng_kernel_context *ctx)
834 {
835 int ret = 0;
836
837 if (!ctx) {
838 goto end;
839 }
840
841 ret = config_writer_open_element(writer, config_element_context);
842 if (ret) {
843 ret = LTTNG_ERR_SAVE_IO_FAIL;
844 goto end;
845 }
846
847 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
848 ret = config_writer_open_element(writer, config_element_perf);
849 if (ret) {
850 ret = LTTNG_ERR_SAVE_IO_FAIL;
851 goto end;
852 }
853
854 ret = config_writer_write_element_unsigned_int(writer,
855 config_element_type, ctx->u.perf_counter.type);
856 if (ret) {
857 ret = LTTNG_ERR_SAVE_IO_FAIL;
858 goto end;
859 }
860
861 ret = config_writer_write_element_unsigned_int(writer,
862 config_element_config, ctx->u.perf_counter.config);
863 if (ret) {
864 ret = LTTNG_ERR_SAVE_IO_FAIL;
865 goto end;
866 }
867
868 ret = config_writer_write_element_string(writer,
869 config_element_name, ctx->u.perf_counter.name);
870 if (ret) {
871 ret = LTTNG_ERR_SAVE_IO_FAIL;
872 goto end;
873 }
874
875 /* /perf */
876 ret = config_writer_close_element(writer);
877 if (ret) {
878 ret = LTTNG_ERR_SAVE_IO_FAIL;
879 goto end;
880 }
881 } else {
882 const char *context_type_string =
883 get_kernel_context_type_string(ctx->ctx);
884
885 if (!context_type_string) {
886 ERR("Unsupported kernel context type.");
887 ret = LTTNG_ERR_INVALID;
888 goto end;
889 }
890
891 ret = config_writer_write_element_string(writer,
892 config_element_type, context_type_string);
893 if (ret) {
894 ret = LTTNG_ERR_SAVE_IO_FAIL;
895 goto end;
896 }
897 }
898
899 /* /context */
900 ret = config_writer_close_element(writer);
901 if (ret) {
902 ret = LTTNG_ERR_SAVE_IO_FAIL;
903 goto end;
904 }
905
906 end:
907 return ret;
908 }
909
910 static
911 int save_kernel_contexts(struct config_writer *writer,
912 struct ltt_kernel_channel *kchan)
913 {
914 int ret;
915 struct ltt_kernel_context *ctx;
916
917 if (cds_list_empty(&kchan->ctx_list)) {
918 ret = 0;
919 goto end;
920 }
921
922 ret = config_writer_open_element(writer, config_element_contexts);
923 if (ret) {
924 ret = LTTNG_ERR_SAVE_IO_FAIL;
925 goto end;
926 }
927
928 cds_list_for_each_entry(ctx, &kchan->ctx_list, list) {
929 ret = save_kernel_context(writer, &ctx->ctx);
930 if (ret) {
931 goto end;
932 }
933 }
934
935 /* /contexts */
936 ret = config_writer_close_element(writer);
937 if (ret) {
938 ret = LTTNG_ERR_SAVE_IO_FAIL;
939 goto end;
940 }
941 end:
942 return ret;
943 }
944
945 static
946 int save_ust_context(struct config_writer *writer,
947 struct cds_list_head *ctx_list)
948 {
949 int ret;
950 struct ltt_ust_context *ctx;
951
952 assert(writer);
953 assert(ctx_list);
954
955 ret = config_writer_open_element(writer, config_element_contexts);
956 if (ret) {
957 ret = LTTNG_ERR_SAVE_IO_FAIL;
958 goto end;
959 }
960
961 cds_list_for_each_entry(ctx, ctx_list, list) {
962 const char *context_type_string;
963
964
965 ret = config_writer_open_element(writer,
966 config_element_context);
967 if (ret) {
968 ret = LTTNG_ERR_SAVE_IO_FAIL;
969 goto end;
970 }
971
972 if (ctx->ctx.ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) {
973 /* Perf contexts are saved as event_perf_context_type */
974 ret = config_writer_open_element(writer,
975 config_element_perf);
976 if (ret) {
977 ret = LTTNG_ERR_SAVE_IO_FAIL;
978 goto end;
979 }
980
981 ret = config_writer_write_element_unsigned_int(writer,
982 config_element_type,
983 ctx->ctx.u.perf_counter.type);
984 if (ret) {
985 ret = LTTNG_ERR_SAVE_IO_FAIL;
986 goto end;
987 }
988
989 ret = config_writer_write_element_unsigned_int(writer,
990 config_element_config,
991 ctx->ctx.u.perf_counter.config);
992 if (ret) {
993 ret = LTTNG_ERR_SAVE_IO_FAIL;
994 goto end;
995 }
996
997 ret = config_writer_write_element_string(writer,
998 config_element_name,
999 ctx->ctx.u.perf_counter.name);
1000 if (ret) {
1001 ret = LTTNG_ERR_SAVE_IO_FAIL;
1002 goto end;
1003 }
1004
1005 /* /perf */
1006 ret = config_writer_close_element(writer);
1007 if (ret) {
1008 ret = LTTNG_ERR_SAVE_IO_FAIL;
1009 goto end;
1010 }
1011 } else {
1012 /* Save context as event_context_type_type */
1013 context_type_string = get_ust_context_type_string(
1014 ctx->ctx.ctx);
1015 if (!context_type_string) {
1016 ERR("Unsupported UST context type.")
1017 ret = LTTNG_ERR_INVALID;
1018 goto end;
1019 }
1020
1021 ret = config_writer_write_element_string(writer,
1022 config_element_type, context_type_string);
1023 if (ret) {
1024 ret = LTTNG_ERR_SAVE_IO_FAIL;
1025 goto end;
1026 }
1027 }
1028
1029 /* /context */
1030 ret = config_writer_close_element(writer);
1031 if (ret) {
1032 ret = LTTNG_ERR_SAVE_IO_FAIL;
1033 goto end;
1034 }
1035 }
1036
1037 /* /contexts */
1038 ret = config_writer_close_element(writer);
1039 if (ret) {
1040 ret = LTTNG_ERR_SAVE_IO_FAIL;
1041 goto end;
1042 }
1043 end:
1044 return ret;
1045 }
1046
1047 static
1048 int save_kernel_channel(struct config_writer *writer,
1049 struct ltt_kernel_channel *kchan)
1050 {
1051 int ret;
1052
1053 assert(writer);
1054 assert(kchan);
1055
1056 ret = config_writer_open_element(writer, config_element_channel);
1057 if (ret) {
1058 ret = LTTNG_ERR_SAVE_IO_FAIL;
1059 goto end;
1060 }
1061
1062 ret = config_writer_write_element_string(writer, config_element_name,
1063 kchan->channel->name);
1064 if (ret) {
1065 ret = LTTNG_ERR_SAVE_IO_FAIL;
1066 goto end;
1067 }
1068
1069 ret = config_writer_write_element_bool(writer, config_element_enabled,
1070 kchan->channel->enabled);
1071 if (ret) {
1072 ret = LTTNG_ERR_SAVE_IO_FAIL;
1073 goto end;
1074 }
1075
1076 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
1077 if (ret) {
1078 goto end;
1079 }
1080
1081 ret = save_kernel_events(writer, kchan);
1082 if (ret) {
1083 goto end;
1084 }
1085
1086 ret = save_kernel_contexts(writer, kchan);
1087 if (ret) {
1088 goto end;
1089 }
1090
1091 /* /channel */
1092 ret = config_writer_close_element(writer);
1093 if (ret) {
1094 ret = LTTNG_ERR_SAVE_IO_FAIL;
1095 goto end;
1096 }
1097 end:
1098 return ret;
1099 }
1100
1101 static
1102 int save_ust_channel(struct config_writer *writer,
1103 struct ltt_ust_channel *ust_chan,
1104 struct ltt_ust_session *session)
1105 {
1106 int ret;
1107
1108 assert(writer);
1109 assert(ust_chan);
1110 assert(session);
1111
1112 ret = config_writer_open_element(writer, config_element_channel);
1113 if (ret) {
1114 ret = LTTNG_ERR_SAVE_IO_FAIL;
1115 goto end;
1116 }
1117
1118 ret = config_writer_write_element_string(writer, config_element_name,
1119 ust_chan->name);
1120 if (ret) {
1121 ret = LTTNG_ERR_SAVE_IO_FAIL;
1122 goto end;
1123 }
1124
1125 ret = config_writer_write_element_bool(writer, config_element_enabled,
1126 ust_chan->enabled);
1127 if (ret) {
1128 ret = LTTNG_ERR_SAVE_IO_FAIL;
1129 goto end;
1130 }
1131
1132 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
1133 if (ret) {
1134 goto end;
1135 }
1136
1137 ret = config_writer_write_element_unsigned_int(writer,
1138 config_element_tracefile_size, ust_chan->tracefile_size);
1139 if (ret) {
1140 ret = LTTNG_ERR_SAVE_IO_FAIL;
1141 goto end;
1142 }
1143
1144 ret = config_writer_write_element_unsigned_int(writer,
1145 config_element_tracefile_count, ust_chan->tracefile_count);
1146 if (ret) {
1147 ret = LTTNG_ERR_SAVE_IO_FAIL;
1148 goto end;
1149 }
1150
1151 ret = config_writer_write_element_unsigned_int(writer,
1152 config_element_live_timer_interval,
1153 session->live_timer_interval);
1154 if (ret) {
1155 ret = LTTNG_ERR_SAVE_IO_FAIL;
1156 goto end;
1157 }
1158
1159 if (ust_chan->domain == LTTNG_DOMAIN_UST) {
1160 ret = save_ust_events(writer, ust_chan->events);
1161 if (ret) {
1162 goto end;
1163 }
1164 } else {
1165 struct agent *agent = NULL;
1166
1167 agent = trace_ust_find_agent(session, ust_chan->domain);
1168 if (!agent) {
1169 ret = LTTNG_ERR_SAVE_IO_FAIL;
1170 ERR("Could not find agent associated to UST subdomain");
1171 goto end;
1172 }
1173
1174 /*
1175 * Channels associated with a UST sub-domain (such as JUL, Log4j
1176 * or Python) don't have any non-internal events. We retrieve
1177 * the "agent" events associated with this channel and serialize
1178 * them.
1179 */
1180 ret = save_agent_events(writer, ust_chan, agent);
1181 if (ret) {
1182 goto end;
1183 }
1184 }
1185
1186 ret = save_ust_context(writer, &ust_chan->ctx_list);
1187 if (ret) {
1188 goto end;
1189 }
1190
1191 /* /channel */
1192 ret = config_writer_close_element(writer);
1193 if (ret) {
1194 ret = LTTNG_ERR_SAVE_IO_FAIL;
1195 goto end;
1196 }
1197 end:
1198 return ret;
1199 }
1200
1201 static
1202 int save_kernel_session(struct config_writer *writer,
1203 struct ltt_session *session)
1204 {
1205 int ret;
1206 struct ltt_kernel_channel *kchan;
1207
1208 assert(writer);
1209 assert(session);
1210
1211 ret = config_writer_write_element_string(writer, config_element_type,
1212 config_domain_type_kernel);
1213 if (ret) {
1214 ret = LTTNG_ERR_SAVE_IO_FAIL;
1215 goto end;
1216 }
1217
1218 ret = config_writer_write_element_string(writer,
1219 config_element_buffer_type, config_buffer_type_global);
1220 if (ret) {
1221 ret = LTTNG_ERR_SAVE_IO_FAIL;
1222 goto end;
1223 }
1224
1225 ret = config_writer_open_element(writer,
1226 config_element_channels);
1227 if (ret) {
1228 ret = LTTNG_ERR_SAVE_IO_FAIL;
1229 goto end;
1230 }
1231
1232 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
1233 list) {
1234 ret = save_kernel_channel(writer, kchan);
1235 if (ret) {
1236 goto end;
1237 }
1238 }
1239
1240 /* /channels */
1241 ret = config_writer_close_element(writer);
1242 if (ret) {
1243 ret = LTTNG_ERR_SAVE_IO_FAIL;
1244 goto end;
1245 }
1246 end:
1247 return ret;
1248 }
1249
1250 static
1251 const char *get_config_domain_str(enum lttng_domain_type domain)
1252 {
1253 const char *str_dom;
1254
1255 switch (domain) {
1256 case LTTNG_DOMAIN_KERNEL:
1257 str_dom = config_domain_type_kernel;
1258 break;
1259 case LTTNG_DOMAIN_UST:
1260 str_dom = config_domain_type_ust;
1261 break;
1262 case LTTNG_DOMAIN_JUL:
1263 str_dom = config_domain_type_jul;
1264 break;
1265 case LTTNG_DOMAIN_LOG4J:
1266 str_dom = config_domain_type_log4j;
1267 break;
1268 case LTTNG_DOMAIN_PYTHON:
1269 str_dom = config_domain_type_python;
1270 break;
1271 default:
1272 assert(0);
1273 }
1274
1275 return str_dom;
1276 }
1277
1278 static
1279 int save_pid_tracker(struct config_writer *writer,
1280 struct ltt_session *sess, int domain)
1281 {
1282 int ret = 0;
1283 ssize_t nr_pids = 0, i;
1284 int32_t *pids = NULL;
1285
1286 switch (domain) {
1287 case LTTNG_DOMAIN_KERNEL:
1288 {
1289 nr_pids = kernel_list_tracker_pids(sess->kernel_session, &pids);
1290 if (nr_pids < 0) {
1291 ret = LTTNG_ERR_KERN_LIST_FAIL;
1292 goto end;
1293 }
1294 break;
1295 }
1296 case LTTNG_DOMAIN_UST:
1297 {
1298 nr_pids = trace_ust_list_tracker_pids(sess->ust_session, &pids);
1299 if (nr_pids < 0) {
1300 ret = LTTNG_ERR_UST_LIST_FAIL;
1301 goto end;
1302 }
1303 break;
1304 }
1305 case LTTNG_DOMAIN_JUL:
1306 case LTTNG_DOMAIN_LOG4J:
1307 case LTTNG_DOMAIN_PYTHON:
1308 default:
1309 ret = LTTNG_ERR_UNKNOWN_DOMAIN;
1310 goto end;
1311 }
1312
1313 /* Only create a pid_tracker if enabled or untrack all */
1314 if (nr_pids != 1 || (nr_pids == 1 && pids[0] != -1)) {
1315 ret = config_writer_open_element(writer,
1316 config_element_pid_tracker);
1317 if (ret) {
1318 ret = LTTNG_ERR_SAVE_IO_FAIL;
1319 goto end;
1320 }
1321
1322 ret = config_writer_open_element(writer,
1323 config_element_targets);
1324 if (ret) {
1325 ret = LTTNG_ERR_SAVE_IO_FAIL;
1326 goto end;
1327 }
1328
1329 for (i = 0; i < nr_pids; i++) {
1330 ret = config_writer_open_element(writer,
1331 config_element_target_pid);
1332 if (ret) {
1333 ret = LTTNG_ERR_SAVE_IO_FAIL;
1334 goto end;
1335 }
1336
1337 ret = config_writer_write_element_unsigned_int(writer,
1338 config_element_pid, pids[i]);
1339 if (ret) {
1340 ret = LTTNG_ERR_SAVE_IO_FAIL;
1341 goto end;
1342 }
1343
1344 /* /pid_target */
1345 ret = config_writer_close_element(writer);
1346 if (ret) {
1347 ret = LTTNG_ERR_SAVE_IO_FAIL;
1348 goto end;
1349 }
1350 }
1351
1352 /* /targets */
1353 ret = config_writer_close_element(writer);
1354 if (ret) {
1355 ret = LTTNG_ERR_SAVE_IO_FAIL;
1356 goto end;
1357 }
1358
1359 /* /pid_tracker */
1360 ret = config_writer_close_element(writer);
1361 if (ret) {
1362 ret = LTTNG_ERR_SAVE_IO_FAIL;
1363 goto end;
1364 }
1365 }
1366 end:
1367 free(pids);
1368 return ret;
1369 }
1370
1371 static
1372 int save_ust_domain(struct config_writer *writer,
1373 struct ltt_session *session, enum lttng_domain_type domain)
1374 {
1375 int ret;
1376 struct ltt_ust_channel *ust_chan;
1377 const char *buffer_type_string;
1378 struct lttng_ht_node_str *node;
1379 struct lttng_ht_iter iter;
1380 const char *config_domain_name;
1381
1382 assert(writer);
1383 assert(session);
1384
1385 ret = config_writer_open_element(writer,
1386 config_element_domain);
1387 if (ret) {
1388 ret = LTTNG_ERR_SAVE_IO_FAIL;
1389 goto end;
1390 }
1391
1392 config_domain_name = get_config_domain_str(domain);
1393 if (!config_domain_name) {
1394 ret = LTTNG_ERR_INVALID;
1395 goto end;
1396 }
1397
1398 ret = config_writer_write_element_string(writer,
1399 config_element_type, config_domain_name);
1400 if (ret) {
1401 ret = LTTNG_ERR_SAVE_IO_FAIL;
1402 goto end;
1403 }
1404
1405 buffer_type_string = get_buffer_type_string(
1406 session->ust_session->buffer_type);
1407 if (!buffer_type_string) {
1408 ERR("Unsupported buffer type.");
1409 ret = LTTNG_ERR_INVALID;
1410 goto end;
1411 }
1412
1413 ret = config_writer_write_element_string(writer,
1414 config_element_buffer_type, buffer_type_string);
1415 if (ret) {
1416 ret = LTTNG_ERR_SAVE_IO_FAIL;
1417 goto end;
1418 }
1419
1420 ret = config_writer_open_element(writer, config_element_channels);
1421 if (ret) {
1422 ret = LTTNG_ERR_SAVE_IO_FAIL;
1423 goto end;
1424 }
1425
1426 rcu_read_lock();
1427 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1428 &iter.iter, node, node) {
1429 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
1430 if (domain == ust_chan->domain) {
1431 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1432 if (ret) {
1433 rcu_read_unlock();
1434 goto end;
1435 }
1436 }
1437 }
1438 rcu_read_unlock();
1439
1440 /* /channels */
1441 ret = config_writer_close_element(writer);
1442 if (ret) {
1443 ret = LTTNG_ERR_SAVE_IO_FAIL;
1444 goto end;
1445 }
1446
1447 if (domain == LTTNG_DOMAIN_UST) {
1448 ret = config_writer_open_element(writer,
1449 config_element_trackers);
1450 if (ret) {
1451 ret = LTTNG_ERR_SAVE_IO_FAIL;
1452 goto end;
1453 }
1454
1455 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST);
1456 if (ret) {
1457 goto end;
1458 }
1459
1460 /* /trackers */
1461 ret = config_writer_close_element(writer);
1462 if (ret) {
1463 goto end;
1464 }
1465 }
1466
1467 /* /domain */
1468 ret = config_writer_close_element(writer);
1469 if (ret) {
1470 ret = LTTNG_ERR_SAVE_IO_FAIL;
1471 goto end;
1472 }
1473
1474 end:
1475 return ret;
1476 }
1477
1478 static
1479 int save_domains(struct config_writer *writer, struct ltt_session *session)
1480 {
1481 int ret = 0;
1482
1483 assert(writer);
1484 assert(session);
1485
1486 if (!session->kernel_session && !session->ust_session) {
1487 goto end;
1488 }
1489
1490 ret = config_writer_open_element(writer, config_element_domains);
1491 if (ret) {
1492 ret = LTTNG_ERR_SAVE_IO_FAIL;
1493 goto end;
1494 }
1495
1496
1497 if (session->kernel_session) {
1498 ret = config_writer_open_element(writer,
1499 config_element_domain);
1500 if (ret) {
1501 ret = LTTNG_ERR_SAVE_IO_FAIL;
1502 goto end;
1503 }
1504
1505 ret = save_kernel_session(writer, session);
1506 if (ret) {
1507 goto end;
1508 }
1509
1510 ret = config_writer_open_element(writer,
1511 config_element_trackers);
1512 if (ret) {
1513 ret = LTTNG_ERR_SAVE_IO_FAIL;
1514 goto end;
1515 }
1516
1517 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL);
1518 if (ret) {
1519 goto end;
1520 }
1521
1522 /* /trackers */
1523 ret = config_writer_close_element(writer);
1524 if (ret) {
1525 ret = LTTNG_ERR_SAVE_IO_FAIL;
1526 goto end;
1527 }
1528 /* /domain */
1529 ret = config_writer_close_element(writer);
1530 if (ret) {
1531 ret = LTTNG_ERR_SAVE_IO_FAIL;
1532 goto end;
1533 }
1534 }
1535
1536 if (session->ust_session) {
1537 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST);
1538 if (ret) {
1539 goto end;
1540 }
1541
1542 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL);
1543 if (ret) {
1544 goto end;
1545 }
1546
1547 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J);
1548 if (ret) {
1549 goto end;
1550 }
1551
1552 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON);
1553 if (ret) {
1554 goto end;
1555 }
1556 }
1557
1558 /* /domains */
1559 ret = config_writer_close_element(writer);
1560 if (ret) {
1561 ret = LTTNG_ERR_SAVE_IO_FAIL;
1562 goto end;
1563 }
1564 end:
1565 return ret;
1566 }
1567
1568 static
1569 int save_consumer_output(struct config_writer *writer,
1570 struct consumer_output *output)
1571 {
1572 int ret;
1573
1574 assert(writer);
1575 assert(output);
1576
1577 ret = config_writer_open_element(writer, config_element_consumer_output);
1578 if (ret) {
1579 ret = LTTNG_ERR_SAVE_IO_FAIL;
1580 goto end;
1581 }
1582
1583 ret = config_writer_write_element_bool(writer, config_element_enabled,
1584 output->enabled);
1585 if (ret) {
1586 ret = LTTNG_ERR_SAVE_IO_FAIL;
1587 goto end;
1588 }
1589
1590 ret = config_writer_open_element(writer, config_element_destination);
1591 if (ret) {
1592 ret = LTTNG_ERR_SAVE_IO_FAIL;
1593 goto end;
1594 }
1595
1596 switch (output->type) {
1597 case CONSUMER_DST_LOCAL:
1598 ret = config_writer_write_element_string(writer,
1599 config_element_path, output->dst.trace_path);
1600 if (ret) {
1601 ret = LTTNG_ERR_SAVE_IO_FAIL;
1602 goto end;
1603 }
1604 break;
1605 case CONSUMER_DST_NET:
1606 {
1607 char *uri;
1608
1609 uri = zmalloc(PATH_MAX);
1610 if (!uri) {
1611 ret = LTTNG_ERR_NOMEM;
1612 goto end;
1613 }
1614
1615 ret = config_writer_open_element(writer, config_element_net_output);
1616 if (ret) {
1617 ret = LTTNG_ERR_SAVE_IO_FAIL;
1618 goto end_net_output;
1619 }
1620
1621 if (output->dst.net.control_isset &&
1622 output->dst.net.data_isset) {
1623 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1624 if (ret < 0) {
1625 ret = LTTNG_ERR_INVALID;
1626 goto end_net_output;
1627 }
1628
1629 ret = config_writer_write_element_string(writer,
1630 config_element_control_uri, uri);
1631 if (ret) {
1632 ret = LTTNG_ERR_SAVE_IO_FAIL;
1633 goto end_net_output;
1634 }
1635
1636 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1637 if (ret < 0) {
1638 ret = LTTNG_ERR_INVALID;
1639 goto end_net_output;
1640 }
1641
1642 ret = config_writer_write_element_string(writer,
1643 config_element_data_uri, uri);
1644 if (ret) {
1645 ret = LTTNG_ERR_SAVE_IO_FAIL;
1646 goto end_net_output;
1647 }
1648
1649 end_net_output:
1650 free(uri);
1651 if (ret) {
1652 goto end;
1653 }
1654 } else {
1655 ret = !output->dst.net.control_isset ?
1656 LTTNG_ERR_URL_CTRL_MISS :
1657 LTTNG_ERR_URL_DATA_MISS;
1658 free(uri);
1659 goto end;
1660 }
1661
1662 ret = config_writer_close_element(writer);
1663 if (ret) {
1664 ret = LTTNG_ERR_SAVE_IO_FAIL;
1665 goto end;
1666 }
1667 break;
1668 }
1669 default:
1670 ERR("Unsupported consumer output type.");
1671 ret = LTTNG_ERR_INVALID;
1672 goto end;
1673 }
1674
1675 /* /destination */
1676 ret = config_writer_close_element(writer);
1677 if (ret) {
1678 ret = LTTNG_ERR_SAVE_IO_FAIL;
1679 goto end;
1680 }
1681
1682 /* /consumer_output */
1683 ret = config_writer_close_element(writer);
1684 if (ret) {
1685 ret = LTTNG_ERR_SAVE_IO_FAIL;
1686 goto end;
1687 }
1688 end:
1689 return ret;
1690 }
1691
1692 static
1693 int save_snapshot_outputs(struct config_writer *writer,
1694 struct snapshot *snapshot)
1695 {
1696 int ret;
1697 struct lttng_ht_iter iter;
1698 struct snapshot_output *output;
1699
1700 assert(writer);
1701 assert(snapshot);
1702
1703 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1704 if (ret) {
1705 ret = LTTNG_ERR_SAVE_IO_FAIL;
1706 goto end;
1707 }
1708
1709 rcu_read_lock();
1710 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1711 node.node) {
1712 ret = config_writer_open_element(writer,
1713 config_element_output);
1714 if (ret) {
1715 ret = LTTNG_ERR_SAVE_IO_FAIL;
1716 goto end_unlock;
1717 }
1718
1719 ret = config_writer_write_element_string(writer,
1720 config_element_name, output->name);
1721 if (ret) {
1722 ret = LTTNG_ERR_SAVE_IO_FAIL;
1723 goto end_unlock;
1724 }
1725
1726 ret = config_writer_write_element_unsigned_int(writer,
1727 config_element_max_size, output->max_size);
1728 if (ret) {
1729 ret = LTTNG_ERR_SAVE_IO_FAIL;
1730 goto end_unlock;
1731 }
1732
1733 ret = save_consumer_output(writer, output->consumer);
1734 if (ret) {
1735 goto end_unlock;
1736 }
1737
1738 /* /output */
1739 ret = config_writer_close_element(writer);
1740 if (ret) {
1741 ret = LTTNG_ERR_SAVE_IO_FAIL;
1742 goto end_unlock;
1743 }
1744 }
1745 rcu_read_unlock();
1746
1747 /* /snapshot_outputs */
1748 ret = config_writer_close_element(writer);
1749 if (ret) {
1750 ret = LTTNG_ERR_SAVE_IO_FAIL;
1751 goto end;
1752 }
1753
1754 end:
1755 return ret;
1756 end_unlock:
1757 rcu_read_unlock();
1758 return ret;
1759 }
1760
1761 static
1762 int save_session_output(struct config_writer *writer,
1763 struct ltt_session *session)
1764 {
1765 int ret;
1766
1767 assert(writer);
1768 assert(session);
1769
1770 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1771 (!session->snapshot_mode && !session->consumer)) {
1772 /* Session is in no output mode */
1773 ret = 0;
1774 goto end;
1775 }
1776
1777 ret = config_writer_open_element(writer, config_element_output);
1778 if (ret) {
1779 ret = LTTNG_ERR_SAVE_IO_FAIL;
1780 goto end;
1781 }
1782
1783 if (session->snapshot_mode) {
1784 ret = save_snapshot_outputs(writer, &session->snapshot);
1785 if (ret) {
1786 goto end;
1787 }
1788 } else {
1789 if (session->consumer) {
1790 ret = save_consumer_output(writer, session->consumer);
1791 if (ret) {
1792 goto end;
1793 }
1794 }
1795 }
1796
1797 /* /output */
1798 ret = config_writer_close_element(writer);
1799 if (ret) {
1800 ret = LTTNG_ERR_SAVE_IO_FAIL;
1801 goto end;
1802 }
1803 end:
1804 return ret;
1805 }
1806
1807 /*
1808 * Save the given session.
1809 *
1810 * Return 0 on success else a LTTNG_ERR* code.
1811 */
1812 static
1813 int save_session(struct ltt_session *session,
1814 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1815 {
1816 int ret, fd;
1817 unsigned int file_opened = 0; /* Indicate if the file has been opened */
1818 char config_file_path[PATH_MAX];
1819 size_t len;
1820 struct config_writer *writer = NULL;
1821 size_t session_name_len;
1822 const char *provided_path;
1823
1824 assert(session);
1825 assert(attr);
1826 assert(creds);
1827
1828 session_name_len = strlen(session->name);
1829 memset(config_file_path, 0, sizeof(config_file_path));
1830
1831 if (!session_access_ok(session,
1832 LTTNG_SOCK_GET_UID_CRED(creds),
1833 LTTNG_SOCK_GET_GID_CRED(creds))) {
1834 ret = LTTNG_ERR_EPERM;
1835 goto end;
1836 }
1837
1838 provided_path = lttng_save_session_attr_get_output_url(attr);
1839 if (provided_path) {
1840 DBG3("Save session in provided path %s", provided_path);
1841 len = strlen(provided_path);
1842 if (len >= sizeof(config_file_path)) {
1843 ret = LTTNG_ERR_SET_URL;
1844 goto end;
1845 }
1846 strncpy(config_file_path, provided_path, len);
1847 } else {
1848 ssize_t ret_len;
1849 char *home_dir = utils_get_user_home_dir(
1850 LTTNG_SOCK_GET_UID_CRED(creds));
1851 if (!home_dir) {
1852 ret = LTTNG_ERR_SET_URL;
1853 goto end;
1854 }
1855
1856 ret_len = snprintf(config_file_path, sizeof(config_file_path),
1857 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1858 free(home_dir);
1859 if (ret_len < 0) {
1860 PERROR("snprintf save session");
1861 ret = LTTNG_ERR_SET_URL;
1862 goto end;
1863 }
1864 len = ret_len;
1865 }
1866
1867 /*
1868 * Check the path fits in the config file path dst including the '/'
1869 * followed by trailing .lttng extension and the NULL terminated string.
1870 */
1871 if ((len + session_name_len + 2 +
1872 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1873 > sizeof(config_file_path)) {
1874 ret = LTTNG_ERR_SET_URL;
1875 goto end;
1876 }
1877
1878 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1879 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1880 if (ret) {
1881 ret = LTTNG_ERR_SET_URL;
1882 goto end;
1883 }
1884
1885 /*
1886 * At this point, we know that everything fits in the buffer. Validation
1887 * was done just above.
1888 */
1889 config_file_path[len++] = '/';
1890 strncpy(config_file_path + len, session->name, session_name_len);
1891 len += session_name_len;
1892 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1893 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1894 config_file_path[len] = '\0';
1895
1896 if (!access(config_file_path, F_OK) && !attr->overwrite) {
1897 /* File exists, notify the user since the overwrite flag is off. */
1898 ret = LTTNG_ERR_SAVE_FILE_EXIST;
1899 goto end;
1900 }
1901
1902 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1903 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1904 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1905 if (fd < 0) {
1906 PERROR("Could not create configuration file");
1907 ret = LTTNG_ERR_SAVE_IO_FAIL;
1908 goto end;
1909 }
1910 file_opened = 1;
1911
1912 writer = config_writer_create(fd, 1);
1913 if (!writer) {
1914 ret = LTTNG_ERR_NOMEM;
1915 goto end;
1916 }
1917
1918 ret = config_writer_open_element(writer, config_element_sessions);
1919 if (ret) {
1920 ret = LTTNG_ERR_SAVE_IO_FAIL;
1921 goto end;
1922 }
1923
1924 ret = config_writer_open_element(writer, config_element_session);
1925 if (ret) {
1926 ret = LTTNG_ERR_SAVE_IO_FAIL;
1927 goto end;
1928 }
1929
1930 ret = config_writer_write_element_string(writer, config_element_name,
1931 session->name);
1932 if (ret) {
1933 ret = LTTNG_ERR_SAVE_IO_FAIL;
1934 goto end;
1935 }
1936
1937 if(session->shm_path[0] != '\0') {
1938 ret = config_writer_write_element_string(writer,
1939 config_element_shared_memory_path,
1940 session->shm_path);
1941 if (ret) {
1942 ret = LTTNG_ERR_SAVE_IO_FAIL;
1943 goto end;
1944 }
1945 }
1946
1947 ret = save_domains(writer, session);
1948 if (ret) {
1949 goto end;
1950 }
1951
1952 ret = config_writer_write_element_bool(writer, config_element_started,
1953 session->active);
1954 if (ret) {
1955 ret = LTTNG_ERR_SAVE_IO_FAIL;
1956 goto end;
1957 }
1958
1959 if (session->snapshot_mode || session->live_timer) {
1960 ret = config_writer_open_element(writer, config_element_attributes);
1961 if (ret) {
1962 ret = LTTNG_ERR_SAVE_IO_FAIL;
1963 goto end;
1964 }
1965
1966 if (session->snapshot_mode) {
1967 ret = config_writer_write_element_bool(writer,
1968 config_element_snapshot_mode, 1);
1969 if (ret) {
1970 ret = LTTNG_ERR_SAVE_IO_FAIL;
1971 goto end;
1972 }
1973 } else {
1974 ret = config_writer_write_element_unsigned_int(writer,
1975 config_element_live_timer_interval, session->live_timer);
1976 if (ret) {
1977 ret = LTTNG_ERR_SAVE_IO_FAIL;
1978 goto end;
1979 }
1980 }
1981
1982 /* /attributes */
1983 ret = config_writer_close_element(writer);
1984 if (ret) {
1985 ret = LTTNG_ERR_SAVE_IO_FAIL;
1986 goto end;
1987 }
1988 }
1989
1990 ret = save_session_output(writer, session);
1991 if (ret) {
1992 goto end;
1993 }
1994
1995 /* /session */
1996 ret = config_writer_close_element(writer);
1997 if (ret) {
1998 ret = LTTNG_ERR_SAVE_IO_FAIL;
1999 goto end;
2000 }
2001
2002 /* /sessions */
2003 ret = config_writer_close_element(writer);
2004 if (ret) {
2005 ret = LTTNG_ERR_SAVE_IO_FAIL;
2006 goto end;
2007 }
2008 end:
2009 if (writer && config_writer_destroy(writer)) {
2010 /* Preserve the original error code */
2011 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
2012 }
2013 if (ret) {
2014 /* Delete file in case of error */
2015 if (file_opened && unlink(config_file_path)) {
2016 PERROR("Unlinking XML session configuration.");
2017 }
2018 }
2019
2020 return ret;
2021 }
2022
2023 int cmd_save_sessions(struct lttng_save_session_attr *attr,
2024 lttng_sock_cred *creds)
2025 {
2026 int ret;
2027 const char *session_name;
2028 struct ltt_session *session;
2029
2030 session_lock_list();
2031
2032 session_name = lttng_save_session_attr_get_session_name(attr);
2033 if (session_name) {
2034 session = session_find_by_name(session_name);
2035 if (!session) {
2036 ret = LTTNG_ERR_SESS_NOT_FOUND;
2037 goto end;
2038 }
2039
2040 session_lock(session);
2041 ret = save_session(session, attr, creds);
2042 session_unlock(session);
2043 if (ret) {
2044 goto end;
2045 }
2046 } else {
2047 struct ltt_session_list *list = session_get_list();
2048
2049 cds_list_for_each_entry(session, &list->head, list) {
2050 session_lock(session);
2051 ret = save_session(session, attr, creds);
2052 session_unlock(session);
2053
2054 /* Don't abort if we don't have the required permissions. */
2055 if (ret && ret != LTTNG_ERR_EPERM) {
2056 goto end;
2057 }
2058 }
2059 }
2060 ret = LTTNG_OK;
2061
2062 end:
2063 session_unlock_list();
2064 return ret;
2065 }
This page took 0.119908 seconds and 3 git commands to generate.