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