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