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