c6fc33e7bb83c5b02b6fdc7c4c8b38517d5f9aea
[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 unsigned long agent_count;
1229
1230 ret = config_writer_open_element(writer,
1231 config_element_domain);
1232 if (ret) {
1233 ret = LTTNG_ERR_SAVE_IO_FAIL;
1234 goto end;
1235 }
1236
1237 ret = save_ust_session(writer, session, 0);
1238 if (ret) {
1239 goto end;
1240 }
1241
1242 /* /domain */
1243 ret = config_writer_close_element(writer);
1244 if (ret) {
1245 ret = LTTNG_ERR_SAVE_IO_FAIL;
1246 goto end;
1247 }
1248
1249 rcu_read_lock();
1250 agent_count =
1251 lttng_ht_get_count(session->ust_session->agents);
1252 rcu_read_unlock();
1253
1254 if (agent_count > 0) {
1255 ret = config_writer_open_element(writer,
1256 config_element_domain);
1257 if (ret) {
1258 ret = LTTNG_ERR_SAVE_IO_FAIL;
1259 goto end;
1260 }
1261
1262 ret = save_ust_session(writer, session, 1);
1263 if (ret) {
1264 goto end;
1265 }
1266
1267 /* /domain */
1268 ret = config_writer_close_element(writer);
1269 if (ret) {
1270 ret = LTTNG_ERR_SAVE_IO_FAIL;
1271 goto end;
1272 }
1273 }
1274 }
1275
1276 if (session->ust_session) {
1277 }
1278
1279 /* /domains */
1280 ret = config_writer_close_element(writer);
1281 if (ret) {
1282 ret = LTTNG_ERR_SAVE_IO_FAIL;
1283 goto end;
1284 }
1285 end:
1286 return ret;
1287 }
1288
1289 static
1290 int save_consumer_output(struct config_writer *writer,
1291 struct consumer_output *output)
1292 {
1293 int ret;
1294
1295 assert(writer);
1296 assert(output);
1297
1298 ret = config_writer_open_element(writer, config_element_consumer_output);
1299 if (ret) {
1300 ret = LTTNG_ERR_SAVE_IO_FAIL;
1301 goto end;
1302 }
1303
1304 ret = config_writer_write_element_bool(writer, config_element_enabled,
1305 output->enabled);
1306 if (ret) {
1307 ret = LTTNG_ERR_SAVE_IO_FAIL;
1308 goto end;
1309 }
1310
1311 ret = config_writer_open_element(writer, config_element_destination);
1312 if (ret) {
1313 ret = LTTNG_ERR_SAVE_IO_FAIL;
1314 goto end;
1315 }
1316
1317 switch (output->type) {
1318 case CONSUMER_DST_LOCAL:
1319 ret = config_writer_write_element_string(writer,
1320 config_element_path, output->dst.trace_path);
1321 if (ret) {
1322 ret = LTTNG_ERR_SAVE_IO_FAIL;
1323 goto end;
1324 }
1325 break;
1326 case CONSUMER_DST_NET:
1327 {
1328 char *uri;
1329
1330 uri = zmalloc(PATH_MAX);
1331 if (!uri) {
1332 ret = LTTNG_ERR_NOMEM;
1333 goto end;
1334 }
1335
1336 ret = config_writer_open_element(writer, config_element_net_output);
1337 if (ret) {
1338 ret = LTTNG_ERR_SAVE_IO_FAIL;
1339 goto end_net_output;
1340 }
1341
1342 if (output->dst.net.control_isset &&
1343 output->dst.net.data_isset) {
1344 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1345 if (ret < 0) {
1346 ret = LTTNG_ERR_INVALID;
1347 goto end_net_output;
1348 }
1349
1350 ret = config_writer_write_element_string(writer,
1351 config_element_control_uri, uri);
1352 if (ret) {
1353 ret = LTTNG_ERR_SAVE_IO_FAIL;
1354 goto end_net_output;
1355 }
1356
1357 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1358 if (ret < 0) {
1359 ret = LTTNG_ERR_INVALID;
1360 goto end_net_output;
1361 }
1362
1363 ret = config_writer_write_element_string(writer,
1364 config_element_data_uri, uri);
1365 if (ret) {
1366 ret = LTTNG_ERR_SAVE_IO_FAIL;
1367 goto end_net_output;
1368 }
1369
1370 end_net_output:
1371 free(uri);
1372 if (ret) {
1373 goto end;
1374 }
1375 } else {
1376 ret = !output->dst.net.control_isset ?
1377 LTTNG_ERR_URL_CTRL_MISS :
1378 LTTNG_ERR_URL_DATA_MISS;
1379 free(uri);
1380 goto end;
1381 }
1382
1383 ret = config_writer_close_element(writer);
1384 if (ret) {
1385 ret = LTTNG_ERR_SAVE_IO_FAIL;
1386 goto end;
1387 }
1388 break;
1389 }
1390 default:
1391 ERR("Unsupported consumer output type.");
1392 ret = LTTNG_ERR_INVALID;
1393 goto end;
1394 }
1395
1396 /* /destination */
1397 ret = config_writer_close_element(writer);
1398 if (ret) {
1399 ret = LTTNG_ERR_SAVE_IO_FAIL;
1400 goto end;
1401 }
1402
1403 /* /consumer_output */
1404 ret = config_writer_close_element(writer);
1405 if (ret) {
1406 ret = LTTNG_ERR_SAVE_IO_FAIL;
1407 goto end;
1408 }
1409 end:
1410 return ret;
1411 }
1412
1413 static
1414 int save_snapshot_outputs(struct config_writer *writer,
1415 struct snapshot *snapshot)
1416 {
1417 int ret;
1418 struct lttng_ht_iter iter;
1419 struct snapshot_output *output;
1420
1421 assert(writer);
1422 assert(snapshot);
1423
1424 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1425 if (ret) {
1426 ret = LTTNG_ERR_SAVE_IO_FAIL;
1427 goto end;
1428 }
1429
1430 rcu_read_lock();
1431 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1432 node.node) {
1433 ret = config_writer_open_element(writer,
1434 config_element_output);
1435 if (ret) {
1436 ret = LTTNG_ERR_SAVE_IO_FAIL;
1437 goto end_unlock;
1438 }
1439
1440 ret = config_writer_write_element_string(writer,
1441 config_element_name, output->name);
1442 if (ret) {
1443 ret = LTTNG_ERR_SAVE_IO_FAIL;
1444 goto end_unlock;
1445 }
1446
1447 ret = config_writer_write_element_unsigned_int(writer,
1448 config_element_max_size, output->max_size);
1449 if (ret) {
1450 ret = LTTNG_ERR_SAVE_IO_FAIL;
1451 goto end_unlock;
1452 }
1453
1454 ret = save_consumer_output(writer, output->consumer);
1455 if (ret) {
1456 goto end_unlock;
1457 }
1458
1459 /* /output */
1460 ret = config_writer_close_element(writer);
1461 if (ret) {
1462 ret = LTTNG_ERR_SAVE_IO_FAIL;
1463 goto end_unlock;
1464 }
1465 }
1466 rcu_read_unlock();
1467
1468 /* /snapshot_outputs */
1469 ret = config_writer_close_element(writer);
1470 if (ret) {
1471 ret = LTTNG_ERR_SAVE_IO_FAIL;
1472 goto end;
1473 }
1474
1475 end:
1476 return ret;
1477 end_unlock:
1478 rcu_read_unlock();
1479 return ret;
1480 }
1481
1482 static
1483 int save_session_output(struct config_writer *writer,
1484 struct ltt_session *session)
1485 {
1486 int ret;
1487
1488 assert(writer);
1489 assert(session);
1490
1491 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1492 (!session->snapshot_mode && !session->consumer)) {
1493 /* Session is in no output mode */
1494 ret = 0;
1495 goto end;
1496 }
1497
1498 ret = config_writer_open_element(writer, config_element_output);
1499 if (ret) {
1500 ret = LTTNG_ERR_SAVE_IO_FAIL;
1501 goto end;
1502 }
1503
1504 if (session->snapshot_mode) {
1505 ret = save_snapshot_outputs(writer, &session->snapshot);
1506 if (ret) {
1507 goto end;
1508 }
1509 } else {
1510 if (session->consumer) {
1511 ret = save_consumer_output(writer, session->consumer);
1512 if (ret) {
1513 goto end;
1514 }
1515 }
1516 }
1517
1518 /* /output */
1519 ret = config_writer_close_element(writer);
1520 if (ret) {
1521 ret = LTTNG_ERR_SAVE_IO_FAIL;
1522 goto end;
1523 }
1524 end:
1525 return ret;
1526 }
1527
1528 /*
1529 * Save the given session.
1530 *
1531 * Return 0 on success else a LTTNG_ERR* code.
1532 */
1533 static
1534 int save_session(struct ltt_session *session,
1535 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1536 {
1537 int ret, fd;
1538 unsigned int file_opened = 0; /* Indicate if the file has been opened */
1539 char config_file_path[PATH_MAX];
1540 size_t len;
1541 struct config_writer *writer = NULL;
1542 size_t session_name_len;
1543 const char *provided_path;
1544
1545 assert(session);
1546 assert(attr);
1547 assert(creds);
1548
1549 session_name_len = strlen(session->name);
1550 memset(config_file_path, 0, sizeof(config_file_path));
1551
1552 if (!session_access_ok(session,
1553 LTTNG_SOCK_GET_UID_CRED(creds),
1554 LTTNG_SOCK_GET_GID_CRED(creds))) {
1555 ret = LTTNG_ERR_EPERM;
1556 goto end;
1557 }
1558
1559 provided_path = lttng_save_session_attr_get_output_url(attr);
1560 if (provided_path) {
1561 DBG3("Save session in provided path %s", provided_path);
1562 len = strlen(provided_path);
1563 if (len >= sizeof(config_file_path)) {
1564 ret = LTTNG_ERR_SET_URL;
1565 goto end;
1566 }
1567 strncpy(config_file_path, provided_path, len);
1568 } else {
1569 ssize_t ret_len;
1570 char *home_dir = utils_get_user_home_dir(
1571 LTTNG_SOCK_GET_UID_CRED(creds));
1572 if (!home_dir) {
1573 ret = LTTNG_ERR_SET_URL;
1574 goto end;
1575 }
1576
1577 ret_len = snprintf(config_file_path, sizeof(config_file_path),
1578 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1579 free(home_dir);
1580 if (ret_len < 0) {
1581 PERROR("snprintf save session");
1582 ret = LTTNG_ERR_SET_URL;
1583 goto end;
1584 }
1585 len = ret_len;
1586 }
1587
1588 /*
1589 * Check the path fits in the config file path dst including the '/'
1590 * followed by trailing .lttng extension and the NULL terminated string.
1591 */
1592 if ((len + session_name_len + 2 +
1593 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1594 > sizeof(config_file_path)) {
1595 ret = LTTNG_ERR_SET_URL;
1596 goto end;
1597 }
1598
1599 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1600 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1601 if (ret) {
1602 ret = LTTNG_ERR_SET_URL;
1603 goto end;
1604 }
1605
1606 /*
1607 * At this point, we know that everything fits in the buffer. Validation
1608 * was done just above.
1609 */
1610 config_file_path[len++] = '/';
1611 strncpy(config_file_path + len, session->name, session_name_len);
1612 len += session_name_len;
1613 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1614 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1615 config_file_path[len] = '\0';
1616
1617 if (!access(config_file_path, F_OK) && !attr->overwrite) {
1618 /* File exists, notify the user since the overwrite flag is off. */
1619 ret = LTTNG_ERR_SAVE_FILE_EXIST;
1620 goto end;
1621 }
1622
1623 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1624 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1625 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1626 if (fd < 0) {
1627 PERROR("Could not create configuration file");
1628 ret = LTTNG_ERR_SAVE_IO_FAIL;
1629 goto end;
1630 }
1631 file_opened = 1;
1632
1633 writer = config_writer_create(fd, 1);
1634 if (!writer) {
1635 ret = LTTNG_ERR_NOMEM;
1636 goto end;
1637 }
1638
1639 ret = config_writer_open_element(writer, config_element_sessions);
1640 if (ret) {
1641 ret = LTTNG_ERR_SAVE_IO_FAIL;
1642 goto end;
1643 }
1644
1645 ret = config_writer_open_element(writer, config_element_session);
1646 if (ret) {
1647 ret = LTTNG_ERR_SAVE_IO_FAIL;
1648 goto end;
1649 }
1650
1651 ret = config_writer_write_element_string(writer, config_element_name,
1652 session->name);
1653 if (ret) {
1654 ret = LTTNG_ERR_SAVE_IO_FAIL;
1655 goto end;
1656 }
1657
1658 ret = save_domains(writer, session);
1659 if (ret) {
1660 goto end;
1661 }
1662
1663 ret = config_writer_write_element_bool(writer, config_element_started,
1664 session->active);
1665 if (ret) {
1666 ret = LTTNG_ERR_SAVE_IO_FAIL;
1667 goto end;
1668 }
1669
1670 if (session->snapshot_mode || session->live_timer) {
1671 ret = config_writer_open_element(writer, config_element_attributes);
1672 if (ret) {
1673 ret = LTTNG_ERR_SAVE_IO_FAIL;
1674 goto end;
1675 }
1676
1677 if (session->snapshot_mode) {
1678 ret = config_writer_write_element_bool(writer,
1679 config_element_snapshot_mode, 1);
1680 if (ret) {
1681 ret = LTTNG_ERR_SAVE_IO_FAIL;
1682 goto end;
1683 }
1684 } else {
1685 ret = config_writer_write_element_unsigned_int(writer,
1686 config_element_live_timer_interval, session->live_timer);
1687 if (ret) {
1688 ret = LTTNG_ERR_SAVE_IO_FAIL;
1689 goto end;
1690 }
1691 }
1692
1693 /* /attributes */
1694 ret = config_writer_close_element(writer);
1695 if (ret) {
1696 ret = LTTNG_ERR_SAVE_IO_FAIL;
1697 goto end;
1698 }
1699 }
1700
1701 ret = save_session_output(writer, session);
1702 if (ret) {
1703 goto end;
1704 }
1705
1706 /* /session */
1707 ret = config_writer_close_element(writer);
1708 if (ret) {
1709 ret = LTTNG_ERR_SAVE_IO_FAIL;
1710 goto end;
1711 }
1712
1713 /* /sessions */
1714 ret = config_writer_close_element(writer);
1715 if (ret) {
1716 ret = LTTNG_ERR_SAVE_IO_FAIL;
1717 goto end;
1718 }
1719 end:
1720 if (writer && config_writer_destroy(writer)) {
1721 /* Preserve the original error code */
1722 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1723 }
1724 if (ret) {
1725 /* Delete file in case of error */
1726 if (file_opened && unlink(config_file_path)) {
1727 PERROR("Unlinking XML session configuration.");
1728 }
1729 }
1730
1731 return ret;
1732 }
1733
1734 int cmd_save_sessions(struct lttng_save_session_attr *attr,
1735 lttng_sock_cred *creds)
1736 {
1737 int ret;
1738 const char *session_name;
1739 struct ltt_session *session;
1740
1741 session_lock_list();
1742
1743 session_name = lttng_save_session_attr_get_session_name(attr);
1744 if (session_name) {
1745 session = session_find_by_name(session_name);
1746 if (!session) {
1747 ret = LTTNG_ERR_SESS_NOT_FOUND;
1748 goto end;
1749 }
1750
1751 session_lock(session);
1752 ret = save_session(session, attr, creds);
1753 session_unlock(session);
1754 if (ret) {
1755 goto end;
1756 }
1757 } else {
1758 struct ltt_session_list *list = session_get_list();
1759
1760 cds_list_for_each_entry(session, &list->head, list) {
1761 session_lock(session);
1762 ret = save_session(session, attr, creds);
1763 session_unlock(session);
1764
1765 /* Don't abort if we don't have the required permissions. */
1766 if (ret && ret != LTTNG_ERR_EPERM) {
1767 goto end;
1768 }
1769 }
1770 }
1771 ret = LTTNG_OK;
1772
1773 end:
1774 session_unlock_list();
1775 return ret;
1776 }
This page took 0.103599 seconds and 3 git commands to generate.