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