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