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