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