Skip internal events when saving a session configuration
[lttng-tools.git] / src / bin / lttng-sessiond / save.c
CommitLineData
fb198a11
JG
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 _GNU_SOURCE
6c1c0768 19#define _LGPL_SOURCE
fb198a11
JG
20#include <assert.h>
21#include <inttypes.h>
22#include <string.h>
23#include <urcu/uatomic.h>
24#include <unistd.h>
25
26#include <common/defaults.h>
27#include <common/error.h>
28#include <common/config/config.h>
fb198a11
JG
29#include <common/utils.h>
30#include <common/runas.h>
31#include <lttng/save-internal.h>
32
847a5916 33#include "kernel.h"
fb198a11
JG
34#include "save.h"
35#include "session.h"
0de3eda1 36#include "syscall.h"
fb198a11
JG
37#include "trace-ust.h"
38
39static
40int 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 }
107end:
108 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
109}
110
111static
112int 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 }
159end:
160 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
161}
162
163static
164const 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
198static
199const 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
242static
243const 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;
e885a367 264 case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
14ce5bd8
JG
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 */
fb198a11
JG
269 default:
270 context_type_string = NULL;
e885a367 271 break;
fb198a11
JG
272 }
273
274 return context_type_string;
275}
276
277static
278const 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
300static
301const 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
323static
324int 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->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
367 event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
368 event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
369
370 ret = config_writer_open_element(writer,
371 config_element_attributes);
372 if (ret) {
373 ret = LTTNG_ERR_SAVE_IO_FAIL;
374 goto end;
375 }
376
377 switch (event->event->instrumentation) {
0de3eda1 378 case LTTNG_KERNEL_SYSCALL:
fb198a11
JG
379 case LTTNG_KERNEL_FUNCTION:
380 ret = config_writer_open_element(writer,
381 config_element_function_attributes);
382 if (ret) {
383 ret = LTTNG_ERR_SAVE_IO_FAIL;
384 goto end;
385 }
386
387 ret = config_writer_write_element_string(writer,
388 config_element_name,
389 event->event->u.ftrace.symbol_name);
390 if (ret) {
391 ret = LTTNG_ERR_SAVE_IO_FAIL;
392 goto end;
393 }
394
395 /* /function attributes */
396 ret = config_writer_close_element(writer);
397 if (ret) {
398 ret = LTTNG_ERR_SAVE_IO_FAIL;
399 goto end;
400 }
401 break;
402 case LTTNG_KERNEL_KPROBE:
403 case LTTNG_KERNEL_KRETPROBE:
404 {
405 const char *symbol_name;
406 uint64_t addr;
407 uint64_t offset;
408
409 if (event->event->instrumentation ==
410 LTTNG_KERNEL_KPROBE) {
411 /*
412 * Comments in lttng-kernel.h mention that
413 * either addr or symbol_name are set, not both.
414 */
415 addr = event->event->u.kprobe.addr;
416 offset = event->event->u.kprobe.offset;
417 symbol_name = addr ? NULL :
418 event->event->u.kprobe.symbol_name;
419 } else {
420 symbol_name =
421 event->event->u.kretprobe.symbol_name;
422 addr = event->event->u.kretprobe.addr;
423 offset = event->event->u.kretprobe.offset;
424 }
425
426 ret = config_writer_open_element(writer,
427 config_element_probe_attributes);
428 if (ret) {
429 ret = LTTNG_ERR_SAVE_IO_FAIL;
430 goto end;
431 }
432
433 if (symbol_name) {
434 ret = config_writer_write_element_string(writer,
435 config_element_symbol_name,
436 symbol_name);
437 if (ret) {
438 ret = LTTNG_ERR_SAVE_IO_FAIL;
439 goto end;
440 }
441 }
442
443 if (addr) {
444 ret = config_writer_write_element_unsigned_int(
445 writer, config_element_address, addr);
446 if (ret) {
447 ret = LTTNG_ERR_SAVE_IO_FAIL;
448 goto end;
449 }
450 }
451
452 if (offset) {
453 ret = config_writer_write_element_unsigned_int(
454 writer, config_element_offset, offset);
455 if (ret) {
456 ret = LTTNG_ERR_SAVE_IO_FAIL;
457 goto end;
458 }
459 }
460
461 ret = config_writer_close_element(writer);
462 if (ret) {
463 ret = LTTNG_ERR_SAVE_IO_FAIL;
464 goto end;
465 }
466 break;
467 }
468 default:
469 ERR("Unsupported kernel instrumentation type.");
470 ret = LTTNG_ERR_INVALID;
471 goto end;
472 }
473
474 /* /attributes */
475 ret = config_writer_close_element(writer);
476 if (ret) {
477 ret = LTTNG_ERR_SAVE_IO_FAIL;
478 goto end;
479 }
480 }
481
482 /* /event */
483 ret = config_writer_close_element(writer);
484 if (ret) {
485 ret = LTTNG_ERR_SAVE_IO_FAIL;
486 goto end;
487 }
488end:
489 return ret;
490}
491
0de3eda1
DG
492static
493int save_kernel_syscall(struct config_writer *writer,
494 struct ltt_kernel_channel *kchan)
495{
496 int ret, i;
497 ssize_t count;
498 struct lttng_event *events = NULL;
499
500 assert(writer);
501 assert(kchan);
502
503 count = syscall_list_channel(kchan, &events, 0);
504 if (!count) {
505 /* No syscalls, just gracefully return. */
506 ret = 0;
507 goto end;
508 }
509
510 for (i = 0; i < count; i++) {
511 struct ltt_kernel_event *kevent;
512
513 /* Create a temporary kevent in order to save it. */
00a62084
MD
514 /*
515 * TODO: struct lttng_event does not really work for a filter,
516 * but unfortunately, it is exposed as external API (and used as
517 * internal representation. Using NULL meanwhile.
518 */
519 kevent = trace_kernel_create_event(&events[i],
520 NULL, NULL);
0de3eda1
DG
521 if (!kevent) {
522 ret = -ENOMEM;
523 goto end;
524 }
525 /* Init list in order so the destroy call can del the node. */
526 CDS_INIT_LIST_HEAD(&kevent->list);
527
528 ret = save_kernel_event(writer, kevent);
529 trace_kernel_destroy_event(kevent);
530 if (ret) {
531 goto end;
532 }
533 }
534
535 /* Everything went well */
536 ret = 0;
537
538end:
539 free(events);
540 return ret;
541}
542
fb198a11
JG
543static
544int save_kernel_events(struct config_writer *writer,
0de3eda1 545 struct ltt_kernel_channel *kchan)
fb198a11
JG
546{
547 int ret;
548 struct ltt_kernel_event *event;
549
550 ret = config_writer_open_element(writer, config_element_events);
551 if (ret) {
552 ret = LTTNG_ERR_SAVE_IO_FAIL;
553 goto end;
554 }
555
0de3eda1 556 cds_list_for_each_entry(event, &kchan->events_list.head, list) {
fb198a11
JG
557 ret = save_kernel_event(writer, event);
558 if (ret) {
559 goto end;
560 }
561 }
562
0de3eda1
DG
563 /* Save syscalls if any. */
564 ret = save_kernel_syscall(writer, kchan);
565 if (ret) {
566 goto end;
567 }
568
fb198a11
JG
569 /* /events */
570 ret = config_writer_close_element(writer);
571 if (ret) {
572 ret = LTTNG_ERR_SAVE_IO_FAIL;
573 goto end;
574 }
575end:
576 return ret;
577}
578
579static
580int save_ust_event(struct config_writer *writer,
581 struct ltt_ust_event *event)
582{
583 int ret;
584 const char *loglevel_type_string;
585
586 ret = config_writer_open_element(writer, config_element_event);
587 if (ret) {
588 ret = LTTNG_ERR_SAVE_IO_FAIL;
589 goto end;
590 }
591
592 if (event->attr.name[0]) {
593 ret = config_writer_write_element_string(writer,
594 config_element_name, event->attr.name);
595 if (ret) {
596 ret = LTTNG_ERR_SAVE_IO_FAIL;
597 goto end;
598 }
599 }
600
601 ret = config_writer_write_element_bool(writer, config_element_enabled,
602 event->enabled);
603 if (ret) {
604 ret = LTTNG_ERR_SAVE_IO_FAIL;
605 goto end;
606 }
607
608 if (event->attr.instrumentation != LTTNG_UST_TRACEPOINT) {
609 ERR("Unsupported UST instrumentation type.");
610 ret = LTTNG_ERR_INVALID;
611 goto end;
612 }
613 ret = config_writer_write_element_string(writer, config_element_type,
614 config_event_type_tracepoint);
615 if (ret) {
616 ret = LTTNG_ERR_SAVE_IO_FAIL;
617 goto end;
618 }
619
620 loglevel_type_string = get_loglevel_type_string(
621 event->attr.loglevel_type);
622 if (!loglevel_type_string) {
623 ERR("Unsupported UST loglevel type.");
624 ret = LTTNG_ERR_INVALID;
625 goto end;
626 }
627
628 ret = config_writer_write_element_string(writer,
629 config_element_loglevel_type, loglevel_type_string);
630 if (ret) {
631 ret = LTTNG_ERR_SAVE_IO_FAIL;
632 goto end;
633 }
634
635 ret = config_writer_write_element_signed_int(writer,
636 config_element_loglevel, event->attr.loglevel);
637 if (ret) {
638 ret = LTTNG_ERR_SAVE_IO_FAIL;
639 goto end;
640 }
641
642 if (event->filter_expression) {
643 ret = config_writer_write_element_string(writer,
644 config_element_filter, event->filter_expression);
645 if (ret) {
646 ret = LTTNG_ERR_SAVE_IO_FAIL;
647 goto end;
648 }
649 }
650
651 if (event->exclusion && event->exclusion->count) {
652 uint32_t i;
653
654 ret = config_writer_open_element(writer,
655 config_element_exclusions);
656 if (ret) {
657 ret = LTTNG_ERR_SAVE_IO_FAIL;
658 goto end;
659 }
660
661 for (i = 0; i < event->exclusion->count; i++) {
662 ret = config_writer_write_element_string(writer,
663 config_element_exclusion,
664 &event->exclusion->names[0][i]);
665 if (ret) {
666 ret = LTTNG_ERR_SAVE_IO_FAIL;
667 goto end;
668 }
669 }
670
671 /* /exclusions */
672 ret = config_writer_close_element(writer);
673 if (ret) {
674 ret = LTTNG_ERR_SAVE_IO_FAIL;
675 goto end;
676 }
677 }
678
679 /* /event */
680 ret = config_writer_close_element(writer);
681 if (ret) {
682 ret = LTTNG_ERR_SAVE_IO_FAIL;
683 goto end;
684 }
685end:
686 return ret;
687}
688
689static
690int save_ust_events(struct config_writer *writer,
691 struct lttng_ht *events)
692{
693 int ret;
694 struct ltt_ust_event *event;
695 struct lttng_ht_node_str *node;
696 struct lttng_ht_iter iter;
697
698 ret = config_writer_open_element(writer, config_element_events);
699 if (ret) {
700 ret = LTTNG_ERR_SAVE_IO_FAIL;
701 goto end;
702 }
703
704 rcu_read_lock();
705 cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) {
706 event = caa_container_of(node, struct ltt_ust_event, node);
707
af325ba1
JG
708 if (event->internal) {
709 /* Internal events must not be exposed to clients */
710 continue;
711 }
fb198a11
JG
712 ret = save_ust_event(writer, event);
713 if (ret) {
714 rcu_read_unlock();
715 goto end;
716 }
717 }
718 rcu_read_unlock();
719
720 /* /events */
721 ret = config_writer_close_element(writer);
722 if (ret) {
723 ret = LTTNG_ERR_SAVE_IO_FAIL;
724 goto end;
725 }
726end:
727 return ret;
728}
729
730static
731int save_kernel_context(struct config_writer *writer,
732 struct lttng_kernel_context *ctx)
733{
734 int ret = 0;
735
736 if (!ctx) {
737 goto end;
738 }
739
fb198a11
JG
740 ret = config_writer_open_element(writer, config_element_context);
741 if (ret) {
742 ret = LTTNG_ERR_SAVE_IO_FAIL;
743 goto end;
744 }
745
cba45eda 746 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
fb198a11
JG
747 ret = config_writer_open_element(writer, config_element_perf);
748 if (ret) {
749 ret = LTTNG_ERR_SAVE_IO_FAIL;
750 goto end;
751 }
752
753 ret = config_writer_write_element_unsigned_int(writer,
754 config_element_type, ctx->u.perf_counter.type);
755 if (ret) {
756 ret = LTTNG_ERR_SAVE_IO_FAIL;
757 goto end;
758 }
759
760 ret = config_writer_write_element_unsigned_int(writer,
761 config_element_config, ctx->u.perf_counter.config);
762 if (ret) {
763 ret = LTTNG_ERR_SAVE_IO_FAIL;
764 goto end;
765 }
766
767 ret = config_writer_write_element_string(writer,
768 config_element_name, ctx->u.perf_counter.name);
769 if (ret) {
770 ret = LTTNG_ERR_SAVE_IO_FAIL;
771 goto end;
772 }
773
774 /* /perf */
775 ret = config_writer_close_element(writer);
776 if (ret) {
777 ret = LTTNG_ERR_SAVE_IO_FAIL;
778 goto end;
779 }
780 } else {
781 const char *context_type_string =
782 get_kernel_context_type_string(ctx->ctx);
783
784 if (!context_type_string) {
785 ERR("Unsupported kernel context type.");
786 ret = LTTNG_ERR_INVALID;
787 goto end;
788 }
789
790 ret = config_writer_write_element_string(writer,
791 config_element_type, context_type_string);
792 if (ret) {
793 ret = LTTNG_ERR_SAVE_IO_FAIL;
794 goto end;
795 }
796 }
797
798 /* /context */
799 ret = config_writer_close_element(writer);
800 if (ret) {
801 ret = LTTNG_ERR_SAVE_IO_FAIL;
802 goto end;
803 }
804
645328ae
DG
805end:
806 return ret;
807}
808
809static
810int save_kernel_contexts(struct config_writer *writer,
811 struct ltt_kernel_channel *kchan)
812{
813 int ret;
814 struct ltt_kernel_context *ctx;
815
2aa64052
JG
816 if (cds_list_empty(&kchan->ctx_list)) {
817 ret = 0;
818 goto end;
819 }
820
645328ae
DG
821 ret = config_writer_open_element(writer, config_element_contexts);
822 if (ret) {
823 ret = LTTNG_ERR_SAVE_IO_FAIL;
824 goto end;
825 }
826
827 cds_list_for_each_entry(ctx, &kchan->ctx_list, list) {
828 ret = save_kernel_context(writer, &ctx->ctx);
829 if (ret) {
830 goto end;
831 }
832 }
833
fb198a11
JG
834 /* /contexts */
835 ret = config_writer_close_element(writer);
836 if (ret) {
837 ret = LTTNG_ERR_SAVE_IO_FAIL;
838 goto end;
839 }
840end:
841 return ret;
842}
843
844static
845int save_ust_context(struct config_writer *writer,
846 struct cds_list_head *ctx_list)
847{
848 int ret;
849 struct ltt_ust_context *ctx;
850
851 assert(writer);
852 assert(ctx_list);
853
854 ret = config_writer_open_element(writer, config_element_contexts);
855 if (ret) {
856 ret = LTTNG_ERR_SAVE_IO_FAIL;
857 goto end;
858 }
859
860 cds_list_for_each_entry(ctx, ctx_list, list) {
861 const char *context_type_string;
862
fb198a11
JG
863
864 ret = config_writer_open_element(writer,
865 config_element_context);
866 if (ret) {
867 ret = LTTNG_ERR_SAVE_IO_FAIL;
868 goto end;
869 }
870
14ce5bd8
JG
871 if (ctx->ctx.ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) {
872 /* Perf contexts are saved as event_perf_context_type */
873 ret = config_writer_open_element(writer,
874 config_element_perf);
875 if (ret) {
876 ret = LTTNG_ERR_SAVE_IO_FAIL;
877 goto end;
878 }
879
880 ret = config_writer_write_element_unsigned_int(writer,
881 config_element_type,
882 ctx->ctx.u.perf_counter.type);
883 if (ret) {
884 ret = LTTNG_ERR_SAVE_IO_FAIL;
885 goto end;
886 }
887
888 ret = config_writer_write_element_unsigned_int(writer,
889 config_element_config,
890 ctx->ctx.u.perf_counter.config);
891 if (ret) {
892 ret = LTTNG_ERR_SAVE_IO_FAIL;
893 goto end;
894 }
895
896 ret = config_writer_write_element_string(writer,
897 config_element_name,
898 ctx->ctx.u.perf_counter.name);
899 if (ret) {
900 ret = LTTNG_ERR_SAVE_IO_FAIL;
901 goto end;
902 }
903
904 /* /perf */
905 ret = config_writer_close_element(writer);
906 if (ret) {
907 ret = LTTNG_ERR_SAVE_IO_FAIL;
908 goto end;
909 }
910 } else {
911 /* Save context as event_context_type_type */
912 context_type_string = get_ust_context_type_string(
913 ctx->ctx.ctx);
914 if (!context_type_string) {
915 ERR("Unsupported UST context type.")
916 ret = LTTNG_ERR_INVALID;
917 goto end;
918 }
919
920 ret = config_writer_write_element_string(writer,
921 config_element_type, context_type_string);
922 if (ret) {
923 ret = LTTNG_ERR_SAVE_IO_FAIL;
924 goto end;
925 }
fb198a11
JG
926 }
927
928 /* /context */
929 ret = config_writer_close_element(writer);
930 if (ret) {
931 ret = LTTNG_ERR_SAVE_IO_FAIL;
932 goto end;
933 }
934 }
935
936 /* /contexts */
937 ret = config_writer_close_element(writer);
938 if (ret) {
939 ret = LTTNG_ERR_SAVE_IO_FAIL;
940 goto end;
941 }
942end:
943 return ret;
944}
945
946static
947int save_kernel_channel(struct config_writer *writer,
948 struct ltt_kernel_channel *kchan)
949{
950 int ret;
951
952 assert(writer);
953 assert(kchan);
954
955 ret = config_writer_open_element(writer, config_element_channel);
956 if (ret) {
957 ret = LTTNG_ERR_SAVE_IO_FAIL;
958 goto end;
959 }
960
961 ret = config_writer_write_element_string(writer, config_element_name,
962 kchan->channel->name);
963 if (ret) {
964 ret = LTTNG_ERR_SAVE_IO_FAIL;
965 goto end;
966 }
967
968 ret = config_writer_write_element_bool(writer, config_element_enabled,
969 kchan->channel->enabled);
970 if (ret) {
971 ret = LTTNG_ERR_SAVE_IO_FAIL;
972 goto end;
973 }
974
975 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
976 if (ret) {
977 goto end;
978 }
979
0de3eda1 980 ret = save_kernel_events(writer, kchan);
fb198a11
JG
981 if (ret) {
982 goto end;
983 }
984
645328ae 985 ret = save_kernel_contexts(writer, kchan);
fb198a11
JG
986 if (ret) {
987 goto end;
988 }
989
990 /* /channel */
991 ret = config_writer_close_element(writer);
992 if (ret) {
993 ret = LTTNG_ERR_SAVE_IO_FAIL;
994 goto end;
995 }
996end:
997 return ret;
998}
999
1000static
1001int save_ust_channel(struct config_writer *writer,
1002 struct ltt_ust_channel *ust_chan,
1003 struct ltt_ust_session *session)
1004{
1005 int ret;
1006
1007 assert(writer);
1008 assert(ust_chan);
1009 assert(session);
1010
1011 ret = config_writer_open_element(writer, config_element_channel);
1012 if (ret) {
1013 ret = LTTNG_ERR_SAVE_IO_FAIL;
1014 goto end;
1015 }
1016
1017 ret = config_writer_write_element_string(writer, config_element_name,
1018 ust_chan->name);
1019 if (ret) {
1020 ret = LTTNG_ERR_SAVE_IO_FAIL;
1021 goto end;
1022 }
1023
1024 ret = config_writer_write_element_bool(writer, config_element_enabled,
1025 ust_chan->enabled);
1026 if (ret) {
1027 ret = LTTNG_ERR_SAVE_IO_FAIL;
1028 goto end;
1029 }
1030
1031 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
1032 if (ret) {
1033 goto end;
1034 }
1035
1036 ret = config_writer_write_element_unsigned_int(writer,
1037 config_element_tracefile_size, ust_chan->tracefile_size);
1038 if (ret) {
1039 ret = LTTNG_ERR_SAVE_IO_FAIL;
1040 goto end;
1041 }
1042
1043 ret = config_writer_write_element_unsigned_int(writer,
1044 config_element_tracefile_count, ust_chan->tracefile_count);
1045 if (ret) {
1046 ret = LTTNG_ERR_SAVE_IO_FAIL;
1047 goto end;
1048 }
1049
1050 ret = config_writer_write_element_unsigned_int(writer,
1051 config_element_live_timer_interval,
1052 session->live_timer_interval);
1053 if (ret) {
1054 ret = LTTNG_ERR_SAVE_IO_FAIL;
1055 goto end;
1056 }
1057
1058 ret = save_ust_events(writer, ust_chan->events);
1059 if (ret) {
1060 ret = LTTNG_ERR_SAVE_IO_FAIL;
1061 goto end;
1062 }
1063
1064 ret = save_ust_context(writer, &ust_chan->ctx_list);
1065 if (ret) {
1066 goto end;
1067 }
1068
1069 /* /channel */
1070 ret = config_writer_close_element(writer);
1071 if (ret) {
1072 ret = LTTNG_ERR_SAVE_IO_FAIL;
1073 goto end;
1074 }
1075end:
1076 return ret;
1077}
1078
1079static
1080int save_kernel_session(struct config_writer *writer,
1081 struct ltt_session *session)
1082{
1083 int ret;
1084 struct ltt_kernel_channel *kchan;
1085
1086 assert(writer);
1087 assert(session);
1088
1089 ret = config_writer_write_element_string(writer, config_element_type,
1090 config_domain_type_kernel);
1091 if (ret) {
1092 ret = LTTNG_ERR_SAVE_IO_FAIL;
1093 goto end;
1094 }
1095
1096 ret = config_writer_write_element_string(writer,
1097 config_element_buffer_type, config_buffer_type_global);
1098 if (ret) {
1099 ret = LTTNG_ERR_SAVE_IO_FAIL;
1100 goto end;
1101 }
1102
1103 ret = config_writer_open_element(writer,
1104 config_element_channels);
1105 if (ret) {
1106 ret = LTTNG_ERR_SAVE_IO_FAIL;
1107 goto end;
1108 }
1109
1110 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
1111 list) {
1112 ret = save_kernel_channel(writer, kchan);
1113 if (ret) {
1114 goto end;
1115 }
1116 }
1117
1118 /* /channels */
1119 ret = config_writer_close_element(writer);
1120 if (ret) {
1121 ret = LTTNG_ERR_SAVE_IO_FAIL;
1122 goto end;
1123 }
1124end:
1125 return ret;
1126}
1127
1128static
1129int save_ust_session(struct config_writer *writer,
022d91ba 1130 struct ltt_session *session, int save_agent)
fb198a11
JG
1131{
1132 int ret;
1133 struct ltt_ust_channel *ust_chan;
1134 const char *buffer_type_string;
1135 struct lttng_ht_node_str *node;
1136 struct lttng_ht_iter iter;
1137
1138 assert(writer);
1139 assert(session);
1140
1141 ret = config_writer_write_element_string(writer, config_element_type,
022d91ba 1142 save_agent ? config_domain_type_jul : config_domain_type_ust);
fb198a11
JG
1143 if (ret) {
1144 ret = LTTNG_ERR_SAVE_IO_FAIL;
1145 goto end;
1146 }
1147
1148 buffer_type_string = get_buffer_type_string(
1149 session->ust_session->buffer_type);
1150 if (!buffer_type_string) {
1151 ERR("Unsupported buffer type.");
1152 ret = LTTNG_ERR_INVALID;
1153 goto end;
1154 }
1155
1156 ret = config_writer_write_element_string(writer,
1157 config_element_buffer_type, buffer_type_string);
1158 if (ret) {
1159 ret = LTTNG_ERR_SAVE_IO_FAIL;
1160 goto end;
1161 }
1162
1163 ret = config_writer_open_element(writer, config_element_channels);
1164 if (ret) {
1165 ret = LTTNG_ERR_SAVE_IO_FAIL;
1166 goto end;
1167 }
1168
1169 rcu_read_lock();
1170 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1171 &iter.iter, node, node) {
022d91ba 1172 int agent_channel;
fb198a11
JG
1173
1174 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
da6c3a50 1175 agent_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name) ||
0e115563
DG
1176 !strcmp(DEFAULT_LOG4J_CHANNEL_NAME, ust_chan->name) ||
1177 !strcmp(DEFAULT_PYTHON_CHANNEL_NAME, ust_chan->name);
022d91ba 1178 if (!(save_agent ^ agent_channel)) {
fb198a11
JG
1179 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1180 if (ret) {
1181 rcu_read_unlock();
1182 goto end;
1183 }
1184 }
1185 }
1186 rcu_read_unlock();
1187
1188 /* /channels */
1189 ret = config_writer_close_element(writer);
1190 if (ret) {
1191 ret = LTTNG_ERR_SAVE_IO_FAIL;
1192 goto end;
1193 }
1194end:
1195 return ret;
1196}
1197
847a5916
JR
1198static
1199int save_pid_tracker(struct config_writer *writer,
1200 struct ltt_session *sess, int domain)
1201{
1202 int ret = 0;
1203 ssize_t nr_pids = 0, i;
1204 int32_t *pids = NULL;
1205
1206 switch (domain) {
1207 case LTTNG_DOMAIN_KERNEL:
1208 {
1209 nr_pids = kernel_list_tracker_pids(sess->kernel_session, &pids);
1210 if (nr_pids < 0) {
1211 ret = LTTNG_ERR_KERN_LIST_FAIL;
1212 goto end;
1213 }
1214 break;
1215 }
1216 case LTTNG_DOMAIN_UST:
1217 {
1218 nr_pids = trace_ust_list_tracker_pids(sess->ust_session, &pids);
1219 if (nr_pids < 0) {
1220 ret = LTTNG_ERR_UST_LIST_FAIL;
1221 goto end;
1222 }
1223 break;
1224 }
1225 case LTTNG_DOMAIN_JUL:
1226 case LTTNG_DOMAIN_LOG4J:
1227 case LTTNG_DOMAIN_PYTHON:
1228 default:
1229 ret = LTTNG_ERR_UNKNOWN_DOMAIN;
1230 goto end;
1231 }
1232
1233 /* Only create a pid_tracker if enabled or untrack all */
1234 if (nr_pids != 1 || (nr_pids == 1 && pids[0] != -1)) {
1235 ret = config_writer_open_element(writer,
1236 config_element_pid_tracker);
1237 if (ret) {
1238 ret = LTTNG_ERR_SAVE_IO_FAIL;
1239 goto end;
1240 }
1241
1242 ret = config_writer_open_element(writer,
1243 config_element_targets);
1244 if (ret) {
1245 ret = LTTNG_ERR_SAVE_IO_FAIL;
1246 goto end;
1247 }
1248
1249 for (i = 0; i < nr_pids; i++) {
1250 ret = config_writer_open_element(writer,
1251 config_element_target_pid);
1252 if (ret) {
1253 ret = LTTNG_ERR_SAVE_IO_FAIL;
1254 goto end;
1255 }
1256
1257 ret = config_writer_write_element_unsigned_int(writer,
1258 config_element_pid, pids[i]);
1259 if (ret) {
1260 ret = LTTNG_ERR_SAVE_IO_FAIL;
1261 goto end;
1262 }
1263
1264 /* /pid_target */
1265 ret = config_writer_close_element(writer);
1266 if (ret) {
1267 ret = LTTNG_ERR_SAVE_IO_FAIL;
1268 goto end;
1269 }
1270 }
1271
1272 /* /targets */
1273 ret = config_writer_close_element(writer);
1274 if (ret) {
1275 ret = LTTNG_ERR_SAVE_IO_FAIL;
1276 goto end;
1277 }
1278
1279 /* /pid_tracker */
1280 ret = config_writer_close_element(writer);
1281 if (ret) {
1282 ret = LTTNG_ERR_SAVE_IO_FAIL;
1283 goto end;
1284 }
1285 }
1286end:
1287 free(pids);
1288 return ret;
1289}
1290
fb198a11
JG
1291static
1292int save_domains(struct config_writer *writer, struct ltt_session *session)
1293{
1294 int ret = 0;
1295
1296 assert(writer);
1297 assert(session);
1298
1299 if (!session->kernel_session && !session->ust_session) {
1300 goto end;
1301 }
1302
1303 ret = config_writer_open_element(writer, config_element_domains);
1304 if (ret) {
1305 ret = LTTNG_ERR_SAVE_IO_FAIL;
1306 goto end;
1307 }
1308
1309
1310 if (session->kernel_session) {
1311 ret = config_writer_open_element(writer,
1312 config_element_domain);
1313 if (ret) {
1314 ret = LTTNG_ERR_SAVE_IO_FAIL;
1315 goto end;
1316 }
1317
1318 ret = save_kernel_session(writer, session);
1319 if (ret) {
1320 goto end;
1321 }
1322
847a5916
JR
1323 ret = config_writer_open_element(writer,
1324 config_element_trackers);
1325 if (ret) {
1326 ret = LTTNG_ERR_SAVE_IO_FAIL;
1327 goto end;
1328 }
1329
1330 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL);
1331 if (ret) {
1332 goto end;
1333 }
1334
1335 /* /trackers */
1336 ret = config_writer_close_element(writer);
1337 if (ret) {
1338 ret = LTTNG_ERR_SAVE_IO_FAIL;
1339 goto end;
1340 }
fb198a11
JG
1341 /* /domain */
1342 ret = config_writer_close_element(writer);
1343 if (ret) {
1344 ret = LTTNG_ERR_SAVE_IO_FAIL;
1345 goto end;
1346 }
1347 }
1348
1349 if (session->ust_session) {
65d72c41
JG
1350 unsigned long agent_count;
1351
fb198a11
JG
1352 ret = config_writer_open_element(writer,
1353 config_element_domain);
1354 if (ret) {
1355 ret = LTTNG_ERR_SAVE_IO_FAIL;
1356 goto end;
1357 }
1358
1359 ret = save_ust_session(writer, session, 0);
1360 if (ret) {
1361 goto end;
1362 }
1363
847a5916
JR
1364 ret = config_writer_open_element(writer,
1365 config_element_trackers);
1366 if (ret) {
1367 ret = LTTNG_ERR_SAVE_IO_FAIL;
1368 goto end;
1369 }
1370
1371 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST);
1372 if (ret) {
1373 goto end;
1374 }
1375
1376 /* /trackers */
1377 ret = config_writer_close_element(writer);
1378 if (ret) {
1379 ret = LTTNG_ERR_SAVE_IO_FAIL;
1380 goto end;
1381 }
fb198a11
JG
1382 /* /domain */
1383 ret = config_writer_close_element(writer);
1384 if (ret) {
1385 ret = LTTNG_ERR_SAVE_IO_FAIL;
1386 goto end;
1387 }
fb198a11 1388
65d72c41
JG
1389 rcu_read_lock();
1390 agent_count =
1391 lttng_ht_get_count(session->ust_session->agents);
1392 rcu_read_unlock();
fb198a11 1393
65d72c41
JG
1394 if (agent_count > 0) {
1395 ret = config_writer_open_element(writer,
1396 config_element_domain);
1397 if (ret) {
1398 ret = LTTNG_ERR_SAVE_IO_FAIL;
1399 goto end;
1400 }
fb198a11 1401
65d72c41
JG
1402 ret = save_ust_session(writer, session, 1);
1403 if (ret) {
1404 goto end;
1405 }
1406
1407 /* /domain */
1408 ret = config_writer_close_element(writer);
1409 if (ret) {
1410 ret = LTTNG_ERR_SAVE_IO_FAIL;
1411 goto end;
1412 }
fb198a11
JG
1413 }
1414 }
1415
1416 /* /domains */
1417 ret = config_writer_close_element(writer);
1418 if (ret) {
1419 ret = LTTNG_ERR_SAVE_IO_FAIL;
1420 goto end;
1421 }
1422end:
1423 return ret;
1424}
1425
1426static
1427int save_consumer_output(struct config_writer *writer,
1428 struct consumer_output *output)
1429{
1430 int ret;
1431
1432 assert(writer);
1433 assert(output);
1434
1435 ret = config_writer_open_element(writer, config_element_consumer_output);
1436 if (ret) {
1437 ret = LTTNG_ERR_SAVE_IO_FAIL;
1438 goto end;
1439 }
1440
1441 ret = config_writer_write_element_bool(writer, config_element_enabled,
1442 output->enabled);
1443 if (ret) {
1444 ret = LTTNG_ERR_SAVE_IO_FAIL;
1445 goto end;
1446 }
1447
1448 ret = config_writer_open_element(writer, config_element_destination);
1449 if (ret) {
1450 ret = LTTNG_ERR_SAVE_IO_FAIL;
1451 goto end;
1452 }
1453
1454 switch (output->type) {
1455 case CONSUMER_DST_LOCAL:
1456 ret = config_writer_write_element_string(writer,
1457 config_element_path, output->dst.trace_path);
1458 if (ret) {
1459 ret = LTTNG_ERR_SAVE_IO_FAIL;
1460 goto end;
1461 }
1462 break;
1463 case CONSUMER_DST_NET:
1464 {
1465 char *uri;
1466
1467 uri = zmalloc(PATH_MAX);
1468 if (!uri) {
1469 ret = LTTNG_ERR_NOMEM;
1470 goto end;
1471 }
1472
1473 ret = config_writer_open_element(writer, config_element_net_output);
1474 if (ret) {
1475 ret = LTTNG_ERR_SAVE_IO_FAIL;
1476 goto end_net_output;
1477 }
1478
1479 if (output->dst.net.control_isset &&
1480 output->dst.net.data_isset) {
1481 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1482 if (ret < 0) {
1483 ret = LTTNG_ERR_INVALID;
1484 goto end_net_output;
1485 }
1486
1487 ret = config_writer_write_element_string(writer,
1488 config_element_control_uri, uri);
1489 if (ret) {
1490 ret = LTTNG_ERR_SAVE_IO_FAIL;
1491 goto end_net_output;
1492 }
1493
1494 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1495 if (ret < 0) {
1496 ret = LTTNG_ERR_INVALID;
1497 goto end_net_output;
1498 }
1499
1500 ret = config_writer_write_element_string(writer,
1501 config_element_data_uri, uri);
1502 if (ret) {
1503 ret = LTTNG_ERR_SAVE_IO_FAIL;
1504 goto end_net_output;
1505 }
1506
1507end_net_output:
1508 free(uri);
1509 if (ret) {
1510 goto end;
1511 }
1512 } else {
1513 ret = !output->dst.net.control_isset ?
1514 LTTNG_ERR_URL_CTRL_MISS :
1515 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1516 free(uri);
fb198a11
JG
1517 goto end;
1518 }
1519
1520 ret = config_writer_close_element(writer);
1521 if (ret) {
1522 ret = LTTNG_ERR_SAVE_IO_FAIL;
1523 goto end;
1524 }
1525 break;
1526 }
1527 default:
1528 ERR("Unsupported consumer output type.");
1529 ret = LTTNG_ERR_INVALID;
1530 goto end;
1531 }
1532
1533 /* /destination */
1534 ret = config_writer_close_element(writer);
1535 if (ret) {
1536 ret = LTTNG_ERR_SAVE_IO_FAIL;
1537 goto end;
1538 }
1539
1540 /* /consumer_output */
1541 ret = config_writer_close_element(writer);
1542 if (ret) {
1543 ret = LTTNG_ERR_SAVE_IO_FAIL;
1544 goto end;
1545 }
1546end:
1547 return ret;
1548}
1549
1550static
1551int save_snapshot_outputs(struct config_writer *writer,
1552 struct snapshot *snapshot)
1553{
1554 int ret;
1555 struct lttng_ht_iter iter;
1556 struct snapshot_output *output;
1557
1558 assert(writer);
1559 assert(snapshot);
1560
1561 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1562 if (ret) {
1563 ret = LTTNG_ERR_SAVE_IO_FAIL;
1564 goto end;
1565 }
1566
1567 rcu_read_lock();
1568 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1569 node.node) {
1570 ret = config_writer_open_element(writer,
1571 config_element_output);
1572 if (ret) {
1573 ret = LTTNG_ERR_SAVE_IO_FAIL;
1574 goto end_unlock;
1575 }
1576
1577 ret = config_writer_write_element_string(writer,
1578 config_element_name, output->name);
1579 if (ret) {
1580 ret = LTTNG_ERR_SAVE_IO_FAIL;
1581 goto end_unlock;
1582 }
1583
1584 ret = config_writer_write_element_unsigned_int(writer,
1585 config_element_max_size, output->max_size);
1586 if (ret) {
1587 ret = LTTNG_ERR_SAVE_IO_FAIL;
1588 goto end_unlock;
1589 }
1590
1591 ret = save_consumer_output(writer, output->consumer);
1592 if (ret) {
1593 goto end_unlock;
1594 }
1595
1596 /* /output */
1597 ret = config_writer_close_element(writer);
1598 if (ret) {
1599 ret = LTTNG_ERR_SAVE_IO_FAIL;
1600 goto end_unlock;
1601 }
1602 }
1603 rcu_read_unlock();
1604
1605 /* /snapshot_outputs */
1606 ret = config_writer_close_element(writer);
1607 if (ret) {
1608 ret = LTTNG_ERR_SAVE_IO_FAIL;
1609 goto end;
1610 }
1611
1612end:
1613 return ret;
1614end_unlock:
1615 rcu_read_unlock();
1616 return ret;
1617}
1618
1619static
1620int save_session_output(struct config_writer *writer,
1621 struct ltt_session *session)
1622{
1623 int ret;
1624
1625 assert(writer);
1626 assert(session);
1627
1628 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1629 (!session->snapshot_mode && !session->consumer)) {
1630 /* Session is in no output mode */
1631 ret = 0;
1632 goto end;
1633 }
1634
1635 ret = config_writer_open_element(writer, config_element_output);
1636 if (ret) {
1637 ret = LTTNG_ERR_SAVE_IO_FAIL;
1638 goto end;
1639 }
1640
1641 if (session->snapshot_mode) {
1642 ret = save_snapshot_outputs(writer, &session->snapshot);
1643 if (ret) {
1644 goto end;
1645 }
1646 } else {
1647 if (session->consumer) {
1648 ret = save_consumer_output(writer, session->consumer);
1649 if (ret) {
1650 goto end;
1651 }
1652 }
1653 }
1654
1655 /* /output */
1656 ret = config_writer_close_element(writer);
1657 if (ret) {
1658 ret = LTTNG_ERR_SAVE_IO_FAIL;
1659 goto end;
1660 }
1661end:
1662 return ret;
1663}
1664
1665/*
1666 * Save the given session.
1667 *
1668 * Return 0 on success else a LTTNG_ERR* code.
1669 */
1670static
1671int save_session(struct ltt_session *session,
1672 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1673{
1674 int ret, fd;
db471218 1675 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
1676 char config_file_path[PATH_MAX];
1677 size_t len;
1678 struct config_writer *writer = NULL;
1679 size_t session_name_len;
1680 const char *provided_path;
1681
1682 assert(session);
1683 assert(attr);
1684 assert(creds);
1685
1686 session_name_len = strlen(session->name);
95a29ab8 1687 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
1688
1689 if (!session_access_ok(session,
1690 LTTNG_SOCK_GET_UID_CRED(creds),
1691 LTTNG_SOCK_GET_GID_CRED(creds))) {
1692 ret = LTTNG_ERR_EPERM;
1693 goto end;
1694 }
1695
1696 provided_path = lttng_save_session_attr_get_output_url(attr);
1697 if (provided_path) {
95a29ab8 1698 DBG3("Save session in provided path %s", provided_path);
fb198a11 1699 len = strlen(provided_path);
d2992717 1700 if (len >= sizeof(config_file_path)) {
fb198a11
JG
1701 ret = LTTNG_ERR_SET_URL;
1702 goto end;
1703 }
1704 strncpy(config_file_path, provided_path, len);
1705 } else {
7e078ad1 1706 ssize_t ret_len;
fb198a11
JG
1707 char *home_dir = utils_get_user_home_dir(
1708 LTTNG_SOCK_GET_UID_CRED(creds));
1709 if (!home_dir) {
1710 ret = LTTNG_ERR_SET_URL;
1711 goto end;
1712 }
1713
d2992717 1714 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
1715 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1716 free(home_dir);
7e078ad1 1717 if (ret_len < 0) {
fb198a11
JG
1718 PERROR("snprintf save session");
1719 ret = LTTNG_ERR_SET_URL;
1720 goto end;
1721 }
7e078ad1 1722 len = ret_len;
fb198a11
JG
1723 }
1724
1725 /*
d2992717
DG
1726 * Check the path fits in the config file path dst including the '/'
1727 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 1728 */
d2992717
DG
1729 if ((len + session_name_len + 2 +
1730 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1731 > sizeof(config_file_path)) {
fb198a11
JG
1732 ret = LTTNG_ERR_SET_URL;
1733 goto end;
1734 }
1735
1736 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1737 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1738 if (ret) {
1739 ret = LTTNG_ERR_SET_URL;
1740 goto end;
1741 }
1742
d2992717
DG
1743 /*
1744 * At this point, we know that everything fits in the buffer. Validation
1745 * was done just above.
1746 */
fb198a11
JG
1747 config_file_path[len++] = '/';
1748 strncpy(config_file_path + len, session->name, session_name_len);
1749 len += session_name_len;
1750 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
1751 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1752 config_file_path[len] = '\0';
fb198a11
JG
1753
1754 if (!access(config_file_path, F_OK) && !attr->overwrite) {
f9b57ab2
DG
1755 /* File exists, notify the user since the overwrite flag is off. */
1756 ret = LTTNG_ERR_SAVE_FILE_EXIST;
fb198a11
JG
1757 goto end;
1758 }
1759
1760 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1761 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1762 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1763 if (fd < 0) {
1764 PERROR("Could not create configuration file");
1765 ret = LTTNG_ERR_SAVE_IO_FAIL;
1766 goto end;
1767 }
db471218 1768 file_opened = 1;
fb198a11 1769
705bb62f 1770 writer = config_writer_create(fd, 1);
fb198a11
JG
1771 if (!writer) {
1772 ret = LTTNG_ERR_NOMEM;
1773 goto end;
1774 }
1775
1776 ret = config_writer_open_element(writer, config_element_sessions);
1777 if (ret) {
1778 ret = LTTNG_ERR_SAVE_IO_FAIL;
1779 goto end;
1780 }
1781
1782 ret = config_writer_open_element(writer, config_element_session);
1783 if (ret) {
1784 ret = LTTNG_ERR_SAVE_IO_FAIL;
1785 goto end;
1786 }
1787
1788 ret = config_writer_write_element_string(writer, config_element_name,
1789 session->name);
1790 if (ret) {
1791 ret = LTTNG_ERR_SAVE_IO_FAIL;
1792 goto end;
1793 }
1794
9e7c9f56
JR
1795 if(session->shm_path[0] != '\0') {
1796 ret = config_writer_write_element_string(writer,
1797 config_element_shared_memory_path,
1798 session->shm_path);
1799 if (ret) {
1800 ret = LTTNG_ERR_SAVE_IO_FAIL;
1801 goto end;
1802 }
1803 }
1804
fb198a11
JG
1805 ret = save_domains(writer, session);
1806 if (ret) {
1807 goto end;
1808 }
1809
1810 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 1811 session->active);
fb198a11
JG
1812 if (ret) {
1813 ret = LTTNG_ERR_SAVE_IO_FAIL;
1814 goto end;
1815 }
1816
1817 if (session->snapshot_mode || session->live_timer) {
1818 ret = config_writer_open_element(writer, config_element_attributes);
1819 if (ret) {
1820 ret = LTTNG_ERR_SAVE_IO_FAIL;
1821 goto end;
1822 }
1823
1824 if (session->snapshot_mode) {
1825 ret = config_writer_write_element_bool(writer,
1826 config_element_snapshot_mode, 1);
1827 if (ret) {
1828 ret = LTTNG_ERR_SAVE_IO_FAIL;
1829 goto end;
1830 }
1831 } else {
d98ad589 1832 ret = config_writer_write_element_unsigned_int(writer,
fb198a11
JG
1833 config_element_live_timer_interval, session->live_timer);
1834 if (ret) {
1835 ret = LTTNG_ERR_SAVE_IO_FAIL;
1836 goto end;
1837 }
1838 }
1839
1840 /* /attributes */
1841 ret = config_writer_close_element(writer);
1842 if (ret) {
1843 ret = LTTNG_ERR_SAVE_IO_FAIL;
1844 goto end;
1845 }
1846 }
1847
1848 ret = save_session_output(writer, session);
1849 if (ret) {
1850 goto end;
1851 }
1852
1853 /* /session */
1854 ret = config_writer_close_element(writer);
1855 if (ret) {
1856 ret = LTTNG_ERR_SAVE_IO_FAIL;
1857 goto end;
1858 }
1859
1860 /* /sessions */
1861 ret = config_writer_close_element(writer);
1862 if (ret) {
1863 ret = LTTNG_ERR_SAVE_IO_FAIL;
1864 goto end;
1865 }
1866end:
1867 if (writer && config_writer_destroy(writer)) {
1868 /* Preserve the original error code */
1869 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1870 }
1871 if (ret) {
1872 /* Delete file in case of error */
db471218 1873 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
1874 PERROR("Unlinking XML session configuration.");
1875 }
1876 }
1877
1878 return ret;
1879}
1880
1881int cmd_save_sessions(struct lttng_save_session_attr *attr,
1882 lttng_sock_cred *creds)
1883{
1884 int ret;
1885 const char *session_name;
1886 struct ltt_session *session;
1887
1888 session_lock_list();
1889
1890 session_name = lttng_save_session_attr_get_session_name(attr);
1891 if (session_name) {
1892 session = session_find_by_name(session_name);
1893 if (!session) {
1894 ret = LTTNG_ERR_SESS_NOT_FOUND;
1895 goto end;
1896 }
1897
1898 session_lock(session);
1899 ret = save_session(session, attr, creds);
1900 session_unlock(session);
1901 if (ret) {
1902 goto end;
1903 }
1904 } else {
1905 struct ltt_session_list *list = session_get_list();
1906
1907 cds_list_for_each_entry(session, &list->head, list) {
1908 session_lock(session);
1909 ret = save_session(session, attr, creds);
1910 session_unlock(session);
1911
1912 /* Don't abort if we don't have the required permissions. */
1913 if (ret && ret != LTTNG_ERR_EPERM) {
1914 goto end;
1915 }
1916 }
1917 }
1918 ret = LTTNG_OK;
1919
1920end:
1921 session_unlock_list();
1922 return ret;
1923}
This page took 0.171996 seconds and 4 git commands to generate.