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