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