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