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