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