Fix: HT must not be destroyed with a rcu_read_lock held
[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
2aa64052
JG
804 if (cds_list_empty(&kchan->ctx_list)) {
805 ret = 0;
806 goto end;
807 }
808
645328ae
DG
809 ret = config_writer_open_element(writer, config_element_contexts);
810 if (ret) {
811 ret = LTTNG_ERR_SAVE_IO_FAIL;
812 goto end;
813 }
814
815 cds_list_for_each_entry(ctx, &kchan->ctx_list, list) {
816 ret = save_kernel_context(writer, &ctx->ctx);
817 if (ret) {
818 goto end;
819 }
820 }
821
fb198a11
JG
822 /* /contexts */
823 ret = config_writer_close_element(writer);
824 if (ret) {
825 ret = LTTNG_ERR_SAVE_IO_FAIL;
826 goto end;
827 }
828end:
829 return ret;
830}
831
832static
833int save_ust_context(struct config_writer *writer,
834 struct cds_list_head *ctx_list)
835{
836 int ret;
837 struct ltt_ust_context *ctx;
838
839 assert(writer);
840 assert(ctx_list);
841
842 ret = config_writer_open_element(writer, config_element_contexts);
843 if (ret) {
844 ret = LTTNG_ERR_SAVE_IO_FAIL;
845 goto end;
846 }
847
848 cds_list_for_each_entry(ctx, ctx_list, list) {
849 const char *context_type_string;
850
fb198a11
JG
851
852 ret = config_writer_open_element(writer,
853 config_element_context);
854 if (ret) {
855 ret = LTTNG_ERR_SAVE_IO_FAIL;
856 goto end;
857 }
858
14ce5bd8
JG
859 if (ctx->ctx.ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) {
860 /* Perf contexts are saved as event_perf_context_type */
861 ret = config_writer_open_element(writer,
862 config_element_perf);
863 if (ret) {
864 ret = LTTNG_ERR_SAVE_IO_FAIL;
865 goto end;
866 }
867
868 ret = config_writer_write_element_unsigned_int(writer,
869 config_element_type,
870 ctx->ctx.u.perf_counter.type);
871 if (ret) {
872 ret = LTTNG_ERR_SAVE_IO_FAIL;
873 goto end;
874 }
875
876 ret = config_writer_write_element_unsigned_int(writer,
877 config_element_config,
878 ctx->ctx.u.perf_counter.config);
879 if (ret) {
880 ret = LTTNG_ERR_SAVE_IO_FAIL;
881 goto end;
882 }
883
884 ret = config_writer_write_element_string(writer,
885 config_element_name,
886 ctx->ctx.u.perf_counter.name);
887 if (ret) {
888 ret = LTTNG_ERR_SAVE_IO_FAIL;
889 goto end;
890 }
891
892 /* /perf */
893 ret = config_writer_close_element(writer);
894 if (ret) {
895 ret = LTTNG_ERR_SAVE_IO_FAIL;
896 goto end;
897 }
898 } else {
899 /* Save context as event_context_type_type */
900 context_type_string = get_ust_context_type_string(
901 ctx->ctx.ctx);
902 if (!context_type_string) {
903 ERR("Unsupported UST context type.")
904 ret = LTTNG_ERR_INVALID;
905 goto end;
906 }
907
908 ret = config_writer_write_element_string(writer,
909 config_element_type, context_type_string);
910 if (ret) {
911 ret = LTTNG_ERR_SAVE_IO_FAIL;
912 goto end;
913 }
fb198a11
JG
914 }
915
916 /* /context */
917 ret = config_writer_close_element(writer);
918 if (ret) {
919 ret = LTTNG_ERR_SAVE_IO_FAIL;
920 goto end;
921 }
922 }
923
924 /* /contexts */
925 ret = config_writer_close_element(writer);
926 if (ret) {
927 ret = LTTNG_ERR_SAVE_IO_FAIL;
928 goto end;
929 }
930end:
931 return ret;
932}
933
934static
935int save_kernel_channel(struct config_writer *writer,
936 struct ltt_kernel_channel *kchan)
937{
938 int ret;
939
940 assert(writer);
941 assert(kchan);
942
943 ret = config_writer_open_element(writer, config_element_channel);
944 if (ret) {
945 ret = LTTNG_ERR_SAVE_IO_FAIL;
946 goto end;
947 }
948
949 ret = config_writer_write_element_string(writer, config_element_name,
950 kchan->channel->name);
951 if (ret) {
952 ret = LTTNG_ERR_SAVE_IO_FAIL;
953 goto end;
954 }
955
956 ret = config_writer_write_element_bool(writer, config_element_enabled,
957 kchan->channel->enabled);
958 if (ret) {
959 ret = LTTNG_ERR_SAVE_IO_FAIL;
960 goto end;
961 }
962
963 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
964 if (ret) {
965 goto end;
966 }
967
0de3eda1 968 ret = save_kernel_events(writer, kchan);
fb198a11
JG
969 if (ret) {
970 goto end;
971 }
972
645328ae 973 ret = save_kernel_contexts(writer, kchan);
fb198a11
JG
974 if (ret) {
975 goto end;
976 }
977
978 /* /channel */
979 ret = config_writer_close_element(writer);
980 if (ret) {
981 ret = LTTNG_ERR_SAVE_IO_FAIL;
982 goto end;
983 }
984end:
985 return ret;
986}
987
988static
989int save_ust_channel(struct config_writer *writer,
990 struct ltt_ust_channel *ust_chan,
991 struct ltt_ust_session *session)
992{
993 int ret;
994
995 assert(writer);
996 assert(ust_chan);
997 assert(session);
998
999 ret = config_writer_open_element(writer, config_element_channel);
1000 if (ret) {
1001 ret = LTTNG_ERR_SAVE_IO_FAIL;
1002 goto end;
1003 }
1004
1005 ret = config_writer_write_element_string(writer, config_element_name,
1006 ust_chan->name);
1007 if (ret) {
1008 ret = LTTNG_ERR_SAVE_IO_FAIL;
1009 goto end;
1010 }
1011
1012 ret = config_writer_write_element_bool(writer, config_element_enabled,
1013 ust_chan->enabled);
1014 if (ret) {
1015 ret = LTTNG_ERR_SAVE_IO_FAIL;
1016 goto end;
1017 }
1018
1019 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
1020 if (ret) {
1021 goto end;
1022 }
1023
1024 ret = config_writer_write_element_unsigned_int(writer,
1025 config_element_tracefile_size, ust_chan->tracefile_size);
1026 if (ret) {
1027 ret = LTTNG_ERR_SAVE_IO_FAIL;
1028 goto end;
1029 }
1030
1031 ret = config_writer_write_element_unsigned_int(writer,
1032 config_element_tracefile_count, ust_chan->tracefile_count);
1033 if (ret) {
1034 ret = LTTNG_ERR_SAVE_IO_FAIL;
1035 goto end;
1036 }
1037
1038 ret = config_writer_write_element_unsigned_int(writer,
1039 config_element_live_timer_interval,
1040 session->live_timer_interval);
1041 if (ret) {
1042 ret = LTTNG_ERR_SAVE_IO_FAIL;
1043 goto end;
1044 }
1045
1046 ret = save_ust_events(writer, ust_chan->events);
1047 if (ret) {
1048 ret = LTTNG_ERR_SAVE_IO_FAIL;
1049 goto end;
1050 }
1051
1052 ret = save_ust_context(writer, &ust_chan->ctx_list);
1053 if (ret) {
1054 goto end;
1055 }
1056
1057 /* /channel */
1058 ret = config_writer_close_element(writer);
1059 if (ret) {
1060 ret = LTTNG_ERR_SAVE_IO_FAIL;
1061 goto end;
1062 }
1063end:
1064 return ret;
1065}
1066
1067static
1068int save_kernel_session(struct config_writer *writer,
1069 struct ltt_session *session)
1070{
1071 int ret;
1072 struct ltt_kernel_channel *kchan;
1073
1074 assert(writer);
1075 assert(session);
1076
1077 ret = config_writer_write_element_string(writer, config_element_type,
1078 config_domain_type_kernel);
1079 if (ret) {
1080 ret = LTTNG_ERR_SAVE_IO_FAIL;
1081 goto end;
1082 }
1083
1084 ret = config_writer_write_element_string(writer,
1085 config_element_buffer_type, config_buffer_type_global);
1086 if (ret) {
1087 ret = LTTNG_ERR_SAVE_IO_FAIL;
1088 goto end;
1089 }
1090
1091 ret = config_writer_open_element(writer,
1092 config_element_channels);
1093 if (ret) {
1094 ret = LTTNG_ERR_SAVE_IO_FAIL;
1095 goto end;
1096 }
1097
1098 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
1099 list) {
1100 ret = save_kernel_channel(writer, kchan);
1101 if (ret) {
1102 goto end;
1103 }
1104 }
1105
1106 /* /channels */
1107 ret = config_writer_close_element(writer);
1108 if (ret) {
1109 ret = LTTNG_ERR_SAVE_IO_FAIL;
1110 goto end;
1111 }
1112end:
1113 return ret;
1114}
1115
1116static
1117int save_ust_session(struct config_writer *writer,
022d91ba 1118 struct ltt_session *session, int save_agent)
fb198a11
JG
1119{
1120 int ret;
1121 struct ltt_ust_channel *ust_chan;
1122 const char *buffer_type_string;
1123 struct lttng_ht_node_str *node;
1124 struct lttng_ht_iter iter;
1125
1126 assert(writer);
1127 assert(session);
1128
1129 ret = config_writer_write_element_string(writer, config_element_type,
022d91ba 1130 save_agent ? config_domain_type_jul : config_domain_type_ust);
fb198a11
JG
1131 if (ret) {
1132 ret = LTTNG_ERR_SAVE_IO_FAIL;
1133 goto end;
1134 }
1135
1136 buffer_type_string = get_buffer_type_string(
1137 session->ust_session->buffer_type);
1138 if (!buffer_type_string) {
1139 ERR("Unsupported buffer type.");
1140 ret = LTTNG_ERR_INVALID;
1141 goto end;
1142 }
1143
1144 ret = config_writer_write_element_string(writer,
1145 config_element_buffer_type, buffer_type_string);
1146 if (ret) {
1147 ret = LTTNG_ERR_SAVE_IO_FAIL;
1148 goto end;
1149 }
1150
1151 ret = config_writer_open_element(writer, config_element_channels);
1152 if (ret) {
1153 ret = LTTNG_ERR_SAVE_IO_FAIL;
1154 goto end;
1155 }
1156
1157 rcu_read_lock();
1158 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1159 &iter.iter, node, node) {
022d91ba 1160 int agent_channel;
fb198a11
JG
1161
1162 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
da6c3a50 1163 agent_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name) ||
0e115563
DG
1164 !strcmp(DEFAULT_LOG4J_CHANNEL_NAME, ust_chan->name) ||
1165 !strcmp(DEFAULT_PYTHON_CHANNEL_NAME, ust_chan->name);
022d91ba 1166 if (!(save_agent ^ agent_channel)) {
fb198a11
JG
1167 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1168 if (ret) {
1169 rcu_read_unlock();
1170 goto end;
1171 }
1172 }
1173 }
1174 rcu_read_unlock();
1175
1176 /* /channels */
1177 ret = config_writer_close_element(writer);
1178 if (ret) {
1179 ret = LTTNG_ERR_SAVE_IO_FAIL;
1180 goto end;
1181 }
1182end:
1183 return ret;
1184}
1185
1186static
1187int save_domains(struct config_writer *writer, struct ltt_session *session)
1188{
1189 int ret = 0;
1190
1191 assert(writer);
1192 assert(session);
1193
1194 if (!session->kernel_session && !session->ust_session) {
1195 goto end;
1196 }
1197
1198 ret = config_writer_open_element(writer, config_element_domains);
1199 if (ret) {
1200 ret = LTTNG_ERR_SAVE_IO_FAIL;
1201 goto end;
1202 }
1203
1204
1205 if (session->kernel_session) {
1206 ret = config_writer_open_element(writer,
1207 config_element_domain);
1208 if (ret) {
1209 ret = LTTNG_ERR_SAVE_IO_FAIL;
1210 goto end;
1211 }
1212
1213 ret = save_kernel_session(writer, session);
1214 if (ret) {
1215 goto end;
1216 }
1217
1218 /* /domain */
1219 ret = config_writer_close_element(writer);
1220 if (ret) {
1221 ret = LTTNG_ERR_SAVE_IO_FAIL;
1222 goto end;
1223 }
1224 }
1225
1226 if (session->ust_session) {
1227 ret = config_writer_open_element(writer,
1228 config_element_domain);
1229 if (ret) {
1230 ret = LTTNG_ERR_SAVE_IO_FAIL;
1231 goto end;
1232 }
1233
1234 ret = save_ust_session(writer, session, 0);
1235 if (ret) {
1236 goto end;
1237 }
1238
1239 /* /domain */
1240 ret = config_writer_close_element(writer);
1241 if (ret) {
1242 ret = LTTNG_ERR_SAVE_IO_FAIL;
1243 goto end;
1244 }
1245 }
1246
1247 if (session->ust_session &&
fefd409b 1248 lttng_ht_get_count(session->ust_session->agents) > 0) {
fb198a11
JG
1249 ret = config_writer_open_element(writer,
1250 config_element_domain);
1251 if (ret) {
1252 ret = LTTNG_ERR_SAVE_IO_FAIL;
1253 goto end;
1254 }
1255
1256 ret = save_ust_session(writer, session, 1);
1257 if (ret) {
1258 goto end;
1259 }
1260
1261 /* /domain */
1262 ret = config_writer_close_element(writer);
1263 if (ret) {
1264 ret = LTTNG_ERR_SAVE_IO_FAIL;
1265 goto end;
1266 }
1267 }
1268
1269 /* /domains */
1270 ret = config_writer_close_element(writer);
1271 if (ret) {
1272 ret = LTTNG_ERR_SAVE_IO_FAIL;
1273 goto end;
1274 }
1275end:
1276 return ret;
1277}
1278
1279static
1280int save_consumer_output(struct config_writer *writer,
1281 struct consumer_output *output)
1282{
1283 int ret;
1284
1285 assert(writer);
1286 assert(output);
1287
1288 ret = config_writer_open_element(writer, config_element_consumer_output);
1289 if (ret) {
1290 ret = LTTNG_ERR_SAVE_IO_FAIL;
1291 goto end;
1292 }
1293
1294 ret = config_writer_write_element_bool(writer, config_element_enabled,
1295 output->enabled);
1296 if (ret) {
1297 ret = LTTNG_ERR_SAVE_IO_FAIL;
1298 goto end;
1299 }
1300
1301 ret = config_writer_open_element(writer, config_element_destination);
1302 if (ret) {
1303 ret = LTTNG_ERR_SAVE_IO_FAIL;
1304 goto end;
1305 }
1306
1307 switch (output->type) {
1308 case CONSUMER_DST_LOCAL:
1309 ret = config_writer_write_element_string(writer,
1310 config_element_path, output->dst.trace_path);
1311 if (ret) {
1312 ret = LTTNG_ERR_SAVE_IO_FAIL;
1313 goto end;
1314 }
1315 break;
1316 case CONSUMER_DST_NET:
1317 {
1318 char *uri;
1319
1320 uri = zmalloc(PATH_MAX);
1321 if (!uri) {
1322 ret = LTTNG_ERR_NOMEM;
1323 goto end;
1324 }
1325
1326 ret = config_writer_open_element(writer, config_element_net_output);
1327 if (ret) {
1328 ret = LTTNG_ERR_SAVE_IO_FAIL;
1329 goto end_net_output;
1330 }
1331
1332 if (output->dst.net.control_isset &&
1333 output->dst.net.data_isset) {
1334 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1335 if (ret < 0) {
1336 ret = LTTNG_ERR_INVALID;
1337 goto end_net_output;
1338 }
1339
1340 ret = config_writer_write_element_string(writer,
1341 config_element_control_uri, uri);
1342 if (ret) {
1343 ret = LTTNG_ERR_SAVE_IO_FAIL;
1344 goto end_net_output;
1345 }
1346
1347 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1348 if (ret < 0) {
1349 ret = LTTNG_ERR_INVALID;
1350 goto end_net_output;
1351 }
1352
1353 ret = config_writer_write_element_string(writer,
1354 config_element_data_uri, uri);
1355 if (ret) {
1356 ret = LTTNG_ERR_SAVE_IO_FAIL;
1357 goto end_net_output;
1358 }
1359
1360end_net_output:
1361 free(uri);
1362 if (ret) {
1363 goto end;
1364 }
1365 } else {
1366 ret = !output->dst.net.control_isset ?
1367 LTTNG_ERR_URL_CTRL_MISS :
1368 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1369 free(uri);
fb198a11
JG
1370 goto end;
1371 }
1372
1373 ret = config_writer_close_element(writer);
1374 if (ret) {
1375 ret = LTTNG_ERR_SAVE_IO_FAIL;
1376 goto end;
1377 }
1378 break;
1379 }
1380 default:
1381 ERR("Unsupported consumer output type.");
1382 ret = LTTNG_ERR_INVALID;
1383 goto end;
1384 }
1385
1386 /* /destination */
1387 ret = config_writer_close_element(writer);
1388 if (ret) {
1389 ret = LTTNG_ERR_SAVE_IO_FAIL;
1390 goto end;
1391 }
1392
1393 /* /consumer_output */
1394 ret = config_writer_close_element(writer);
1395 if (ret) {
1396 ret = LTTNG_ERR_SAVE_IO_FAIL;
1397 goto end;
1398 }
1399end:
1400 return ret;
1401}
1402
1403static
1404int save_snapshot_outputs(struct config_writer *writer,
1405 struct snapshot *snapshot)
1406{
1407 int ret;
1408 struct lttng_ht_iter iter;
1409 struct snapshot_output *output;
1410
1411 assert(writer);
1412 assert(snapshot);
1413
1414 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1415 if (ret) {
1416 ret = LTTNG_ERR_SAVE_IO_FAIL;
1417 goto end;
1418 }
1419
1420 rcu_read_lock();
1421 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1422 node.node) {
1423 ret = config_writer_open_element(writer,
1424 config_element_output);
1425 if (ret) {
1426 ret = LTTNG_ERR_SAVE_IO_FAIL;
1427 goto end_unlock;
1428 }
1429
1430 ret = config_writer_write_element_string(writer,
1431 config_element_name, output->name);
1432 if (ret) {
1433 ret = LTTNG_ERR_SAVE_IO_FAIL;
1434 goto end_unlock;
1435 }
1436
1437 ret = config_writer_write_element_unsigned_int(writer,
1438 config_element_max_size, output->max_size);
1439 if (ret) {
1440 ret = LTTNG_ERR_SAVE_IO_FAIL;
1441 goto end_unlock;
1442 }
1443
1444 ret = save_consumer_output(writer, output->consumer);
1445 if (ret) {
1446 goto end_unlock;
1447 }
1448
1449 /* /output */
1450 ret = config_writer_close_element(writer);
1451 if (ret) {
1452 ret = LTTNG_ERR_SAVE_IO_FAIL;
1453 goto end_unlock;
1454 }
1455 }
1456 rcu_read_unlock();
1457
1458 /* /snapshot_outputs */
1459 ret = config_writer_close_element(writer);
1460 if (ret) {
1461 ret = LTTNG_ERR_SAVE_IO_FAIL;
1462 goto end;
1463 }
1464
1465end:
1466 return ret;
1467end_unlock:
1468 rcu_read_unlock();
1469 return ret;
1470}
1471
1472static
1473int save_session_output(struct config_writer *writer,
1474 struct ltt_session *session)
1475{
1476 int ret;
1477
1478 assert(writer);
1479 assert(session);
1480
1481 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1482 (!session->snapshot_mode && !session->consumer)) {
1483 /* Session is in no output mode */
1484 ret = 0;
1485 goto end;
1486 }
1487
1488 ret = config_writer_open_element(writer, config_element_output);
1489 if (ret) {
1490 ret = LTTNG_ERR_SAVE_IO_FAIL;
1491 goto end;
1492 }
1493
1494 if (session->snapshot_mode) {
1495 ret = save_snapshot_outputs(writer, &session->snapshot);
1496 if (ret) {
1497 goto end;
1498 }
1499 } else {
1500 if (session->consumer) {
1501 ret = save_consumer_output(writer, session->consumer);
1502 if (ret) {
1503 goto end;
1504 }
1505 }
1506 }
1507
1508 /* /output */
1509 ret = config_writer_close_element(writer);
1510 if (ret) {
1511 ret = LTTNG_ERR_SAVE_IO_FAIL;
1512 goto end;
1513 }
1514end:
1515 return ret;
1516}
1517
1518/*
1519 * Save the given session.
1520 *
1521 * Return 0 on success else a LTTNG_ERR* code.
1522 */
1523static
1524int save_session(struct ltt_session *session,
1525 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1526{
1527 int ret, fd;
db471218 1528 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
1529 char config_file_path[PATH_MAX];
1530 size_t len;
1531 struct config_writer *writer = NULL;
1532 size_t session_name_len;
1533 const char *provided_path;
1534
1535 assert(session);
1536 assert(attr);
1537 assert(creds);
1538
1539 session_name_len = strlen(session->name);
95a29ab8 1540 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
1541
1542 if (!session_access_ok(session,
1543 LTTNG_SOCK_GET_UID_CRED(creds),
1544 LTTNG_SOCK_GET_GID_CRED(creds))) {
1545 ret = LTTNG_ERR_EPERM;
1546 goto end;
1547 }
1548
1549 provided_path = lttng_save_session_attr_get_output_url(attr);
1550 if (provided_path) {
95a29ab8 1551 DBG3("Save session in provided path %s", provided_path);
fb198a11 1552 len = strlen(provided_path);
d2992717 1553 if (len >= sizeof(config_file_path)) {
fb198a11
JG
1554 ret = LTTNG_ERR_SET_URL;
1555 goto end;
1556 }
1557 strncpy(config_file_path, provided_path, len);
1558 } else {
7e078ad1 1559 ssize_t ret_len;
fb198a11
JG
1560 char *home_dir = utils_get_user_home_dir(
1561 LTTNG_SOCK_GET_UID_CRED(creds));
1562 if (!home_dir) {
1563 ret = LTTNG_ERR_SET_URL;
1564 goto end;
1565 }
1566
d2992717 1567 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
1568 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1569 free(home_dir);
7e078ad1 1570 if (ret_len < 0) {
fb198a11
JG
1571 PERROR("snprintf save session");
1572 ret = LTTNG_ERR_SET_URL;
1573 goto end;
1574 }
7e078ad1 1575 len = ret_len;
fb198a11
JG
1576 }
1577
1578 /*
d2992717
DG
1579 * Check the path fits in the config file path dst including the '/'
1580 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 1581 */
d2992717
DG
1582 if ((len + session_name_len + 2 +
1583 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1584 > sizeof(config_file_path)) {
fb198a11
JG
1585 ret = LTTNG_ERR_SET_URL;
1586 goto end;
1587 }
1588
1589 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1590 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1591 if (ret) {
1592 ret = LTTNG_ERR_SET_URL;
1593 goto end;
1594 }
1595
d2992717
DG
1596 /*
1597 * At this point, we know that everything fits in the buffer. Validation
1598 * was done just above.
1599 */
fb198a11
JG
1600 config_file_path[len++] = '/';
1601 strncpy(config_file_path + len, session->name, session_name_len);
1602 len += session_name_len;
1603 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
1604 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1605 config_file_path[len] = '\0';
fb198a11
JG
1606
1607 if (!access(config_file_path, F_OK) && !attr->overwrite) {
f9b57ab2
DG
1608 /* File exists, notify the user since the overwrite flag is off. */
1609 ret = LTTNG_ERR_SAVE_FILE_EXIST;
fb198a11
JG
1610 goto end;
1611 }
1612
1613 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1614 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1615 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1616 if (fd < 0) {
1617 PERROR("Could not create configuration file");
1618 ret = LTTNG_ERR_SAVE_IO_FAIL;
1619 goto end;
1620 }
db471218 1621 file_opened = 1;
fb198a11 1622
705bb62f 1623 writer = config_writer_create(fd, 1);
fb198a11
JG
1624 if (!writer) {
1625 ret = LTTNG_ERR_NOMEM;
1626 goto end;
1627 }
1628
1629 ret = config_writer_open_element(writer, config_element_sessions);
1630 if (ret) {
1631 ret = LTTNG_ERR_SAVE_IO_FAIL;
1632 goto end;
1633 }
1634
1635 ret = config_writer_open_element(writer, config_element_session);
1636 if (ret) {
1637 ret = LTTNG_ERR_SAVE_IO_FAIL;
1638 goto end;
1639 }
1640
1641 ret = config_writer_write_element_string(writer, config_element_name,
1642 session->name);
1643 if (ret) {
1644 ret = LTTNG_ERR_SAVE_IO_FAIL;
1645 goto end;
1646 }
1647
1648 ret = save_domains(writer, session);
1649 if (ret) {
1650 goto end;
1651 }
1652
1653 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 1654 session->active);
fb198a11
JG
1655 if (ret) {
1656 ret = LTTNG_ERR_SAVE_IO_FAIL;
1657 goto end;
1658 }
1659
1660 if (session->snapshot_mode || session->live_timer) {
1661 ret = config_writer_open_element(writer, config_element_attributes);
1662 if (ret) {
1663 ret = LTTNG_ERR_SAVE_IO_FAIL;
1664 goto end;
1665 }
1666
1667 if (session->snapshot_mode) {
1668 ret = config_writer_write_element_bool(writer,
1669 config_element_snapshot_mode, 1);
1670 if (ret) {
1671 ret = LTTNG_ERR_SAVE_IO_FAIL;
1672 goto end;
1673 }
1674 } else {
d98ad589 1675 ret = config_writer_write_element_unsigned_int(writer,
fb198a11
JG
1676 config_element_live_timer_interval, session->live_timer);
1677 if (ret) {
1678 ret = LTTNG_ERR_SAVE_IO_FAIL;
1679 goto end;
1680 }
1681 }
1682
1683 /* /attributes */
1684 ret = config_writer_close_element(writer);
1685 if (ret) {
1686 ret = LTTNG_ERR_SAVE_IO_FAIL;
1687 goto end;
1688 }
1689 }
1690
1691 ret = save_session_output(writer, session);
1692 if (ret) {
1693 goto end;
1694 }
1695
1696 /* /session */
1697 ret = config_writer_close_element(writer);
1698 if (ret) {
1699 ret = LTTNG_ERR_SAVE_IO_FAIL;
1700 goto end;
1701 }
1702
1703 /* /sessions */
1704 ret = config_writer_close_element(writer);
1705 if (ret) {
1706 ret = LTTNG_ERR_SAVE_IO_FAIL;
1707 goto end;
1708 }
1709end:
1710 if (writer && config_writer_destroy(writer)) {
1711 /* Preserve the original error code */
1712 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1713 }
1714 if (ret) {
1715 /* Delete file in case of error */
db471218 1716 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
1717 PERROR("Unlinking XML session configuration.");
1718 }
1719 }
1720
1721 return ret;
1722}
1723
1724int cmd_save_sessions(struct lttng_save_session_attr *attr,
1725 lttng_sock_cred *creds)
1726{
1727 int ret;
1728 const char *session_name;
1729 struct ltt_session *session;
1730
1731 session_lock_list();
1732
1733 session_name = lttng_save_session_attr_get_session_name(attr);
1734 if (session_name) {
1735 session = session_find_by_name(session_name);
1736 if (!session) {
1737 ret = LTTNG_ERR_SESS_NOT_FOUND;
1738 goto end;
1739 }
1740
1741 session_lock(session);
1742 ret = save_session(session, attr, creds);
1743 session_unlock(session);
1744 if (ret) {
1745 goto end;
1746 }
1747 } else {
1748 struct ltt_session_list *list = session_get_list();
1749
1750 cds_list_for_each_entry(session, &list->head, list) {
1751 session_lock(session);
1752 ret = save_session(session, attr, creds);
1753 session_unlock(session);
1754
1755 /* Don't abort if we don't have the required permissions. */
1756 if (ret && ret != LTTNG_ERR_EPERM) {
1757 goto end;
1758 }
1759 }
1760 }
1761 ret = LTTNG_OK;
1762
1763end:
1764 session_unlock_list();
1765 return ret;
1766}
This page took 0.096901 seconds and 4 git commands to generate.