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