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