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