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