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