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