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