Save filter expression as part of agent events and save them
[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
JG
744static
745void init_ust_event_from_agent_event(struct ltt_ust_event *ust_event,
746 struct agent_event *agent_event)
747{
748 ust_event->enabled = agent_event->enabled;
749 ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT;
750 strncpy(ust_event->attr.name, agent_event->name, LTTNG_SYMBOL_NAME_LEN);
751 ust_event->attr.loglevel_type = agent_event->loglevel_type;
752 ust_event->attr.loglevel = agent_event->loglevel;
753 ust_event->filter_expression = agent_event->filter_expression;
754 ust_event->exclusion = agent_event->exclusion;
755}
756
757static
758int save_agent_events(struct config_writer *writer,
759 struct ltt_ust_channel *chan,
760 struct agent *agent)
761{
762 int ret;
763 struct lttng_ht_iter iter;
764 struct lttng_ht_node_str *node;
765
766 ret = config_writer_open_element(writer, config_element_events);
767 if (ret) {
768 ret = LTTNG_ERR_SAVE_IO_FAIL;
769 goto end;
770 }
771
772 rcu_read_lock();
773 cds_lfht_for_each_entry(agent->events->ht, &iter.iter, node, node) {
774 int ret;
775 struct agent_event *agent_event;
776 struct ltt_ust_event fake_event;
777
778 memset(&fake_event, 0, sizeof(fake_event));
779 agent_event = caa_container_of(node, struct agent_event, node);
780
781 /*
782 * Initialize a fake ust event to reuse the same serialization
783 * function since UST and agent events contain the same info
784 * (and one could wonder why they don't reuse the same
785 * structures...).
786 */
787 init_ust_event_from_agent_event(&fake_event, agent_event);
788 ret = save_ust_event(writer, &fake_event);
789 if (ret) {
790 rcu_read_unlock();
791 goto end;
792 }
793 }
794 rcu_read_unlock();
795
796 /* /events */
797 ret = config_writer_close_element(writer);
798 if (ret) {
799 ret = LTTNG_ERR_SAVE_IO_FAIL;
800 goto end;
801 }
802end:
803 return ret;
804}
805
fb198a11
JG
806static
807int save_kernel_context(struct config_writer *writer,
808 struct lttng_kernel_context *ctx)
809{
810 int ret = 0;
811
812 if (!ctx) {
813 goto end;
814 }
815
fb198a11
JG
816 ret = config_writer_open_element(writer, config_element_context);
817 if (ret) {
818 ret = LTTNG_ERR_SAVE_IO_FAIL;
819 goto end;
820 }
821
cba45eda 822 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
fb198a11
JG
823 ret = config_writer_open_element(writer, config_element_perf);
824 if (ret) {
825 ret = LTTNG_ERR_SAVE_IO_FAIL;
826 goto end;
827 }
828
829 ret = config_writer_write_element_unsigned_int(writer,
830 config_element_type, ctx->u.perf_counter.type);
831 if (ret) {
832 ret = LTTNG_ERR_SAVE_IO_FAIL;
833 goto end;
834 }
835
836 ret = config_writer_write_element_unsigned_int(writer,
837 config_element_config, ctx->u.perf_counter.config);
838 if (ret) {
839 ret = LTTNG_ERR_SAVE_IO_FAIL;
840 goto end;
841 }
842
843 ret = config_writer_write_element_string(writer,
844 config_element_name, ctx->u.perf_counter.name);
845 if (ret) {
846 ret = LTTNG_ERR_SAVE_IO_FAIL;
847 goto end;
848 }
849
850 /* /perf */
851 ret = config_writer_close_element(writer);
852 if (ret) {
853 ret = LTTNG_ERR_SAVE_IO_FAIL;
854 goto end;
855 }
856 } else {
857 const char *context_type_string =
858 get_kernel_context_type_string(ctx->ctx);
859
860 if (!context_type_string) {
861 ERR("Unsupported kernel context type.");
862 ret = LTTNG_ERR_INVALID;
863 goto end;
864 }
865
866 ret = config_writer_write_element_string(writer,
867 config_element_type, context_type_string);
868 if (ret) {
869 ret = LTTNG_ERR_SAVE_IO_FAIL;
870 goto end;
871 }
872 }
873
874 /* /context */
875 ret = config_writer_close_element(writer);
876 if (ret) {
877 ret = LTTNG_ERR_SAVE_IO_FAIL;
878 goto end;
879 }
880
645328ae
DG
881end:
882 return ret;
883}
884
885static
886int save_kernel_contexts(struct config_writer *writer,
887 struct ltt_kernel_channel *kchan)
888{
889 int ret;
890 struct ltt_kernel_context *ctx;
891
2aa64052
JG
892 if (cds_list_empty(&kchan->ctx_list)) {
893 ret = 0;
894 goto end;
895 }
896
645328ae
DG
897 ret = config_writer_open_element(writer, config_element_contexts);
898 if (ret) {
899 ret = LTTNG_ERR_SAVE_IO_FAIL;
900 goto end;
901 }
902
903 cds_list_for_each_entry(ctx, &kchan->ctx_list, list) {
904 ret = save_kernel_context(writer, &ctx->ctx);
905 if (ret) {
906 goto end;
907 }
908 }
909
fb198a11
JG
910 /* /contexts */
911 ret = config_writer_close_element(writer);
912 if (ret) {
913 ret = LTTNG_ERR_SAVE_IO_FAIL;
914 goto end;
915 }
916end:
917 return ret;
918}
919
920static
921int save_ust_context(struct config_writer *writer,
922 struct cds_list_head *ctx_list)
923{
924 int ret;
925 struct ltt_ust_context *ctx;
926
927 assert(writer);
928 assert(ctx_list);
929
930 ret = config_writer_open_element(writer, config_element_contexts);
931 if (ret) {
932 ret = LTTNG_ERR_SAVE_IO_FAIL;
933 goto end;
934 }
935
936 cds_list_for_each_entry(ctx, ctx_list, list) {
937 const char *context_type_string;
938
fb198a11
JG
939
940 ret = config_writer_open_element(writer,
941 config_element_context);
942 if (ret) {
943 ret = LTTNG_ERR_SAVE_IO_FAIL;
944 goto end;
945 }
946
14ce5bd8
JG
947 if (ctx->ctx.ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) {
948 /* Perf contexts are saved as event_perf_context_type */
949 ret = config_writer_open_element(writer,
950 config_element_perf);
951 if (ret) {
952 ret = LTTNG_ERR_SAVE_IO_FAIL;
953 goto end;
954 }
955
956 ret = config_writer_write_element_unsigned_int(writer,
957 config_element_type,
958 ctx->ctx.u.perf_counter.type);
959 if (ret) {
960 ret = LTTNG_ERR_SAVE_IO_FAIL;
961 goto end;
962 }
963
964 ret = config_writer_write_element_unsigned_int(writer,
965 config_element_config,
966 ctx->ctx.u.perf_counter.config);
967 if (ret) {
968 ret = LTTNG_ERR_SAVE_IO_FAIL;
969 goto end;
970 }
971
972 ret = config_writer_write_element_string(writer,
973 config_element_name,
974 ctx->ctx.u.perf_counter.name);
975 if (ret) {
976 ret = LTTNG_ERR_SAVE_IO_FAIL;
977 goto end;
978 }
979
980 /* /perf */
981 ret = config_writer_close_element(writer);
982 if (ret) {
983 ret = LTTNG_ERR_SAVE_IO_FAIL;
984 goto end;
985 }
986 } else {
987 /* Save context as event_context_type_type */
988 context_type_string = get_ust_context_type_string(
989 ctx->ctx.ctx);
990 if (!context_type_string) {
991 ERR("Unsupported UST context type.")
992 ret = LTTNG_ERR_INVALID;
993 goto end;
994 }
995
996 ret = config_writer_write_element_string(writer,
997 config_element_type, context_type_string);
998 if (ret) {
999 ret = LTTNG_ERR_SAVE_IO_FAIL;
1000 goto end;
1001 }
fb198a11
JG
1002 }
1003
1004 /* /context */
1005 ret = config_writer_close_element(writer);
1006 if (ret) {
1007 ret = LTTNG_ERR_SAVE_IO_FAIL;
1008 goto end;
1009 }
1010 }
1011
1012 /* /contexts */
1013 ret = config_writer_close_element(writer);
1014 if (ret) {
1015 ret = LTTNG_ERR_SAVE_IO_FAIL;
1016 goto end;
1017 }
1018end:
1019 return ret;
1020}
1021
1022static
1023int save_kernel_channel(struct config_writer *writer,
1024 struct ltt_kernel_channel *kchan)
1025{
1026 int ret;
1027
1028 assert(writer);
1029 assert(kchan);
1030
1031 ret = config_writer_open_element(writer, config_element_channel);
1032 if (ret) {
1033 ret = LTTNG_ERR_SAVE_IO_FAIL;
1034 goto end;
1035 }
1036
1037 ret = config_writer_write_element_string(writer, config_element_name,
1038 kchan->channel->name);
1039 if (ret) {
1040 ret = LTTNG_ERR_SAVE_IO_FAIL;
1041 goto end;
1042 }
1043
1044 ret = config_writer_write_element_bool(writer, config_element_enabled,
1045 kchan->channel->enabled);
1046 if (ret) {
1047 ret = LTTNG_ERR_SAVE_IO_FAIL;
1048 goto end;
1049 }
1050
1051 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
1052 if (ret) {
1053 goto end;
1054 }
1055
0de3eda1 1056 ret = save_kernel_events(writer, kchan);
fb198a11
JG
1057 if (ret) {
1058 goto end;
1059 }
1060
645328ae 1061 ret = save_kernel_contexts(writer, kchan);
fb198a11
JG
1062 if (ret) {
1063 goto end;
1064 }
1065
1066 /* /channel */
1067 ret = config_writer_close_element(writer);
1068 if (ret) {
1069 ret = LTTNG_ERR_SAVE_IO_FAIL;
1070 goto end;
1071 }
1072end:
1073 return ret;
1074}
1075
1076static
1077int save_ust_channel(struct config_writer *writer,
1078 struct ltt_ust_channel *ust_chan,
1079 struct ltt_ust_session *session)
1080{
1081 int ret;
1082
1083 assert(writer);
1084 assert(ust_chan);
1085 assert(session);
1086
1087 ret = config_writer_open_element(writer, config_element_channel);
1088 if (ret) {
1089 ret = LTTNG_ERR_SAVE_IO_FAIL;
1090 goto end;
1091 }
1092
1093 ret = config_writer_write_element_string(writer, config_element_name,
1094 ust_chan->name);
1095 if (ret) {
1096 ret = LTTNG_ERR_SAVE_IO_FAIL;
1097 goto end;
1098 }
1099
1100 ret = config_writer_write_element_bool(writer, config_element_enabled,
1101 ust_chan->enabled);
1102 if (ret) {
1103 ret = LTTNG_ERR_SAVE_IO_FAIL;
1104 goto end;
1105 }
1106
1107 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
1108 if (ret) {
1109 goto end;
1110 }
1111
1112 ret = config_writer_write_element_unsigned_int(writer,
1113 config_element_tracefile_size, ust_chan->tracefile_size);
1114 if (ret) {
1115 ret = LTTNG_ERR_SAVE_IO_FAIL;
1116 goto end;
1117 }
1118
1119 ret = config_writer_write_element_unsigned_int(writer,
1120 config_element_tracefile_count, ust_chan->tracefile_count);
1121 if (ret) {
1122 ret = LTTNG_ERR_SAVE_IO_FAIL;
1123 goto end;
1124 }
1125
1126 ret = config_writer_write_element_unsigned_int(writer,
1127 config_element_live_timer_interval,
1128 session->live_timer_interval);
1129 if (ret) {
1130 ret = LTTNG_ERR_SAVE_IO_FAIL;
1131 goto end;
1132 }
1133
51755dc8
JG
1134 if (ust_chan->domain == LTTNG_DOMAIN_UST) {
1135 ret = save_ust_events(writer, ust_chan->events);
1136 if (ret) {
1137 goto end;
1138 }
1139 } else {
1140 struct agent *agent = NULL;
1141
1142 agent = trace_ust_find_agent(session, ust_chan->domain);
1143 if (!agent) {
1144 ret = LTTNG_ERR_SAVE_IO_FAIL;
1145 ERR("Could not find agent associated to UST subdomain");
1146 goto end;
1147 }
1148
1149 /*
1150 * Channels associated with a UST sub-domain (such as JUL, Log4j
1151 * or Python) don't have any non-internal events. We retrieve
1152 * the "agent" events associated with this channel and serialize
1153 * them.
1154 */
1155 ret = save_agent_events(writer, ust_chan, agent);
1156 if (ret) {
1157 goto end;
1158 }
fb198a11
JG
1159 }
1160
1161 ret = save_ust_context(writer, &ust_chan->ctx_list);
1162 if (ret) {
1163 goto end;
1164 }
1165
1166 /* /channel */
1167 ret = config_writer_close_element(writer);
1168 if (ret) {
1169 ret = LTTNG_ERR_SAVE_IO_FAIL;
1170 goto end;
1171 }
1172end:
1173 return ret;
1174}
1175
1176static
1177int save_kernel_session(struct config_writer *writer,
1178 struct ltt_session *session)
1179{
1180 int ret;
1181 struct ltt_kernel_channel *kchan;
1182
1183 assert(writer);
1184 assert(session);
1185
1186 ret = config_writer_write_element_string(writer, config_element_type,
1187 config_domain_type_kernel);
1188 if (ret) {
1189 ret = LTTNG_ERR_SAVE_IO_FAIL;
1190 goto end;
1191 }
1192
1193 ret = config_writer_write_element_string(writer,
1194 config_element_buffer_type, config_buffer_type_global);
1195 if (ret) {
1196 ret = LTTNG_ERR_SAVE_IO_FAIL;
1197 goto end;
1198 }
1199
1200 ret = config_writer_open_element(writer,
1201 config_element_channels);
1202 if (ret) {
1203 ret = LTTNG_ERR_SAVE_IO_FAIL;
1204 goto end;
1205 }
1206
1207 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
1208 list) {
1209 ret = save_kernel_channel(writer, kchan);
1210 if (ret) {
1211 goto end;
1212 }
1213 }
1214
1215 /* /channels */
1216 ret = config_writer_close_element(writer);
1217 if (ret) {
1218 ret = LTTNG_ERR_SAVE_IO_FAIL;
1219 goto end;
1220 }
1221end:
1222 return ret;
1223}
1224
1225static
51755dc8
JG
1226const char *get_config_domain_str(enum lttng_domain_type domain)
1227{
1228 const char *str_dom;
1229
1230 switch (domain) {
1231 case LTTNG_DOMAIN_KERNEL:
1232 str_dom = config_domain_type_kernel;
1233 break;
1234 case LTTNG_DOMAIN_UST:
1235 str_dom = config_domain_type_ust;
1236 break;
1237 case LTTNG_DOMAIN_JUL:
1238 str_dom = config_domain_type_jul;
1239 break;
1240 case LTTNG_DOMAIN_LOG4J:
1241 str_dom = config_domain_type_log4j;
1242 break;
1243 case LTTNG_DOMAIN_PYTHON:
1244 str_dom = config_domain_type_python;
1245 break;
1246 default:
1247 assert(0);
1248 }
1249
1250 return str_dom;
1251}
1252
1253static
1254int save_ust_domain(struct config_writer *writer,
1255 struct ltt_session *session, enum lttng_domain_type domain)
fb198a11
JG
1256{
1257 int ret;
1258 struct ltt_ust_channel *ust_chan;
1259 const char *buffer_type_string;
1260 struct lttng_ht_node_str *node;
1261 struct lttng_ht_iter iter;
51755dc8 1262 const char *config_domain_name;
fb198a11
JG
1263
1264 assert(writer);
1265 assert(session);
1266
51755dc8
JG
1267 ret = config_writer_open_element(writer,
1268 config_element_domain);
1269 if (ret) {
1270 ret = LTTNG_ERR_SAVE_IO_FAIL;
1271 goto end;
1272 }
1273
1274 config_domain_name = get_config_domain_str(domain);
1275 if (!config_domain_name) {
1276 ret = LTTNG_ERR_INVALID;
1277 goto end;
1278 }
1279
1280 ret = config_writer_write_element_string(writer,
1281 config_element_type, config_domain_name);
fb198a11
JG
1282 if (ret) {
1283 ret = LTTNG_ERR_SAVE_IO_FAIL;
1284 goto end;
1285 }
1286
1287 buffer_type_string = get_buffer_type_string(
1288 session->ust_session->buffer_type);
1289 if (!buffer_type_string) {
1290 ERR("Unsupported buffer type.");
1291 ret = LTTNG_ERR_INVALID;
1292 goto end;
1293 }
1294
1295 ret = config_writer_write_element_string(writer,
1296 config_element_buffer_type, buffer_type_string);
1297 if (ret) {
1298 ret = LTTNG_ERR_SAVE_IO_FAIL;
1299 goto end;
1300 }
1301
1302 ret = config_writer_open_element(writer, config_element_channels);
1303 if (ret) {
1304 ret = LTTNG_ERR_SAVE_IO_FAIL;
1305 goto end;
1306 }
1307
1308 rcu_read_lock();
1309 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1310 &iter.iter, node, node) {
fb198a11 1311 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
51755dc8 1312 if (domain == ust_chan->domain) {
fb198a11
JG
1313 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1314 if (ret) {
1315 rcu_read_unlock();
1316 goto end;
1317 }
1318 }
1319 }
1320 rcu_read_unlock();
1321
1322 /* /channels */
1323 ret = config_writer_close_element(writer);
1324 if (ret) {
1325 ret = LTTNG_ERR_SAVE_IO_FAIL;
1326 goto end;
1327 }
51755dc8
JG
1328
1329 /* /domain */
1330 ret = config_writer_close_element(writer);
1331 if (ret) {
1332 ret = LTTNG_ERR_SAVE_IO_FAIL;
1333 goto end;
1334 }
1335
fb198a11
JG
1336end:
1337 return ret;
1338}
1339
847a5916
JR
1340static
1341int save_pid_tracker(struct config_writer *writer,
1342 struct ltt_session *sess, int domain)
1343{
1344 int ret = 0;
1345 ssize_t nr_pids = 0, i;
1346 int32_t *pids = NULL;
1347
1348 switch (domain) {
1349 case LTTNG_DOMAIN_KERNEL:
1350 {
1351 nr_pids = kernel_list_tracker_pids(sess->kernel_session, &pids);
1352 if (nr_pids < 0) {
1353 ret = LTTNG_ERR_KERN_LIST_FAIL;
1354 goto end;
1355 }
1356 break;
1357 }
1358 case LTTNG_DOMAIN_UST:
1359 {
1360 nr_pids = trace_ust_list_tracker_pids(sess->ust_session, &pids);
1361 if (nr_pids < 0) {
1362 ret = LTTNG_ERR_UST_LIST_FAIL;
1363 goto end;
1364 }
1365 break;
1366 }
1367 case LTTNG_DOMAIN_JUL:
1368 case LTTNG_DOMAIN_LOG4J:
1369 case LTTNG_DOMAIN_PYTHON:
1370 default:
1371 ret = LTTNG_ERR_UNKNOWN_DOMAIN;
1372 goto end;
1373 }
1374
1375 /* Only create a pid_tracker if enabled or untrack all */
1376 if (nr_pids != 1 || (nr_pids == 1 && pids[0] != -1)) {
1377 ret = config_writer_open_element(writer,
1378 config_element_pid_tracker);
1379 if (ret) {
1380 ret = LTTNG_ERR_SAVE_IO_FAIL;
1381 goto end;
1382 }
1383
1384 ret = config_writer_open_element(writer,
1385 config_element_targets);
1386 if (ret) {
1387 ret = LTTNG_ERR_SAVE_IO_FAIL;
1388 goto end;
1389 }
1390
1391 for (i = 0; i < nr_pids; i++) {
1392 ret = config_writer_open_element(writer,
1393 config_element_target_pid);
1394 if (ret) {
1395 ret = LTTNG_ERR_SAVE_IO_FAIL;
1396 goto end;
1397 }
1398
1399 ret = config_writer_write_element_unsigned_int(writer,
1400 config_element_pid, pids[i]);
1401 if (ret) {
1402 ret = LTTNG_ERR_SAVE_IO_FAIL;
1403 goto end;
1404 }
1405
1406 /* /pid_target */
1407 ret = config_writer_close_element(writer);
1408 if (ret) {
1409 ret = LTTNG_ERR_SAVE_IO_FAIL;
1410 goto end;
1411 }
1412 }
1413
1414 /* /targets */
1415 ret = config_writer_close_element(writer);
1416 if (ret) {
1417 ret = LTTNG_ERR_SAVE_IO_FAIL;
1418 goto end;
1419 }
1420
1421 /* /pid_tracker */
1422 ret = config_writer_close_element(writer);
1423 if (ret) {
1424 ret = LTTNG_ERR_SAVE_IO_FAIL;
1425 goto end;
1426 }
1427 }
1428end:
1429 free(pids);
1430 return ret;
1431}
1432
fb198a11
JG
1433static
1434int save_domains(struct config_writer *writer, struct ltt_session *session)
1435{
1436 int ret = 0;
1437
1438 assert(writer);
1439 assert(session);
1440
1441 if (!session->kernel_session && !session->ust_session) {
1442 goto end;
1443 }
1444
1445 ret = config_writer_open_element(writer, config_element_domains);
1446 if (ret) {
1447 ret = LTTNG_ERR_SAVE_IO_FAIL;
1448 goto end;
1449 }
1450
1451
1452 if (session->kernel_session) {
1453 ret = config_writer_open_element(writer,
1454 config_element_domain);
1455 if (ret) {
1456 ret = LTTNG_ERR_SAVE_IO_FAIL;
1457 goto end;
1458 }
1459
1460 ret = save_kernel_session(writer, session);
1461 if (ret) {
1462 goto end;
1463 }
1464
847a5916
JR
1465 ret = config_writer_open_element(writer,
1466 config_element_trackers);
1467 if (ret) {
1468 ret = LTTNG_ERR_SAVE_IO_FAIL;
1469 goto end;
1470 }
1471
1472 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL);
1473 if (ret) {
1474 goto end;
1475 }
1476
1477 /* /trackers */
1478 ret = config_writer_close_element(writer);
1479 if (ret) {
1480 ret = LTTNG_ERR_SAVE_IO_FAIL;
1481 goto end;
1482 }
fb198a11
JG
1483 /* /domain */
1484 ret = config_writer_close_element(writer);
1485 if (ret) {
1486 ret = LTTNG_ERR_SAVE_IO_FAIL;
1487 goto end;
1488 }
1489 }
1490
1491 if (session->ust_session) {
51755dc8 1492 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST);
fb198a11
JG
1493 if (ret) {
1494 goto end;
1495 }
1496
847a5916 1497 ret = config_writer_open_element(writer,
51755dc8 1498 config_element_trackers);
847a5916
JR
1499 if (ret) {
1500 ret = LTTNG_ERR_SAVE_IO_FAIL;
1501 goto end;
1502 }
1503
1504 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST);
1505 if (ret) {
1506 goto end;
1507 }
1508
1509 /* /trackers */
1510 ret = config_writer_close_element(writer);
1511 if (ret) {
847a5916
JR
1512 goto end;
1513 }
51755dc8
JG
1514
1515 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL);
fb198a11 1516 if (ret) {
fb198a11
JG
1517 goto end;
1518 }
fb198a11 1519
51755dc8
JG
1520 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J);
1521 if (ret) {
1522 goto end;
1523 }
65d72c41 1524
51755dc8
JG
1525 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON);
1526 if (ret) {
1527 goto end;
fb198a11
JG
1528 }
1529 }
1530
1531 /* /domains */
1532 ret = config_writer_close_element(writer);
1533 if (ret) {
1534 ret = LTTNG_ERR_SAVE_IO_FAIL;
1535 goto end;
1536 }
1537end:
1538 return ret;
1539}
1540
1541static
1542int save_consumer_output(struct config_writer *writer,
1543 struct consumer_output *output)
1544{
1545 int ret;
1546
1547 assert(writer);
1548 assert(output);
1549
1550 ret = config_writer_open_element(writer, config_element_consumer_output);
1551 if (ret) {
1552 ret = LTTNG_ERR_SAVE_IO_FAIL;
1553 goto end;
1554 }
1555
1556 ret = config_writer_write_element_bool(writer, config_element_enabled,
1557 output->enabled);
1558 if (ret) {
1559 ret = LTTNG_ERR_SAVE_IO_FAIL;
1560 goto end;
1561 }
1562
1563 ret = config_writer_open_element(writer, config_element_destination);
1564 if (ret) {
1565 ret = LTTNG_ERR_SAVE_IO_FAIL;
1566 goto end;
1567 }
1568
1569 switch (output->type) {
1570 case CONSUMER_DST_LOCAL:
1571 ret = config_writer_write_element_string(writer,
1572 config_element_path, output->dst.trace_path);
1573 if (ret) {
1574 ret = LTTNG_ERR_SAVE_IO_FAIL;
1575 goto end;
1576 }
1577 break;
1578 case CONSUMER_DST_NET:
1579 {
1580 char *uri;
1581
1582 uri = zmalloc(PATH_MAX);
1583 if (!uri) {
1584 ret = LTTNG_ERR_NOMEM;
1585 goto end;
1586 }
1587
1588 ret = config_writer_open_element(writer, config_element_net_output);
1589 if (ret) {
1590 ret = LTTNG_ERR_SAVE_IO_FAIL;
1591 goto end_net_output;
1592 }
1593
1594 if (output->dst.net.control_isset &&
1595 output->dst.net.data_isset) {
1596 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1597 if (ret < 0) {
1598 ret = LTTNG_ERR_INVALID;
1599 goto end_net_output;
1600 }
1601
1602 ret = config_writer_write_element_string(writer,
1603 config_element_control_uri, uri);
1604 if (ret) {
1605 ret = LTTNG_ERR_SAVE_IO_FAIL;
1606 goto end_net_output;
1607 }
1608
1609 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1610 if (ret < 0) {
1611 ret = LTTNG_ERR_INVALID;
1612 goto end_net_output;
1613 }
1614
1615 ret = config_writer_write_element_string(writer,
1616 config_element_data_uri, uri);
1617 if (ret) {
1618 ret = LTTNG_ERR_SAVE_IO_FAIL;
1619 goto end_net_output;
1620 }
1621
1622end_net_output:
1623 free(uri);
1624 if (ret) {
1625 goto end;
1626 }
1627 } else {
1628 ret = !output->dst.net.control_isset ?
1629 LTTNG_ERR_URL_CTRL_MISS :
1630 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1631 free(uri);
fb198a11
JG
1632 goto end;
1633 }
1634
1635 ret = config_writer_close_element(writer);
1636 if (ret) {
1637 ret = LTTNG_ERR_SAVE_IO_FAIL;
1638 goto end;
1639 }
1640 break;
1641 }
1642 default:
1643 ERR("Unsupported consumer output type.");
1644 ret = LTTNG_ERR_INVALID;
1645 goto end;
1646 }
1647
1648 /* /destination */
1649 ret = config_writer_close_element(writer);
1650 if (ret) {
1651 ret = LTTNG_ERR_SAVE_IO_FAIL;
1652 goto end;
1653 }
1654
1655 /* /consumer_output */
1656 ret = config_writer_close_element(writer);
1657 if (ret) {
1658 ret = LTTNG_ERR_SAVE_IO_FAIL;
1659 goto end;
1660 }
1661end:
1662 return ret;
1663}
1664
1665static
1666int save_snapshot_outputs(struct config_writer *writer,
1667 struct snapshot *snapshot)
1668{
1669 int ret;
1670 struct lttng_ht_iter iter;
1671 struct snapshot_output *output;
1672
1673 assert(writer);
1674 assert(snapshot);
1675
1676 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1677 if (ret) {
1678 ret = LTTNG_ERR_SAVE_IO_FAIL;
1679 goto end;
1680 }
1681
1682 rcu_read_lock();
1683 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1684 node.node) {
1685 ret = config_writer_open_element(writer,
1686 config_element_output);
1687 if (ret) {
1688 ret = LTTNG_ERR_SAVE_IO_FAIL;
1689 goto end_unlock;
1690 }
1691
1692 ret = config_writer_write_element_string(writer,
1693 config_element_name, output->name);
1694 if (ret) {
1695 ret = LTTNG_ERR_SAVE_IO_FAIL;
1696 goto end_unlock;
1697 }
1698
1699 ret = config_writer_write_element_unsigned_int(writer,
1700 config_element_max_size, output->max_size);
1701 if (ret) {
1702 ret = LTTNG_ERR_SAVE_IO_FAIL;
1703 goto end_unlock;
1704 }
1705
1706 ret = save_consumer_output(writer, output->consumer);
1707 if (ret) {
1708 goto end_unlock;
1709 }
1710
1711 /* /output */
1712 ret = config_writer_close_element(writer);
1713 if (ret) {
1714 ret = LTTNG_ERR_SAVE_IO_FAIL;
1715 goto end_unlock;
1716 }
1717 }
1718 rcu_read_unlock();
1719
1720 /* /snapshot_outputs */
1721 ret = config_writer_close_element(writer);
1722 if (ret) {
1723 ret = LTTNG_ERR_SAVE_IO_FAIL;
1724 goto end;
1725 }
1726
1727end:
1728 return ret;
1729end_unlock:
1730 rcu_read_unlock();
1731 return ret;
1732}
1733
1734static
1735int save_session_output(struct config_writer *writer,
1736 struct ltt_session *session)
1737{
1738 int ret;
1739
1740 assert(writer);
1741 assert(session);
1742
1743 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1744 (!session->snapshot_mode && !session->consumer)) {
1745 /* Session is in no output mode */
1746 ret = 0;
1747 goto end;
1748 }
1749
1750 ret = config_writer_open_element(writer, config_element_output);
1751 if (ret) {
1752 ret = LTTNG_ERR_SAVE_IO_FAIL;
1753 goto end;
1754 }
1755
1756 if (session->snapshot_mode) {
1757 ret = save_snapshot_outputs(writer, &session->snapshot);
1758 if (ret) {
1759 goto end;
1760 }
1761 } else {
1762 if (session->consumer) {
1763 ret = save_consumer_output(writer, session->consumer);
1764 if (ret) {
1765 goto end;
1766 }
1767 }
1768 }
1769
1770 /* /output */
1771 ret = config_writer_close_element(writer);
1772 if (ret) {
1773 ret = LTTNG_ERR_SAVE_IO_FAIL;
1774 goto end;
1775 }
1776end:
1777 return ret;
1778}
1779
1780/*
1781 * Save the given session.
1782 *
1783 * Return 0 on success else a LTTNG_ERR* code.
1784 */
1785static
1786int save_session(struct ltt_session *session,
1787 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1788{
1789 int ret, fd;
db471218 1790 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
1791 char config_file_path[PATH_MAX];
1792 size_t len;
1793 struct config_writer *writer = NULL;
1794 size_t session_name_len;
1795 const char *provided_path;
1796
1797 assert(session);
1798 assert(attr);
1799 assert(creds);
1800
1801 session_name_len = strlen(session->name);
95a29ab8 1802 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
1803
1804 if (!session_access_ok(session,
1805 LTTNG_SOCK_GET_UID_CRED(creds),
1806 LTTNG_SOCK_GET_GID_CRED(creds))) {
1807 ret = LTTNG_ERR_EPERM;
1808 goto end;
1809 }
1810
1811 provided_path = lttng_save_session_attr_get_output_url(attr);
1812 if (provided_path) {
95a29ab8 1813 DBG3("Save session in provided path %s", provided_path);
fb198a11 1814 len = strlen(provided_path);
d2992717 1815 if (len >= sizeof(config_file_path)) {
fb198a11
JG
1816 ret = LTTNG_ERR_SET_URL;
1817 goto end;
1818 }
1819 strncpy(config_file_path, provided_path, len);
1820 } else {
7e078ad1 1821 ssize_t ret_len;
fb198a11
JG
1822 char *home_dir = utils_get_user_home_dir(
1823 LTTNG_SOCK_GET_UID_CRED(creds));
1824 if (!home_dir) {
1825 ret = LTTNG_ERR_SET_URL;
1826 goto end;
1827 }
1828
d2992717 1829 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
1830 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1831 free(home_dir);
7e078ad1 1832 if (ret_len < 0) {
fb198a11
JG
1833 PERROR("snprintf save session");
1834 ret = LTTNG_ERR_SET_URL;
1835 goto end;
1836 }
7e078ad1 1837 len = ret_len;
fb198a11
JG
1838 }
1839
1840 /*
d2992717
DG
1841 * Check the path fits in the config file path dst including the '/'
1842 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 1843 */
d2992717
DG
1844 if ((len + session_name_len + 2 +
1845 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1846 > sizeof(config_file_path)) {
fb198a11
JG
1847 ret = LTTNG_ERR_SET_URL;
1848 goto end;
1849 }
1850
1851 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1852 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1853 if (ret) {
1854 ret = LTTNG_ERR_SET_URL;
1855 goto end;
1856 }
1857
d2992717
DG
1858 /*
1859 * At this point, we know that everything fits in the buffer. Validation
1860 * was done just above.
1861 */
fb198a11
JG
1862 config_file_path[len++] = '/';
1863 strncpy(config_file_path + len, session->name, session_name_len);
1864 len += session_name_len;
1865 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
1866 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1867 config_file_path[len] = '\0';
fb198a11
JG
1868
1869 if (!access(config_file_path, F_OK) && !attr->overwrite) {
f9b57ab2
DG
1870 /* File exists, notify the user since the overwrite flag is off. */
1871 ret = LTTNG_ERR_SAVE_FILE_EXIST;
fb198a11
JG
1872 goto end;
1873 }
1874
1875 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1876 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1877 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1878 if (fd < 0) {
1879 PERROR("Could not create configuration file");
1880 ret = LTTNG_ERR_SAVE_IO_FAIL;
1881 goto end;
1882 }
db471218 1883 file_opened = 1;
fb198a11 1884
705bb62f 1885 writer = config_writer_create(fd, 1);
fb198a11
JG
1886 if (!writer) {
1887 ret = LTTNG_ERR_NOMEM;
1888 goto end;
1889 }
1890
1891 ret = config_writer_open_element(writer, config_element_sessions);
1892 if (ret) {
1893 ret = LTTNG_ERR_SAVE_IO_FAIL;
1894 goto end;
1895 }
1896
1897 ret = config_writer_open_element(writer, config_element_session);
1898 if (ret) {
1899 ret = LTTNG_ERR_SAVE_IO_FAIL;
1900 goto end;
1901 }
1902
1903 ret = config_writer_write_element_string(writer, config_element_name,
1904 session->name);
1905 if (ret) {
1906 ret = LTTNG_ERR_SAVE_IO_FAIL;
1907 goto end;
1908 }
1909
9e7c9f56
JR
1910 if(session->shm_path[0] != '\0') {
1911 ret = config_writer_write_element_string(writer,
1912 config_element_shared_memory_path,
1913 session->shm_path);
1914 if (ret) {
1915 ret = LTTNG_ERR_SAVE_IO_FAIL;
1916 goto end;
1917 }
1918 }
1919
fb198a11
JG
1920 ret = save_domains(writer, session);
1921 if (ret) {
1922 goto end;
1923 }
1924
1925 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 1926 session->active);
fb198a11
JG
1927 if (ret) {
1928 ret = LTTNG_ERR_SAVE_IO_FAIL;
1929 goto end;
1930 }
1931
1932 if (session->snapshot_mode || session->live_timer) {
1933 ret = config_writer_open_element(writer, config_element_attributes);
1934 if (ret) {
1935 ret = LTTNG_ERR_SAVE_IO_FAIL;
1936 goto end;
1937 }
1938
1939 if (session->snapshot_mode) {
1940 ret = config_writer_write_element_bool(writer,
1941 config_element_snapshot_mode, 1);
1942 if (ret) {
1943 ret = LTTNG_ERR_SAVE_IO_FAIL;
1944 goto end;
1945 }
1946 } else {
d98ad589 1947 ret = config_writer_write_element_unsigned_int(writer,
fb198a11
JG
1948 config_element_live_timer_interval, session->live_timer);
1949 if (ret) {
1950 ret = LTTNG_ERR_SAVE_IO_FAIL;
1951 goto end;
1952 }
1953 }
1954
1955 /* /attributes */
1956 ret = config_writer_close_element(writer);
1957 if (ret) {
1958 ret = LTTNG_ERR_SAVE_IO_FAIL;
1959 goto end;
1960 }
1961 }
1962
1963 ret = save_session_output(writer, session);
1964 if (ret) {
1965 goto end;
1966 }
1967
1968 /* /session */
1969 ret = config_writer_close_element(writer);
1970 if (ret) {
1971 ret = LTTNG_ERR_SAVE_IO_FAIL;
1972 goto end;
1973 }
1974
1975 /* /sessions */
1976 ret = config_writer_close_element(writer);
1977 if (ret) {
1978 ret = LTTNG_ERR_SAVE_IO_FAIL;
1979 goto end;
1980 }
1981end:
1982 if (writer && config_writer_destroy(writer)) {
1983 /* Preserve the original error code */
1984 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1985 }
1986 if (ret) {
1987 /* Delete file in case of error */
db471218 1988 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
1989 PERROR("Unlinking XML session configuration.");
1990 }
1991 }
1992
1993 return ret;
1994}
1995
1996int cmd_save_sessions(struct lttng_save_session_attr *attr,
1997 lttng_sock_cred *creds)
1998{
1999 int ret;
2000 const char *session_name;
2001 struct ltt_session *session;
2002
2003 session_lock_list();
2004
2005 session_name = lttng_save_session_attr_get_session_name(attr);
2006 if (session_name) {
2007 session = session_find_by_name(session_name);
2008 if (!session) {
2009 ret = LTTNG_ERR_SESS_NOT_FOUND;
2010 goto end;
2011 }
2012
2013 session_lock(session);
2014 ret = save_session(session, attr, creds);
2015 session_unlock(session);
2016 if (ret) {
2017 goto end;
2018 }
2019 } else {
2020 struct ltt_session_list *list = session_get_list();
2021
2022 cds_list_for_each_entry(session, &list->head, list) {
2023 session_lock(session);
2024 ret = save_session(session, attr, creds);
2025 session_unlock(session);
2026
2027 /* Don't abort if we don't have the required permissions. */
2028 if (ret && ret != LTTNG_ERR_EPERM) {
2029 goto end;
2030 }
2031 }
2032 }
2033 ret = LTTNG_OK;
2034
2035end:
2036 session_unlock_list();
2037 return ret;
2038}
This page took 0.104315 seconds and 4 git commands to generate.