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