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