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