Implement MI and save/load support for callstack contexts
[lttng-tools.git] / src / bin / lttng-sessiond / save.c
1 /*
2 * Copyright (C) 2014 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #define _LGPL_SOURCE
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>
27 #include <common/config/session-config.h>
28 #include <common/utils.h>
29 #include <common/runas.h>
30 #include <lttng/save-internal.h>
31
32 #include "kernel.h"
33 #include "save.h"
34 #include "session.h"
35 #include "lttng-syscall.h"
36 #include "trace-ust.h"
37 #include "agent.h"
38
39 static
40 int 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 }
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 }
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 }
125 }
126
127 end:
128 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
129 }
130
131 static
132 int save_ust_channel_attributes(struct config_writer *writer,
133 struct lttng_ust_channel_attr *attr)
134 {
135 int ret;
136 struct ltt_ust_channel *channel = NULL;
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 }
180
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
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
200 end:
201 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
202 }
203
204 static
205 const 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
239 static
240 const 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;
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;
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;
294 default:
295 context_type_string = NULL;
296 }
297
298 return context_type_string;
299 }
300
301 static
302 const 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;
323 case LTTNG_UST_CONTEXT_APP_CONTEXT:
324 context_type_string = config_event_context_app;
325 break;
326 case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
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 */
331 default:
332 context_type_string = NULL;
333 break;
334 }
335
336 return context_type_string;
337 }
338
339 static
340 const 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
362 static
363 const 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
385 static
386 int 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
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
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) {
450 case LTTNG_KERNEL_SYSCALL:
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 }
560 end:
561 return ret;
562 }
563
564 static
565 int save_kernel_events(struct config_writer *writer,
566 struct ltt_kernel_channel *kchan)
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
577 cds_list_for_each_entry(event, &kchan->events_list.head, list) {
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 }
590 end:
591 return ret;
592 }
593
594 static
595 int 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
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 }
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,
682 LTTNG_EVENT_EXCLUSION_NAME_AT(
683 event->exclusion, i));
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 }
704 end:
705 return ret;
706 }
707
708 static
709 int 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
727 if (event->internal) {
728 /* Internal events must not be exposed to clients */
729 continue;
730 }
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 }
745 end:
746 return ret;
747 }
748
749 static
750 int init_ust_event_from_agent_event(struct ltt_ust_event *ust_event,
751 struct agent_event *agent_event)
752 {
753 int ret = 0;
754 enum lttng_ust_loglevel_type ust_loglevel_type;
755
756 ust_event->enabled = agent_event->enabled;
757 ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT;
758 if (lttng_strncpy(ust_event->attr.name, agent_event->name,
759 LTTNG_SYMBOL_NAME_LEN)) {
760 ret = -1;
761 goto end;
762 }
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;
780 ust_event->attr.loglevel = agent_event->loglevel_value;
781 ust_event->filter_expression = agent_event->filter_expression;
782 ust_event->exclusion = agent_event->exclusion;
783 end:
784 return ret;
785 }
786
787 static
788 int save_agent_events(struct config_writer *writer,
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 */
816 ret = init_ust_event_from_agent_event(&fake_event, agent_event);
817 if (ret) {
818 rcu_read_unlock();
819 goto end;
820 }
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 }
835 end:
836 return ret;
837 }
838
839 static
840 int 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
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
855 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
856 ret = config_writer_open_element(writer,
857 config_element_context_perf);
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
915 end:
916 return ret;
917 }
918
919 static
920 int save_kernel_contexts(struct config_writer *writer,
921 struct ltt_kernel_channel *kchan)
922 {
923 int ret;
924 struct ltt_kernel_context *ctx;
925
926 if (cds_list_empty(&kchan->ctx_list)) {
927 ret = 0;
928 goto end;
929 }
930
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
944 /* /contexts */
945 ret = config_writer_close_element(writer);
946 if (ret) {
947 ret = LTTNG_ERR_SAVE_IO_FAIL;
948 goto end;
949 }
950 end:
951 return ret;
952 }
953
954 static
955 int 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 }
997 end:
998 return ret;
999 }
1000
1001 static
1002 int 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 }
1039 end:
1040 return ret;
1041 }
1042
1043 static
1044 int 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 }
1068 end:
1069 return ret;
1070 }
1071
1072 static
1073 int 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) {
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
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;
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 }
1125 end:
1126 return ret;
1127 }
1128
1129 static
1130 int 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
1163 ret = save_kernel_events(writer, kchan);
1164 if (ret) {
1165 goto end;
1166 }
1167
1168 ret = save_kernel_contexts(writer, kchan);
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 }
1179 end:
1180 return ret;
1181 }
1182
1183 static
1184 int 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
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 */
1262 ret = save_agent_events(writer, agent);
1263 if (ret) {
1264 goto end;
1265 }
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 }
1279 end:
1280 return ret;
1281 }
1282
1283 static
1284 int 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 }
1328 end:
1329 return ret;
1330 }
1331
1332 static
1333 const 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
1360 static
1361 int 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 }
1448 end:
1449 free(pids);
1450 return ret;
1451 }
1452
1453 static
1454 int save_ust_domain(struct config_writer *writer,
1455 struct ltt_session *session, enum lttng_domain_type domain)
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;
1462 const char *config_domain_name;
1463
1464 assert(writer);
1465 assert(session);
1466
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);
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) {
1511 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
1512 if (domain == ust_chan->domain) {
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 }
1528
1529 if (domain == LTTNG_DOMAIN_UST) {
1530 ret = config_writer_open_element(writer,
1531 config_element_trackers);
1532 if (ret) {
1533 ret = LTTNG_ERR_SAVE_IO_FAIL;
1534 goto end;
1535 }
1536
1537 ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST);
1538 if (ret) {
1539 goto end;
1540 }
1541
1542 /* /trackers */
1543 ret = config_writer_close_element(writer);
1544 if (ret) {
1545 goto end;
1546 }
1547 }
1548
1549 /* /domain */
1550 ret = config_writer_close_element(writer);
1551 if (ret) {
1552 ret = LTTNG_ERR_SAVE_IO_FAIL;
1553 goto end;
1554 }
1555
1556 end:
1557 return ret;
1558 }
1559
1560 static
1561 int 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
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 }
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) {
1619 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST);
1620 if (ret) {
1621 goto end;
1622 }
1623
1624 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL);
1625 if (ret) {
1626 goto end;
1627 }
1628
1629 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J);
1630 if (ret) {
1631 goto end;
1632 }
1633
1634 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON);
1635 if (ret) {
1636 goto end;
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 }
1646 end:
1647 return ret;
1648 }
1649
1650 static
1651 int 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,
1681 config_element_path, output->dst.session_root_path);
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
1731 end_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;
1740 free(uri);
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 }
1770 end:
1771 return ret;
1772 }
1773
1774 static
1775 int 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
1836 end:
1837 return ret;
1838 end_unlock:
1839 rcu_read_unlock();
1840 return ret;
1841 }
1842
1843 static
1844 int 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 }
1885 end:
1886 return ret;
1887 }
1888
1889 /*
1890 * Save the given session.
1891 *
1892 * Return 0 on success else a LTTNG_ERR* code.
1893 */
1894 static
1895 int save_session(struct ltt_session *session,
1896 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1897 {
1898 int ret, fd;
1899 unsigned int file_opened = 0; /* Indicate if the file has been opened */
1900 char config_file_path[PATH_MAX];
1901 size_t len;
1902 struct config_writer *writer = NULL;
1903 size_t session_name_len;
1904 const char *provided_path;
1905
1906 assert(session);
1907 assert(attr);
1908 assert(creds);
1909
1910 session_name_len = strlen(session->name);
1911 memset(config_file_path, 0, sizeof(config_file_path));
1912
1913 if (!session_access_ok(session,
1914 LTTNG_SOCK_GET_UID_CRED(creds),
1915 LTTNG_SOCK_GET_GID_CRED(creds))) {
1916 ret = LTTNG_ERR_EPERM;
1917 goto end;
1918 }
1919
1920 provided_path = lttng_save_session_attr_get_output_url(attr);
1921 if (provided_path) {
1922 DBG3("Save session in provided path %s", provided_path);
1923 len = strlen(provided_path);
1924 if (len >= sizeof(config_file_path)) {
1925 ret = LTTNG_ERR_SET_URL;
1926 goto end;
1927 }
1928 strncpy(config_file_path, provided_path, len);
1929 } else {
1930 ssize_t ret_len;
1931 char *home_dir = utils_get_user_home_dir(
1932 LTTNG_SOCK_GET_UID_CRED(creds));
1933 if (!home_dir) {
1934 ret = LTTNG_ERR_SET_URL;
1935 goto end;
1936 }
1937
1938 ret_len = snprintf(config_file_path, sizeof(config_file_path),
1939 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1940 free(home_dir);
1941 if (ret_len < 0) {
1942 PERROR("snprintf save session");
1943 ret = LTTNG_ERR_SET_URL;
1944 goto end;
1945 }
1946 len = ret_len;
1947 }
1948
1949 /*
1950 * Check the path fits in the config file path dst including the '/'
1951 * followed by trailing .lttng extension and the NULL terminated string.
1952 */
1953 if ((len + session_name_len + 2 +
1954 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1955 > sizeof(config_file_path)) {
1956 ret = LTTNG_ERR_SET_URL;
1957 goto end;
1958 }
1959
1960 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1961 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1962 if (ret) {
1963 ret = LTTNG_ERR_SET_URL;
1964 goto end;
1965 }
1966
1967 /*
1968 * At this point, we know that everything fits in the buffer. Validation
1969 * was done just above.
1970 */
1971 config_file_path[len++] = '/';
1972 strncpy(config_file_path + len, session->name, session_name_len);
1973 len += session_name_len;
1974 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1975 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1976 config_file_path[len] = '\0';
1977
1978 if (!access(config_file_path, F_OK) && !attr->overwrite) {
1979 /* File exists, notify the user since the overwrite flag is off. */
1980 ret = LTTNG_ERR_SAVE_FILE_EXIST;
1981 goto end;
1982 }
1983
1984 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1985 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1986 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1987 if (fd < 0) {
1988 PERROR("Could not create configuration file");
1989 ret = LTTNG_ERR_SAVE_IO_FAIL;
1990 goto end;
1991 }
1992 file_opened = 1;
1993
1994 writer = config_writer_create(fd, 1);
1995 if (!writer) {
1996 ret = LTTNG_ERR_NOMEM;
1997 goto end;
1998 }
1999
2000 ret = config_writer_open_element(writer, config_element_sessions);
2001 if (ret) {
2002 ret = LTTNG_ERR_SAVE_IO_FAIL;
2003 goto end;
2004 }
2005
2006 ret = config_writer_open_element(writer, config_element_session);
2007 if (ret) {
2008 ret = LTTNG_ERR_SAVE_IO_FAIL;
2009 goto end;
2010 }
2011
2012 ret = config_writer_write_element_string(writer, config_element_name,
2013 session->name);
2014 if (ret) {
2015 ret = LTTNG_ERR_SAVE_IO_FAIL;
2016 goto end;
2017 }
2018
2019 if(session->shm_path[0] != '\0') {
2020 ret = config_writer_write_element_string(writer,
2021 config_element_shared_memory_path,
2022 session->shm_path);
2023 if (ret) {
2024 ret = LTTNG_ERR_SAVE_IO_FAIL;
2025 goto end;
2026 }
2027 }
2028
2029 ret = save_domains(writer, session);
2030 if (ret) {
2031 goto end;
2032 }
2033
2034 ret = config_writer_write_element_bool(writer, config_element_started,
2035 session->active);
2036 if (ret) {
2037 ret = LTTNG_ERR_SAVE_IO_FAIL;
2038 goto end;
2039 }
2040
2041 if (session->snapshot_mode || session->live_timer ||
2042 session->rotate_timer_period || session->rotate_size) {
2043 ret = config_writer_open_element(writer, config_element_attributes);
2044 if (ret) {
2045 ret = LTTNG_ERR_SAVE_IO_FAIL;
2046 goto end;
2047 }
2048
2049 if (session->snapshot_mode) {
2050 ret = config_writer_write_element_bool(writer,
2051 config_element_snapshot_mode, 1);
2052 if (ret) {
2053 ret = LTTNG_ERR_SAVE_IO_FAIL;
2054 goto end;
2055 }
2056 } else if (session->live_timer) {
2057 ret = config_writer_write_element_unsigned_int(writer,
2058 config_element_live_timer_interval, session->live_timer);
2059 if (ret) {
2060 ret = LTTNG_ERR_SAVE_IO_FAIL;
2061 goto end;
2062 }
2063 }
2064 if (session->rotate_timer_period) {
2065 ret = config_writer_write_element_unsigned_int(writer,
2066 config_element_rotation_timer_interval,
2067 session->rotate_timer_period);
2068 if (ret) {
2069 ret = LTTNG_ERR_SAVE_IO_FAIL;
2070 goto end;
2071 }
2072 }
2073
2074 if (session->rotate_size) {
2075 ret = config_writer_write_element_unsigned_int(writer,
2076 config_element_rotation_size,
2077 session->rotate_size);
2078 if (ret) {
2079 ret = LTTNG_ERR_SAVE_IO_FAIL;
2080 goto end;
2081 }
2082 }
2083
2084 /* /attributes */
2085 ret = config_writer_close_element(writer);
2086 if (ret) {
2087 ret = LTTNG_ERR_SAVE_IO_FAIL;
2088 goto end;
2089 }
2090 }
2091
2092 ret = save_session_output(writer, session);
2093 if (ret) {
2094 goto end;
2095 }
2096
2097 /* /session */
2098 ret = config_writer_close_element(writer);
2099 if (ret) {
2100 ret = LTTNG_ERR_SAVE_IO_FAIL;
2101 goto end;
2102 }
2103
2104 /* /sessions */
2105 ret = config_writer_close_element(writer);
2106 if (ret) {
2107 ret = LTTNG_ERR_SAVE_IO_FAIL;
2108 goto end;
2109 }
2110 end:
2111 if (writer && config_writer_destroy(writer)) {
2112 /* Preserve the original error code */
2113 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
2114 }
2115 if (ret) {
2116 /* Delete file in case of error */
2117 if (file_opened && unlink(config_file_path)) {
2118 PERROR("Unlinking XML session configuration.");
2119 }
2120 }
2121
2122 if (file_opened) {
2123 ret = close(fd);
2124 if (ret) {
2125 PERROR("Closing XML session configuration");
2126 }
2127 }
2128
2129 return ret;
2130 }
2131
2132 int cmd_save_sessions(struct lttng_save_session_attr *attr,
2133 lttng_sock_cred *creds)
2134 {
2135 int ret;
2136 const char *session_name;
2137 struct ltt_session *session;
2138
2139 session_lock_list();
2140
2141 session_name = lttng_save_session_attr_get_session_name(attr);
2142 if (session_name) {
2143 session = session_find_by_name(session_name);
2144 if (!session) {
2145 ret = LTTNG_ERR_SESS_NOT_FOUND;
2146 goto end;
2147 }
2148
2149 session_lock(session);
2150 ret = save_session(session, attr, creds);
2151 session_unlock(session);
2152 if (ret) {
2153 goto end;
2154 }
2155 } else {
2156 struct ltt_session_list *list = session_get_list();
2157
2158 cds_list_for_each_entry(session, &list->head, list) {
2159 session_lock(session);
2160 ret = save_session(session, attr, creds);
2161 session_unlock(session);
2162
2163 /* Don't abort if we don't have the required permissions. */
2164 if (ret && ret != LTTNG_ERR_EPERM) {
2165 goto end;
2166 }
2167 }
2168 }
2169 ret = LTTNG_OK;
2170
2171 end:
2172 session_unlock_list();
2173 return ret;
2174 }
This page took 0.11412 seconds and 5 git commands to generate.