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