Fix: streamline ret/errno of run_as()
[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
e8fcabef
JG
1253static
1254int save_pid_tracker(struct config_writer *writer,
1255 struct ltt_session *sess, int domain)
1256{
1257 int ret = 0;
1258 ssize_t nr_pids = 0, i;
1259 int32_t *pids = NULL;
1260
1261 switch (domain) {
1262 case LTTNG_DOMAIN_KERNEL:
1263 {
1264 nr_pids = kernel_list_tracker_pids(sess->kernel_session, &pids);
1265 if (nr_pids < 0) {
1266 ret = LTTNG_ERR_KERN_LIST_FAIL;
1267 goto end;
1268 }
1269 break;
1270 }
1271 case LTTNG_DOMAIN_UST:
1272 {
1273 nr_pids = trace_ust_list_tracker_pids(sess->ust_session, &pids);
1274 if (nr_pids < 0) {
1275 ret = LTTNG_ERR_UST_LIST_FAIL;
1276 goto end;
1277 }
1278 break;
1279 }
1280 case LTTNG_DOMAIN_JUL:
1281 case LTTNG_DOMAIN_LOG4J:
1282 case LTTNG_DOMAIN_PYTHON:
1283 default:
1284 ret = LTTNG_ERR_UNKNOWN_DOMAIN;
1285 goto end;
1286 }
1287
1288 /* Only create a pid_tracker if enabled or untrack all */
1289 if (nr_pids != 1 || (nr_pids == 1 && pids[0] != -1)) {
1290 ret = config_writer_open_element(writer,
1291 config_element_pid_tracker);
1292 if (ret) {
1293 ret = LTTNG_ERR_SAVE_IO_FAIL;
1294 goto end;
1295 }
1296
1297 ret = config_writer_open_element(writer,
1298 config_element_targets);
1299 if (ret) {
1300 ret = LTTNG_ERR_SAVE_IO_FAIL;
1301 goto end;
1302 }
1303
1304 for (i = 0; i < nr_pids; i++) {
1305 ret = config_writer_open_element(writer,
1306 config_element_target_pid);
1307 if (ret) {
1308 ret = LTTNG_ERR_SAVE_IO_FAIL;
1309 goto end;
1310 }
1311
1312 ret = config_writer_write_element_unsigned_int(writer,
1313 config_element_pid, pids[i]);
1314 if (ret) {
1315 ret = LTTNG_ERR_SAVE_IO_FAIL;
1316 goto end;
1317 }
1318
1319 /* /pid_target */
1320 ret = config_writer_close_element(writer);
1321 if (ret) {
1322 ret = LTTNG_ERR_SAVE_IO_FAIL;
1323 goto end;
1324 }
1325 }
1326
1327 /* /targets */
1328 ret = config_writer_close_element(writer);
1329 if (ret) {
1330 ret = LTTNG_ERR_SAVE_IO_FAIL;
1331 goto end;
1332 }
1333
1334 /* /pid_tracker */
1335 ret = config_writer_close_element(writer);
1336 if (ret) {
1337 ret = LTTNG_ERR_SAVE_IO_FAIL;
1338 goto end;
1339 }
1340 }
1341end:
1342 free(pids);
1343 return ret;
1344}
1345
51755dc8
JG
1346static
1347int save_ust_domain(struct config_writer *writer,
1348 struct ltt_session *session, enum lttng_domain_type domain)
fb198a11
JG
1349{
1350 int ret;
1351 struct ltt_ust_channel *ust_chan;
1352 const char *buffer_type_string;
1353 struct lttng_ht_node_str *node;
1354 struct lttng_ht_iter iter;
51755dc8 1355 const char *config_domain_name;
fb198a11
JG
1356
1357 assert(writer);
1358 assert(session);
1359
51755dc8
JG
1360 ret = config_writer_open_element(writer,
1361 config_element_domain);
1362 if (ret) {
1363 ret = LTTNG_ERR_SAVE_IO_FAIL;
1364 goto end;
1365 }
1366
1367 config_domain_name = get_config_domain_str(domain);
1368 if (!config_domain_name) {
1369 ret = LTTNG_ERR_INVALID;
1370 goto end;
1371 }
1372
1373 ret = config_writer_write_element_string(writer,
1374 config_element_type, config_domain_name);
fb198a11
JG
1375 if (ret) {
1376 ret = LTTNG_ERR_SAVE_IO_FAIL;
1377 goto end;
1378 }
1379
1380 buffer_type_string = get_buffer_type_string(
1381 session->ust_session->buffer_type);
1382 if (!buffer_type_string) {
1383 ERR("Unsupported buffer type.");
1384 ret = LTTNG_ERR_INVALID;
1385 goto end;
1386 }
1387
1388 ret = config_writer_write_element_string(writer,
1389 config_element_buffer_type, buffer_type_string);
1390 if (ret) {
1391 ret = LTTNG_ERR_SAVE_IO_FAIL;
1392 goto end;
1393 }
1394
1395 ret = config_writer_open_element(writer, config_element_channels);
1396 if (ret) {
1397 ret = LTTNG_ERR_SAVE_IO_FAIL;
1398 goto end;
1399 }
1400
1401 rcu_read_lock();
1402 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1403 &iter.iter, node, node) {
fb198a11 1404 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
51755dc8 1405 if (domain == ust_chan->domain) {
fb198a11
JG
1406 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1407 if (ret) {
1408 rcu_read_unlock();
1409 goto end;
1410 }
1411 }
1412 }
1413 rcu_read_unlock();
1414
1415 /* /channels */
1416 ret = config_writer_close_element(writer);
1417 if (ret) {
1418 ret = LTTNG_ERR_SAVE_IO_FAIL;
1419 goto end;
1420 }
51755dc8 1421
e8fcabef 1422 if (domain == LTTNG_DOMAIN_UST) {
847a5916 1423 ret = config_writer_open_element(writer,
e8fcabef 1424 config_element_trackers);
847a5916
JR
1425 if (ret) {
1426 ret = LTTNG_ERR_SAVE_IO_FAIL;
1427 goto end;
1428 }
1429
e8fcabef 1430 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST);
847a5916 1431 if (ret) {
847a5916
JR
1432 goto end;
1433 }
1434
e8fcabef 1435 /* /trackers */
847a5916
JR
1436 ret = config_writer_close_element(writer);
1437 if (ret) {
847a5916
JR
1438 goto end;
1439 }
e8fcabef 1440 }
847a5916 1441
e8fcabef
JG
1442 /* /domain */
1443 ret = config_writer_close_element(writer);
1444 if (ret) {
1445 ret = LTTNG_ERR_SAVE_IO_FAIL;
1446 goto end;
847a5916 1447 }
e8fcabef 1448
847a5916 1449end:
847a5916
JR
1450 return ret;
1451}
1452
fb198a11
JG
1453static
1454int save_domains(struct config_writer *writer, struct ltt_session *session)
1455{
1456 int ret = 0;
1457
1458 assert(writer);
1459 assert(session);
1460
1461 if (!session->kernel_session && !session->ust_session) {
1462 goto end;
1463 }
1464
1465 ret = config_writer_open_element(writer, config_element_domains);
1466 if (ret) {
1467 ret = LTTNG_ERR_SAVE_IO_FAIL;
1468 goto end;
1469 }
1470
1471
1472 if (session->kernel_session) {
1473 ret = config_writer_open_element(writer,
1474 config_element_domain);
1475 if (ret) {
1476 ret = LTTNG_ERR_SAVE_IO_FAIL;
1477 goto end;
1478 }
1479
1480 ret = save_kernel_session(writer, session);
1481 if (ret) {
1482 goto end;
1483 }
1484
847a5916
JR
1485 ret = config_writer_open_element(writer,
1486 config_element_trackers);
1487 if (ret) {
1488 ret = LTTNG_ERR_SAVE_IO_FAIL;
1489 goto end;
1490 }
1491
1492 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL);
1493 if (ret) {
1494 goto end;
1495 }
1496
1497 /* /trackers */
1498 ret = config_writer_close_element(writer);
1499 if (ret) {
1500 ret = LTTNG_ERR_SAVE_IO_FAIL;
1501 goto end;
1502 }
fb198a11
JG
1503 /* /domain */
1504 ret = config_writer_close_element(writer);
1505 if (ret) {
1506 ret = LTTNG_ERR_SAVE_IO_FAIL;
1507 goto end;
1508 }
1509 }
1510
1511 if (session->ust_session) {
51755dc8 1512 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST);
fb198a11
JG
1513 if (ret) {
1514 goto end;
1515 }
1516
51755dc8 1517 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL);
fb198a11 1518 if (ret) {
fb198a11
JG
1519 goto end;
1520 }
fb198a11 1521
51755dc8
JG
1522 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J);
1523 if (ret) {
1524 goto end;
1525 }
65d72c41 1526
51755dc8
JG
1527 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON);
1528 if (ret) {
1529 goto end;
fb198a11
JG
1530 }
1531 }
1532
1533 /* /domains */
1534 ret = config_writer_close_element(writer);
1535 if (ret) {
1536 ret = LTTNG_ERR_SAVE_IO_FAIL;
1537 goto end;
1538 }
1539end:
1540 return ret;
1541}
1542
1543static
1544int save_consumer_output(struct config_writer *writer,
1545 struct consumer_output *output)
1546{
1547 int ret;
1548
1549 assert(writer);
1550 assert(output);
1551
1552 ret = config_writer_open_element(writer, config_element_consumer_output);
1553 if (ret) {
1554 ret = LTTNG_ERR_SAVE_IO_FAIL;
1555 goto end;
1556 }
1557
1558 ret = config_writer_write_element_bool(writer, config_element_enabled,
1559 output->enabled);
1560 if (ret) {
1561 ret = LTTNG_ERR_SAVE_IO_FAIL;
1562 goto end;
1563 }
1564
1565 ret = config_writer_open_element(writer, config_element_destination);
1566 if (ret) {
1567 ret = LTTNG_ERR_SAVE_IO_FAIL;
1568 goto end;
1569 }
1570
1571 switch (output->type) {
1572 case CONSUMER_DST_LOCAL:
1573 ret = config_writer_write_element_string(writer,
1574 config_element_path, output->dst.trace_path);
1575 if (ret) {
1576 ret = LTTNG_ERR_SAVE_IO_FAIL;
1577 goto end;
1578 }
1579 break;
1580 case CONSUMER_DST_NET:
1581 {
1582 char *uri;
1583
1584 uri = zmalloc(PATH_MAX);
1585 if (!uri) {
1586 ret = LTTNG_ERR_NOMEM;
1587 goto end;
1588 }
1589
1590 ret = config_writer_open_element(writer, config_element_net_output);
1591 if (ret) {
1592 ret = LTTNG_ERR_SAVE_IO_FAIL;
1593 goto end_net_output;
1594 }
1595
1596 if (output->dst.net.control_isset &&
1597 output->dst.net.data_isset) {
1598 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1599 if (ret < 0) {
1600 ret = LTTNG_ERR_INVALID;
1601 goto end_net_output;
1602 }
1603
1604 ret = config_writer_write_element_string(writer,
1605 config_element_control_uri, uri);
1606 if (ret) {
1607 ret = LTTNG_ERR_SAVE_IO_FAIL;
1608 goto end_net_output;
1609 }
1610
1611 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1612 if (ret < 0) {
1613 ret = LTTNG_ERR_INVALID;
1614 goto end_net_output;
1615 }
1616
1617 ret = config_writer_write_element_string(writer,
1618 config_element_data_uri, uri);
1619 if (ret) {
1620 ret = LTTNG_ERR_SAVE_IO_FAIL;
1621 goto end_net_output;
1622 }
1623
1624end_net_output:
1625 free(uri);
1626 if (ret) {
1627 goto end;
1628 }
1629 } else {
1630 ret = !output->dst.net.control_isset ?
1631 LTTNG_ERR_URL_CTRL_MISS :
1632 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1633 free(uri);
fb198a11
JG
1634 goto end;
1635 }
1636
1637 ret = config_writer_close_element(writer);
1638 if (ret) {
1639 ret = LTTNG_ERR_SAVE_IO_FAIL;
1640 goto end;
1641 }
1642 break;
1643 }
1644 default:
1645 ERR("Unsupported consumer output type.");
1646 ret = LTTNG_ERR_INVALID;
1647 goto end;
1648 }
1649
1650 /* /destination */
1651 ret = config_writer_close_element(writer);
1652 if (ret) {
1653 ret = LTTNG_ERR_SAVE_IO_FAIL;
1654 goto end;
1655 }
1656
1657 /* /consumer_output */
1658 ret = config_writer_close_element(writer);
1659 if (ret) {
1660 ret = LTTNG_ERR_SAVE_IO_FAIL;
1661 goto end;
1662 }
1663end:
1664 return ret;
1665}
1666
1667static
1668int save_snapshot_outputs(struct config_writer *writer,
1669 struct snapshot *snapshot)
1670{
1671 int ret;
1672 struct lttng_ht_iter iter;
1673 struct snapshot_output *output;
1674
1675 assert(writer);
1676 assert(snapshot);
1677
1678 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1679 if (ret) {
1680 ret = LTTNG_ERR_SAVE_IO_FAIL;
1681 goto end;
1682 }
1683
1684 rcu_read_lock();
1685 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1686 node.node) {
1687 ret = config_writer_open_element(writer,
1688 config_element_output);
1689 if (ret) {
1690 ret = LTTNG_ERR_SAVE_IO_FAIL;
1691 goto end_unlock;
1692 }
1693
1694 ret = config_writer_write_element_string(writer,
1695 config_element_name, output->name);
1696 if (ret) {
1697 ret = LTTNG_ERR_SAVE_IO_FAIL;
1698 goto end_unlock;
1699 }
1700
1701 ret = config_writer_write_element_unsigned_int(writer,
1702 config_element_max_size, output->max_size);
1703 if (ret) {
1704 ret = LTTNG_ERR_SAVE_IO_FAIL;
1705 goto end_unlock;
1706 }
1707
1708 ret = save_consumer_output(writer, output->consumer);
1709 if (ret) {
1710 goto end_unlock;
1711 }
1712
1713 /* /output */
1714 ret = config_writer_close_element(writer);
1715 if (ret) {
1716 ret = LTTNG_ERR_SAVE_IO_FAIL;
1717 goto end_unlock;
1718 }
1719 }
1720 rcu_read_unlock();
1721
1722 /* /snapshot_outputs */
1723 ret = config_writer_close_element(writer);
1724 if (ret) {
1725 ret = LTTNG_ERR_SAVE_IO_FAIL;
1726 goto end;
1727 }
1728
1729end:
1730 return ret;
1731end_unlock:
1732 rcu_read_unlock();
1733 return ret;
1734}
1735
1736static
1737int save_session_output(struct config_writer *writer,
1738 struct ltt_session *session)
1739{
1740 int ret;
1741
1742 assert(writer);
1743 assert(session);
1744
1745 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1746 (!session->snapshot_mode && !session->consumer)) {
1747 /* Session is in no output mode */
1748 ret = 0;
1749 goto end;
1750 }
1751
1752 ret = config_writer_open_element(writer, config_element_output);
1753 if (ret) {
1754 ret = LTTNG_ERR_SAVE_IO_FAIL;
1755 goto end;
1756 }
1757
1758 if (session->snapshot_mode) {
1759 ret = save_snapshot_outputs(writer, &session->snapshot);
1760 if (ret) {
1761 goto end;
1762 }
1763 } else {
1764 if (session->consumer) {
1765 ret = save_consumer_output(writer, session->consumer);
1766 if (ret) {
1767 goto end;
1768 }
1769 }
1770 }
1771
1772 /* /output */
1773 ret = config_writer_close_element(writer);
1774 if (ret) {
1775 ret = LTTNG_ERR_SAVE_IO_FAIL;
1776 goto end;
1777 }
1778end:
1779 return ret;
1780}
1781
1782/*
1783 * Save the given session.
1784 *
1785 * Return 0 on success else a LTTNG_ERR* code.
1786 */
1787static
1788int save_session(struct ltt_session *session,
1789 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1790{
1791 int ret, fd;
db471218 1792 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
1793 char config_file_path[PATH_MAX];
1794 size_t len;
1795 struct config_writer *writer = NULL;
1796 size_t session_name_len;
1797 const char *provided_path;
1798
1799 assert(session);
1800 assert(attr);
1801 assert(creds);
1802
1803 session_name_len = strlen(session->name);
95a29ab8 1804 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
1805
1806 if (!session_access_ok(session,
1807 LTTNG_SOCK_GET_UID_CRED(creds),
1808 LTTNG_SOCK_GET_GID_CRED(creds))) {
1809 ret = LTTNG_ERR_EPERM;
1810 goto end;
1811 }
1812
1813 provided_path = lttng_save_session_attr_get_output_url(attr);
1814 if (provided_path) {
95a29ab8 1815 DBG3("Save session in provided path %s", provided_path);
fb198a11 1816 len = strlen(provided_path);
d2992717 1817 if (len >= sizeof(config_file_path)) {
fb198a11
JG
1818 ret = LTTNG_ERR_SET_URL;
1819 goto end;
1820 }
1821 strncpy(config_file_path, provided_path, len);
1822 } else {
7e078ad1 1823 ssize_t ret_len;
fb198a11
JG
1824 char *home_dir = utils_get_user_home_dir(
1825 LTTNG_SOCK_GET_UID_CRED(creds));
1826 if (!home_dir) {
1827 ret = LTTNG_ERR_SET_URL;
1828 goto end;
1829 }
1830
d2992717 1831 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
1832 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1833 free(home_dir);
7e078ad1 1834 if (ret_len < 0) {
fb198a11
JG
1835 PERROR("snprintf save session");
1836 ret = LTTNG_ERR_SET_URL;
1837 goto end;
1838 }
7e078ad1 1839 len = ret_len;
fb198a11
JG
1840 }
1841
1842 /*
d2992717
DG
1843 * Check the path fits in the config file path dst including the '/'
1844 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 1845 */
d2992717
DG
1846 if ((len + session_name_len + 2 +
1847 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1848 > sizeof(config_file_path)) {
fb198a11
JG
1849 ret = LTTNG_ERR_SET_URL;
1850 goto end;
1851 }
1852
1853 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1854 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1855 if (ret) {
1856 ret = LTTNG_ERR_SET_URL;
1857 goto end;
1858 }
1859
d2992717
DG
1860 /*
1861 * At this point, we know that everything fits in the buffer. Validation
1862 * was done just above.
1863 */
fb198a11
JG
1864 config_file_path[len++] = '/';
1865 strncpy(config_file_path + len, session->name, session_name_len);
1866 len += session_name_len;
1867 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
1868 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1869 config_file_path[len] = '\0';
fb198a11
JG
1870
1871 if (!access(config_file_path, F_OK) && !attr->overwrite) {
f9b57ab2
DG
1872 /* File exists, notify the user since the overwrite flag is off. */
1873 ret = LTTNG_ERR_SAVE_FILE_EXIST;
fb198a11
JG
1874 goto end;
1875 }
1876
1877 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1878 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1879 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1880 if (fd < 0) {
1881 PERROR("Could not create configuration file");
1882 ret = LTTNG_ERR_SAVE_IO_FAIL;
1883 goto end;
1884 }
db471218 1885 file_opened = 1;
fb198a11 1886
705bb62f 1887 writer = config_writer_create(fd, 1);
fb198a11
JG
1888 if (!writer) {
1889 ret = LTTNG_ERR_NOMEM;
1890 goto end;
1891 }
1892
1893 ret = config_writer_open_element(writer, config_element_sessions);
1894 if (ret) {
1895 ret = LTTNG_ERR_SAVE_IO_FAIL;
1896 goto end;
1897 }
1898
1899 ret = config_writer_open_element(writer, config_element_session);
1900 if (ret) {
1901 ret = LTTNG_ERR_SAVE_IO_FAIL;
1902 goto end;
1903 }
1904
1905 ret = config_writer_write_element_string(writer, config_element_name,
1906 session->name);
1907 if (ret) {
1908 ret = LTTNG_ERR_SAVE_IO_FAIL;
1909 goto end;
1910 }
1911
9e7c9f56
JR
1912 if(session->shm_path[0] != '\0') {
1913 ret = config_writer_write_element_string(writer,
1914 config_element_shared_memory_path,
1915 session->shm_path);
1916 if (ret) {
1917 ret = LTTNG_ERR_SAVE_IO_FAIL;
1918 goto end;
1919 }
1920 }
1921
fb198a11
JG
1922 ret = save_domains(writer, session);
1923 if (ret) {
1924 goto end;
1925 }
1926
1927 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 1928 session->active);
fb198a11
JG
1929 if (ret) {
1930 ret = LTTNG_ERR_SAVE_IO_FAIL;
1931 goto end;
1932 }
1933
1934 if (session->snapshot_mode || session->live_timer) {
1935 ret = config_writer_open_element(writer, config_element_attributes);
1936 if (ret) {
1937 ret = LTTNG_ERR_SAVE_IO_FAIL;
1938 goto end;
1939 }
1940
1941 if (session->snapshot_mode) {
1942 ret = config_writer_write_element_bool(writer,
1943 config_element_snapshot_mode, 1);
1944 if (ret) {
1945 ret = LTTNG_ERR_SAVE_IO_FAIL;
1946 goto end;
1947 }
1948 } else {
d98ad589 1949 ret = config_writer_write_element_unsigned_int(writer,
fb198a11
JG
1950 config_element_live_timer_interval, session->live_timer);
1951 if (ret) {
1952 ret = LTTNG_ERR_SAVE_IO_FAIL;
1953 goto end;
1954 }
1955 }
1956
1957 /* /attributes */
1958 ret = config_writer_close_element(writer);
1959 if (ret) {
1960 ret = LTTNG_ERR_SAVE_IO_FAIL;
1961 goto end;
1962 }
1963 }
1964
1965 ret = save_session_output(writer, session);
1966 if (ret) {
1967 goto end;
1968 }
1969
1970 /* /session */
1971 ret = config_writer_close_element(writer);
1972 if (ret) {
1973 ret = LTTNG_ERR_SAVE_IO_FAIL;
1974 goto end;
1975 }
1976
1977 /* /sessions */
1978 ret = config_writer_close_element(writer);
1979 if (ret) {
1980 ret = LTTNG_ERR_SAVE_IO_FAIL;
1981 goto end;
1982 }
1983end:
1984 if (writer && config_writer_destroy(writer)) {
1985 /* Preserve the original error code */
1986 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1987 }
1988 if (ret) {
1989 /* Delete file in case of error */
db471218 1990 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
1991 PERROR("Unlinking XML session configuration.");
1992 }
1993 }
1994
1995 return ret;
1996}
1997
1998int cmd_save_sessions(struct lttng_save_session_attr *attr,
1999 lttng_sock_cred *creds)
2000{
2001 int ret;
2002 const char *session_name;
2003 struct ltt_session *session;
2004
2005 session_lock_list();
2006
2007 session_name = lttng_save_session_attr_get_session_name(attr);
2008 if (session_name) {
2009 session = session_find_by_name(session_name);
2010 if (!session) {
2011 ret = LTTNG_ERR_SESS_NOT_FOUND;
2012 goto end;
2013 }
2014
2015 session_lock(session);
2016 ret = save_session(session, attr, creds);
2017 session_unlock(session);
2018 if (ret) {
2019 goto end;
2020 }
2021 } else {
2022 struct ltt_session_list *list = session_get_list();
2023
2024 cds_list_for_each_entry(session, &list->head, list) {
2025 session_lock(session);
2026 ret = save_session(session, attr, creds);
2027 session_unlock(session);
2028
2029 /* Don't abort if we don't have the required permissions. */
2030 if (ret && ret != LTTNG_ERR_EPERM) {
2031 goto end;
2032 }
2033 }
2034 }
2035 ret = LTTNG_OK;
2036
2037end:
2038 session_unlock_list();
2039 return ret;
2040}
This page took 0.11059 seconds and 4 git commands to generate.