action executor: execute action only if the associated trigger is registered
[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,
fc4b93fa 137 struct lttng_ust_abi_channel_attr *attr)
fb198a11
JG
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,
fc4b93fa 184 attr->output == LTTNG_UST_ABI_MMAP ?
fb198a11
JG
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(
fc4b93fa 379 enum lttng_ust_abi_context_type context_type)
fb198a11
JG
380{
381 const char *context_type_string;
382
383 switch (context_type) {
fc4b93fa 384 case LTTNG_UST_ABI_CONTEXT_PROCNAME:
fb198a11
JG
385 context_type_string = config_event_context_procname;
386 break;
fc4b93fa 387 case LTTNG_UST_ABI_CONTEXT_VPID:
fb198a11
JG
388 context_type_string = config_event_context_vpid;
389 break;
fc4b93fa 390 case LTTNG_UST_ABI_CONTEXT_VTID:
fb198a11
JG
391 context_type_string = config_event_context_vtid;
392 break;
fc4b93fa 393 case LTTNG_UST_ABI_CONTEXT_IP:
fb198a11
JG
394 context_type_string = config_event_context_ip;
395 break;
fc4b93fa 396 case LTTNG_UST_ABI_CONTEXT_PTHREAD_ID:
fb198a11
JG
397 context_type_string = config_event_context_pthread_id;
398 break;
fc4b93fa 399 case LTTNG_UST_ABI_CONTEXT_APP_CONTEXT:
045fc617
JG
400 context_type_string = config_event_context_app;
401 break;
fc4b93fa 402 case LTTNG_UST_ABI_CONTEXT_CGROUP_NS:
f17b8732
MJ
403 context_type_string = config_event_context_cgroup_ns;
404 break;
fc4b93fa 405 case LTTNG_UST_ABI_CONTEXT_IPC_NS:
f17b8732
MJ
406 context_type_string = config_event_context_ipc_ns;
407 break;
fc4b93fa 408 case LTTNG_UST_ABI_CONTEXT_MNT_NS:
f17b8732
MJ
409 context_type_string = config_event_context_mnt_ns;
410 break;
fc4b93fa 411 case LTTNG_UST_ABI_CONTEXT_NET_NS:
f17b8732
MJ
412 context_type_string = config_event_context_net_ns;
413 break;
fc4b93fa 414 case LTTNG_UST_ABI_CONTEXT_TIME_NS:
d37ac3cd
MJ
415 context_type_string = config_event_context_time_ns;
416 break;
fc4b93fa 417 case LTTNG_UST_ABI_CONTEXT_PID_NS:
f17b8732
MJ
418 context_type_string = config_event_context_pid_ns;
419 break;
fc4b93fa 420 case LTTNG_UST_ABI_CONTEXT_USER_NS:
f17b8732
MJ
421 context_type_string = config_event_context_user_ns;
422 break;
fc4b93fa 423 case LTTNG_UST_ABI_CONTEXT_UTS_NS:
f17b8732
MJ
424 context_type_string = config_event_context_uts_ns;
425 break;
fc4b93fa 426 case LTTNG_UST_ABI_CONTEXT_VUID:
4fc59cb8
MJ
427 context_type_string = config_event_context_vuid;
428 break;
fc4b93fa 429 case LTTNG_UST_ABI_CONTEXT_VEUID:
4fc59cb8
MJ
430 context_type_string = config_event_context_veuid;
431 break;
fc4b93fa 432 case LTTNG_UST_ABI_CONTEXT_VSUID:
4fc59cb8
MJ
433 context_type_string = config_event_context_vsuid;
434 break;
fc4b93fa 435 case LTTNG_UST_ABI_CONTEXT_VGID:
4fc59cb8
MJ
436 context_type_string = config_event_context_vgid;
437 break;
fc4b93fa 438 case LTTNG_UST_ABI_CONTEXT_VEGID:
4fc59cb8
MJ
439 context_type_string = config_event_context_vegid;
440 break;
fc4b93fa 441 case LTTNG_UST_ABI_CONTEXT_VSGID:
4fc59cb8
MJ
442 context_type_string = config_event_context_vsgid;
443 break;
fc4b93fa 444 case LTTNG_UST_ABI_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(
fc4b93fa 482 enum lttng_ust_abi_loglevel_type loglevel_type)
fb198a11
JG
483{
484 const char *loglevel_type_string;
485
486 switch (loglevel_type) {
fc4b93fa 487 case LTTNG_UST_ABI_LOGLEVEL_ALL:
fb198a11
JG
488 loglevel_type_string = config_loglevel_type_all;
489 break;
fc4b93fa 490 case LTTNG_UST_ABI_LOGLEVEL_RANGE:
fb198a11
JG
491 loglevel_type_string = config_loglevel_type_range;
492 break;
fc4b93fa 493 case LTTNG_UST_ABI_LOGLEVEL_SINGLE:
fb198a11
JG
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
fc4b93fa 1054 if (event->attr.instrumentation != LTTNG_UST_ABI_TRACEPOINT) {
fb198a11
JG
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 1081 /* The log level is irrelevant if no "filtering" is enabled */
fc4b93fa 1082 if (event->attr.loglevel_type != LTTNG_UST_ABI_LOGLEVEL_ALL) {
1adbdb10
JG
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;
fc4b93fa 1191 enum lttng_ust_abi_loglevel_type ust_loglevel_type;
0b35b846 1192
44760c20 1193 ust_event->enabled = AGENT_EVENT_IS_ENABLED(agent_event);
fc4b93fa 1194 ust_event->attr.instrumentation = LTTNG_UST_ABI_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:
fc4b93fa 1202 ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_ALL;
0b35b846
JG
1203 break;
1204 case LTTNG_EVENT_LOGLEVEL_SINGLE:
fc4b93fa 1205 ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_SINGLE;
0b35b846
JG
1206 break;
1207 case LTTNG_EVENT_LOGLEVEL_RANGE:
fc4b93fa 1208 ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_RANGE;
0b35b846
JG
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) {
51755dc8
JG
1243 struct agent_event *agent_event;
1244 struct ltt_ust_event fake_event;
1245
1246 memset(&fake_event, 0, sizeof(fake_event));
1247 agent_event = caa_container_of(node, struct agent_event, node);
1248
1249 /*
1250 * Initialize a fake ust event to reuse the same serialization
1251 * function since UST and agent events contain the same info
1252 * (and one could wonder why they don't reuse the same
1253 * structures...).
1254 */
0b35b846 1255 ret = init_ust_event_from_agent_event(&fake_event, agent_event);
55c9e7ca 1256 if (ret != LTTNG_OK) {
0b35b846
JG
1257 rcu_read_unlock();
1258 goto end;
1259 }
51755dc8 1260 ret = save_ust_event(writer, &fake_event);
55c9e7ca 1261 if (ret != LTTNG_OK) {
51755dc8
JG
1262 rcu_read_unlock();
1263 goto end;
1264 }
1265 }
1266 rcu_read_unlock();
1267
1268 /* /events */
1269 ret = config_writer_close_element(writer);
1270 if (ret) {
1271 ret = LTTNG_ERR_SAVE_IO_FAIL;
1272 goto end;
1273 }
55c9e7ca
JR
1274
1275 ret = LTTNG_OK;
51755dc8
JG
1276end:
1277 return ret;
1278}
1279
55c9e7ca 1280/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1281static
1282int save_kernel_context(struct config_writer *writer,
1283 struct lttng_kernel_context *ctx)
1284{
55c9e7ca 1285 int ret = LTTNG_OK;
fb198a11
JG
1286
1287 if (!ctx) {
1288 goto end;
1289 }
1290
fb198a11
JG
1291 ret = config_writer_open_element(writer, config_element_context);
1292 if (ret) {
1293 ret = LTTNG_ERR_SAVE_IO_FAIL;
1294 goto end;
1295 }
1296
cba45eda 1297 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
045fc617
JG
1298 ret = config_writer_open_element(writer,
1299 config_element_context_perf);
fb198a11
JG
1300 if (ret) {
1301 ret = LTTNG_ERR_SAVE_IO_FAIL;
1302 goto end;
1303 }
1304
1305 ret = config_writer_write_element_unsigned_int(writer,
1306 config_element_type, ctx->u.perf_counter.type);
1307 if (ret) {
1308 ret = LTTNG_ERR_SAVE_IO_FAIL;
1309 goto end;
1310 }
1311
1312 ret = config_writer_write_element_unsigned_int(writer,
1313 config_element_config, ctx->u.perf_counter.config);
1314 if (ret) {
1315 ret = LTTNG_ERR_SAVE_IO_FAIL;
1316 goto end;
1317 }
1318
1319 ret = config_writer_write_element_string(writer,
1320 config_element_name, ctx->u.perf_counter.name);
1321 if (ret) {
1322 ret = LTTNG_ERR_SAVE_IO_FAIL;
1323 goto end;
1324 }
1325
1326 /* /perf */
1327 ret = config_writer_close_element(writer);
1328 if (ret) {
1329 ret = LTTNG_ERR_SAVE_IO_FAIL;
1330 goto end;
1331 }
1332 } else {
1333 const char *context_type_string =
1334 get_kernel_context_type_string(ctx->ctx);
1335
1336 if (!context_type_string) {
1337 ERR("Unsupported kernel context type.");
1338 ret = LTTNG_ERR_INVALID;
1339 goto end;
1340 }
1341
1342 ret = config_writer_write_element_string(writer,
1343 config_element_type, context_type_string);
1344 if (ret) {
1345 ret = LTTNG_ERR_SAVE_IO_FAIL;
1346 goto end;
1347 }
1348 }
1349
1350 /* /context */
1351 ret = config_writer_close_element(writer);
1352 if (ret) {
1353 ret = LTTNG_ERR_SAVE_IO_FAIL;
1354 goto end;
1355 }
1356
55c9e7ca 1357 ret = LTTNG_OK;
645328ae
DG
1358end:
1359 return ret;
1360}
1361
55c9e7ca 1362/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
645328ae
DG
1363static
1364int save_kernel_contexts(struct config_writer *writer,
1365 struct ltt_kernel_channel *kchan)
1366{
1367 int ret;
1368 struct ltt_kernel_context *ctx;
1369
2aa64052 1370 if (cds_list_empty(&kchan->ctx_list)) {
55c9e7ca 1371 ret = LTTNG_OK;
2aa64052
JG
1372 goto end;
1373 }
1374
645328ae
DG
1375 ret = config_writer_open_element(writer, config_element_contexts);
1376 if (ret) {
1377 ret = LTTNG_ERR_SAVE_IO_FAIL;
1378 goto end;
1379 }
1380
1381 cds_list_for_each_entry(ctx, &kchan->ctx_list, list) {
1382 ret = save_kernel_context(writer, &ctx->ctx);
55c9e7ca 1383 if (ret != LTTNG_OK) {
645328ae
DG
1384 goto end;
1385 }
1386 }
1387
fb198a11
JG
1388 /* /contexts */
1389 ret = config_writer_close_element(writer);
1390 if (ret) {
1391 ret = LTTNG_ERR_SAVE_IO_FAIL;
1392 goto end;
1393 }
55c9e7ca
JR
1394
1395 ret = LTTNG_OK;
fb198a11
JG
1396end:
1397 return ret;
1398}
1399
55c9e7ca 1400/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
045fc617
JG
1401static
1402int save_ust_context_perf_thread_counter(struct config_writer *writer,
1403 struct ltt_ust_context *ctx)
1404{
1405 int ret;
1406
1407 assert(writer);
1408 assert(ctx);
1409
1410 /* Perf contexts are saved as event_perf_context_type */
1411 ret = config_writer_open_element(writer, config_element_context_perf);
1412 if (ret) {
1413 ret = LTTNG_ERR_SAVE_IO_FAIL;
1414 goto end;
1415 }
1416
1417 ret = config_writer_write_element_unsigned_int(writer,
1418 config_element_type, ctx->ctx.u.perf_counter.type);
1419 if (ret) {
1420 ret = LTTNG_ERR_SAVE_IO_FAIL;
1421 goto end;
1422 }
1423
1424 ret = config_writer_write_element_unsigned_int(writer,
1425 config_element_config, ctx->ctx.u.perf_counter.config);
1426 if (ret) {
1427 ret = LTTNG_ERR_SAVE_IO_FAIL;
1428 goto end;
1429 }
1430
1431 ret = config_writer_write_element_string(writer, config_element_name,
1432 ctx->ctx.u.perf_counter.name);
1433 if (ret) {
1434 ret = LTTNG_ERR_SAVE_IO_FAIL;
1435 goto end;
1436 }
1437
1438 /* /perf */
1439 ret = config_writer_close_element(writer);
1440 if (ret) {
1441 ret = LTTNG_ERR_SAVE_IO_FAIL;
1442 goto end;
1443 }
55c9e7ca
JR
1444
1445 ret = LTTNG_OK;
045fc617
JG
1446end:
1447 return ret;
1448}
1449
55c9e7ca 1450/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
045fc617
JG
1451static
1452int save_ust_context_app_ctx(struct config_writer *writer,
1453 struct ltt_ust_context *ctx)
1454{
1455 int ret;
1456
1457 assert(writer);
1458 assert(ctx);
1459
1460 /* Application contexts are saved as application_context_type */
1461 ret = config_writer_open_element(writer, config_element_context_app);
1462 if (ret) {
1463 ret = LTTNG_ERR_SAVE_IO_FAIL;
1464 goto end;
1465 }
1466
1467 ret = config_writer_write_element_string(writer,
1468 config_element_context_app_provider_name,
1469 ctx->ctx.u.app_ctx.provider_name);
1470 if (ret) {
1471 ret = LTTNG_ERR_SAVE_IO_FAIL;
1472 goto end;
1473 }
1474
1475 ret = config_writer_write_element_string(writer,
1476 config_element_context_app_ctx_name,
1477 ctx->ctx.u.app_ctx.ctx_name);
1478 if (ret) {
1479 ret = LTTNG_ERR_SAVE_IO_FAIL;
1480 goto end;
1481 }
1482
1483 /* /app */
1484 ret = config_writer_close_element(writer);
1485 if (ret) {
1486 ret = LTTNG_ERR_SAVE_IO_FAIL;
1487 goto end;
1488 }
55c9e7ca
JR
1489
1490 ret = LTTNG_OK;
045fc617
JG
1491end:
1492 return ret;
1493}
1494
55c9e7ca 1495/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
045fc617
JG
1496static
1497int save_ust_context_generic(struct config_writer *writer,
1498 struct ltt_ust_context *ctx)
1499{
1500 int ret;
1501 const char *context_type_string;
1502
1503 assert(writer);
1504 assert(ctx);
1505
1506 /* Save context as event_context_type_type */
1507 context_type_string = get_ust_context_type_string(
1508 ctx->ctx.ctx);
1509 if (!context_type_string) {
1510 ERR("Unsupported UST context type.");
1511 ret = LTTNG_ERR_SAVE_IO_FAIL;
1512 goto end;
1513 }
1514
1515 ret = config_writer_write_element_string(writer,
1516 config_element_type, context_type_string);
1517 if (ret) {
1518 ret = LTTNG_ERR_SAVE_IO_FAIL;
1519 goto end;
1520 }
55c9e7ca
JR
1521
1522 ret = LTTNG_OK;
045fc617
JG
1523end:
1524 return ret;
1525}
1526
55c9e7ca 1527/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1528static
1529int save_ust_context(struct config_writer *writer,
1530 struct cds_list_head *ctx_list)
1531{
1532 int ret;
1533 struct ltt_ust_context *ctx;
1534
1535 assert(writer);
1536 assert(ctx_list);
1537
1538 ret = config_writer_open_element(writer, config_element_contexts);
1539 if (ret) {
1540 ret = LTTNG_ERR_SAVE_IO_FAIL;
1541 goto end;
1542 }
1543
1544 cds_list_for_each_entry(ctx, ctx_list, list) {
fb198a11
JG
1545 ret = config_writer_open_element(writer,
1546 config_element_context);
1547 if (ret) {
1548 ret = LTTNG_ERR_SAVE_IO_FAIL;
1549 goto end;
1550 }
1551
045fc617 1552 switch (ctx->ctx.ctx) {
fc4b93fa 1553 case LTTNG_UST_ABI_CONTEXT_PERF_THREAD_COUNTER:
045fc617
JG
1554 ret = save_ust_context_perf_thread_counter(writer, ctx);
1555 break;
fc4b93fa 1556 case LTTNG_UST_ABI_CONTEXT_APP_CONTEXT:
045fc617
JG
1557 ret = save_ust_context_app_ctx(writer, ctx);
1558 break;
1559 default:
1560 /* Save generic context. */
1561 ret = save_ust_context_generic(writer, ctx);
1562 }
55c9e7ca 1563 if (ret != LTTNG_OK) {
045fc617 1564 goto end;
fb198a11
JG
1565 }
1566
1567 /* /context */
1568 ret = config_writer_close_element(writer);
1569 if (ret) {
1570 ret = LTTNG_ERR_SAVE_IO_FAIL;
1571 goto end;
1572 }
1573 }
1574
1575 /* /contexts */
1576 ret = config_writer_close_element(writer);
1577 if (ret) {
1578 ret = LTTNG_ERR_SAVE_IO_FAIL;
1579 goto end;
1580 }
55c9e7ca
JR
1581
1582 ret = LTTNG_OK;
fb198a11
JG
1583end:
1584 return ret;
1585}
1586
55c9e7ca 1587/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1588static
1589int save_kernel_channel(struct config_writer *writer,
1590 struct ltt_kernel_channel *kchan)
1591{
1592 int ret;
1593
1594 assert(writer);
1595 assert(kchan);
1596
1597 ret = config_writer_open_element(writer, config_element_channel);
1598 if (ret) {
1599 ret = LTTNG_ERR_SAVE_IO_FAIL;
1600 goto end;
1601 }
1602
1603 ret = config_writer_write_element_string(writer, config_element_name,
1604 kchan->channel->name);
1605 if (ret) {
1606 ret = LTTNG_ERR_SAVE_IO_FAIL;
1607 goto end;
1608 }
1609
1610 ret = config_writer_write_element_bool(writer, config_element_enabled,
1611 kchan->channel->enabled);
1612 if (ret) {
1613 ret = LTTNG_ERR_SAVE_IO_FAIL;
1614 goto end;
1615 }
1616
1617 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
55c9e7ca 1618 if (ret != LTTNG_OK) {
fb198a11
JG
1619 goto end;
1620 }
1621
0de3eda1 1622 ret = save_kernel_events(writer, kchan);
55c9e7ca 1623 if (ret != LTTNG_OK) {
fb198a11
JG
1624 goto end;
1625 }
1626
645328ae 1627 ret = save_kernel_contexts(writer, kchan);
55c9e7ca 1628 if (ret != LTTNG_OK) {
fb198a11
JG
1629 goto end;
1630 }
1631
1632 /* /channel */
1633 ret = config_writer_close_element(writer);
1634 if (ret) {
1635 ret = LTTNG_ERR_SAVE_IO_FAIL;
1636 goto end;
1637 }
55c9e7ca
JR
1638
1639 ret = LTTNG_OK;
fb198a11
JG
1640end:
1641 return ret;
1642}
1643
55c9e7ca 1644/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1645static
1646int save_ust_channel(struct config_writer *writer,
1647 struct ltt_ust_channel *ust_chan,
1648 struct ltt_ust_session *session)
1649{
1650 int ret;
1651
1652 assert(writer);
1653 assert(ust_chan);
1654 assert(session);
1655
1656 ret = config_writer_open_element(writer, config_element_channel);
1657 if (ret) {
1658 ret = LTTNG_ERR_SAVE_IO_FAIL;
1659 goto end;
1660 }
1661
1662 ret = config_writer_write_element_string(writer, config_element_name,
1663 ust_chan->name);
1664 if (ret) {
1665 ret = LTTNG_ERR_SAVE_IO_FAIL;
1666 goto end;
1667 }
1668
1669 ret = config_writer_write_element_bool(writer, config_element_enabled,
1670 ust_chan->enabled);
1671 if (ret) {
1672 ret = LTTNG_ERR_SAVE_IO_FAIL;
1673 goto end;
1674 }
1675
1676 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
55c9e7ca 1677 if (ret != LTTNG_OK) {
fb198a11
JG
1678 goto end;
1679 }
1680
1681 ret = config_writer_write_element_unsigned_int(writer,
1682 config_element_tracefile_size, ust_chan->tracefile_size);
1683 if (ret) {
1684 ret = LTTNG_ERR_SAVE_IO_FAIL;
1685 goto end;
1686 }
1687
1688 ret = config_writer_write_element_unsigned_int(writer,
1689 config_element_tracefile_count, ust_chan->tracefile_count);
1690 if (ret) {
1691 ret = LTTNG_ERR_SAVE_IO_FAIL;
1692 goto end;
1693 }
1694
1695 ret = config_writer_write_element_unsigned_int(writer,
1696 config_element_live_timer_interval,
1697 session->live_timer_interval);
1698 if (ret) {
1699 ret = LTTNG_ERR_SAVE_IO_FAIL;
1700 goto end;
1701 }
1702
51755dc8
JG
1703 if (ust_chan->domain == LTTNG_DOMAIN_UST) {
1704 ret = save_ust_events(writer, ust_chan->events);
55c9e7ca 1705 if (ret != LTTNG_OK) {
51755dc8
JG
1706 goto end;
1707 }
1708 } else {
1709 struct agent *agent = NULL;
1710
1711 agent = trace_ust_find_agent(session, ust_chan->domain);
1712 if (!agent) {
1713 ret = LTTNG_ERR_SAVE_IO_FAIL;
1714 ERR("Could not find agent associated to UST subdomain");
1715 goto end;
1716 }
1717
1718 /*
1719 * Channels associated with a UST sub-domain (such as JUL, Log4j
1720 * or Python) don't have any non-internal events. We retrieve
1721 * the "agent" events associated with this channel and serialize
1722 * them.
1723 */
8cd0a98d 1724 ret = save_agent_events(writer, agent);
55c9e7ca 1725 if (ret != LTTNG_OK) {
51755dc8
JG
1726 goto end;
1727 }
fb198a11
JG
1728 }
1729
1730 ret = save_ust_context(writer, &ust_chan->ctx_list);
55c9e7ca 1731 if (ret != LTTNG_OK) {
fb198a11
JG
1732 goto end;
1733 }
1734
1735 /* /channel */
1736 ret = config_writer_close_element(writer);
1737 if (ret) {
1738 ret = LTTNG_ERR_SAVE_IO_FAIL;
1739 goto end;
1740 }
55c9e7ca
JR
1741
1742 ret = LTTNG_OK;
fb198a11
JG
1743end:
1744 return ret;
1745}
1746
55c9e7ca 1747/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
1748static
1749int save_kernel_session(struct config_writer *writer,
1750 struct ltt_session *session)
1751{
1752 int ret;
1753 struct ltt_kernel_channel *kchan;
1754
1755 assert(writer);
1756 assert(session);
1757
1758 ret = config_writer_write_element_string(writer, config_element_type,
1759 config_domain_type_kernel);
1760 if (ret) {
1761 ret = LTTNG_ERR_SAVE_IO_FAIL;
1762 goto end;
1763 }
1764
1765 ret = config_writer_write_element_string(writer,
1766 config_element_buffer_type, config_buffer_type_global);
1767 if (ret) {
1768 ret = LTTNG_ERR_SAVE_IO_FAIL;
1769 goto end;
1770 }
1771
1772 ret = config_writer_open_element(writer,
1773 config_element_channels);
1774 if (ret) {
1775 ret = LTTNG_ERR_SAVE_IO_FAIL;
1776 goto end;
1777 }
1778
1779 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
1780 list) {
1781 ret = save_kernel_channel(writer, kchan);
55c9e7ca 1782 if (ret != LTTNG_OK) {
fb198a11
JG
1783 goto end;
1784 }
1785 }
1786
1787 /* /channels */
1788 ret = config_writer_close_element(writer);
1789 if (ret) {
1790 ret = LTTNG_ERR_SAVE_IO_FAIL;
1791 goto end;
1792 }
55c9e7ca
JR
1793
1794 ret = LTTNG_OK;
fb198a11
JG
1795end:
1796 return ret;
1797}
1798
1799static
51755dc8
JG
1800const char *get_config_domain_str(enum lttng_domain_type domain)
1801{
1802 const char *str_dom;
1803
1804 switch (domain) {
1805 case LTTNG_DOMAIN_KERNEL:
1806 str_dom = config_domain_type_kernel;
1807 break;
1808 case LTTNG_DOMAIN_UST:
1809 str_dom = config_domain_type_ust;
1810 break;
1811 case LTTNG_DOMAIN_JUL:
1812 str_dom = config_domain_type_jul;
1813 break;
1814 case LTTNG_DOMAIN_LOG4J:
1815 str_dom = config_domain_type_log4j;
1816 break;
1817 case LTTNG_DOMAIN_PYTHON:
1818 str_dom = config_domain_type_python;
1819 break;
1820 default:
1821 assert(0);
1822 }
1823
1824 return str_dom;
1825}
1826
55c9e7ca 1827/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
159b042f 1828static int save_process_attr_tracker(struct config_writer *writer,
55c9e7ca
JR
1829 struct ltt_session *sess,
1830 int domain,
159b042f 1831 enum lttng_process_attr process_attr)
e8fcabef 1832{
55c9e7ca 1833 int ret = LTTNG_OK;
55c9e7ca 1834 const char *element_id_tracker, *element_target_id, *element_id;
159b042f
JG
1835 const struct process_attr_tracker *tracker;
1836 enum lttng_tracking_policy tracking_policy;
1837 struct lttng_process_attr_values *values = NULL;
1838
1839 switch (process_attr) {
1840 case LTTNG_PROCESS_ATTR_PROCESS_ID:
1841 element_id_tracker = config_element_process_attr_tracker_pid;
1842 element_target_id = config_element_process_attr_pid_value;
1843 element_id = config_element_process_attr_id;
1844 break;
1845 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
1846 element_id_tracker = config_element_process_attr_tracker_vpid;
1847 element_target_id = config_element_process_attr_vpid_value;
1848 element_id = config_element_process_attr_id;
1849 break;
1850 case LTTNG_PROCESS_ATTR_USER_ID:
1851 element_id_tracker = config_element_process_attr_tracker_uid;
1852 element_target_id = config_element_process_attr_uid_value;
1853 element_id = config_element_process_attr_id;
1854 break;
1855 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
1856 element_id_tracker = config_element_process_attr_tracker_vuid;
1857 element_target_id = config_element_process_attr_vuid_value;
1858 element_id = config_element_process_attr_id;
1859 break;
1860 case LTTNG_PROCESS_ATTR_GROUP_ID:
1861 element_id_tracker = config_element_process_attr_tracker_gid;
1862 element_target_id = config_element_process_attr_gid_value;
1863 element_id = config_element_process_attr_id;
1864 break;
1865 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
1866 element_id_tracker = config_element_process_attr_tracker_vgid;
1867 element_target_id = config_element_process_attr_vgid_value;
1868 element_id = config_element_process_attr_id;
55c9e7ca
JR
1869 break;
1870 default:
1871 ret = LTTNG_ERR_SAVE_IO_FAIL;
1872 goto end;
1873 }
e8fcabef
JG
1874
1875 switch (domain) {
1876 case LTTNG_DOMAIN_KERNEL:
1877 {
159b042f
JG
1878 tracker = kernel_get_process_attr_tracker(
1879 sess->kernel_session, process_attr);
1880 assert(tracker);
e8fcabef
JG
1881 break;
1882 }
1883 case LTTNG_DOMAIN_UST:
1884 {
159b042f
JG
1885 tracker = trace_ust_get_process_attr_tracker(
1886 sess->ust_session, process_attr);
1887 assert(tracker);
e8fcabef
JG
1888 break;
1889 }
1890 case LTTNG_DOMAIN_JUL:
1891 case LTTNG_DOMAIN_LOG4J:
1892 case LTTNG_DOMAIN_PYTHON:
1893 default:
159b042f 1894 ret = LTTNG_ERR_UNSUPPORTED_DOMAIN;
e8fcabef
JG
1895 goto end;
1896 }
1897
159b042f
JG
1898 tracking_policy = process_attr_tracker_get_tracking_policy(tracker);
1899 if (tracking_policy == LTTNG_TRACKING_POLICY_INCLUDE_ALL) {
1900 /* Tracking all, nothing to output. */
1901 ret = LTTNG_OK;
e283e4a0
JR
1902 goto end;
1903 }
a7a533cd 1904
55c9e7ca
JR
1905 ret = config_writer_open_element(writer, element_id_tracker);
1906 if (ret) {
1907 ret = LTTNG_ERR_SAVE_IO_FAIL;
1908 goto end;
1909 }
1910
159b042f
JG
1911 ret = config_writer_open_element(
1912 writer, config_element_process_attr_values);
55c9e7ca
JR
1913 if (ret) {
1914 ret = LTTNG_ERR_SAVE_IO_FAIL;
1915 goto end;
1916 }
1917
88ac6301 1918 if (tracking_policy == LTTNG_TRACKING_POLICY_INCLUDE_SET) {
159b042f
JG
1919 unsigned int i, count;
1920 enum process_attr_tracker_status status =
1921 process_attr_tracker_get_inclusion_set(
1922 tracker, &values);
1923
1924 if (status != PROCESS_ATTR_TRACKER_STATUS_OK) {
1925 ret = LTTNG_ERR_NOMEM;
1926 goto end;
1927 }
1928
1929 count = _lttng_process_attr_values_get_count(values);
1930
1931 for (i = 0; i < count; i++) {
1932 unsigned int integral_value = UINT_MAX;
1933 const char *name = NULL;
1934 const struct process_attr_value *value =
1935 lttng_process_attr_tracker_values_get_at_index(
1936 values, i);
1937
1938 assert(value);
1939 ret = config_writer_open_element(
1940 writer, element_target_id);
1941 if (ret) {
a7a533cd
JR
1942 ret = LTTNG_ERR_SAVE_IO_FAIL;
1943 goto end;
1944 }
159b042f
JG
1945
1946 switch (value->type) {
1947 case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID:
1948 integral_value =
1949 (unsigned int) value->value.pid;
55c9e7ca 1950 break;
159b042f
JG
1951 case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID:
1952 integral_value =
1953 (unsigned int) value->value.uid;
1954 break;
1955 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID:
1956 integral_value =
1957 (unsigned int) value->value.gid;
1958 break;
1959 case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME:
1960 name = value->value.user_name;
1961 assert(name);
1962 break;
1963 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME:
1964 name = value->value.group_name;
1965 assert(name);
55c9e7ca
JR
1966 break;
1967 default:
159b042f 1968 abort();
e8fcabef 1969 }
159b042f
JG
1970
1971 if (name) {
1972 ret = config_writer_write_element_string(writer,
1973 config_element_name, name);
1974 } else {
1975 ret = config_writer_write_element_unsigned_int(
1976 writer, element_id,
1977 integral_value);
e8fcabef 1978 }
159b042f
JG
1979
1980 if (ret) {
2d97a006
JR
1981 ret = LTTNG_ERR_SAVE_IO_FAIL;
1982 goto end;
1983 }
e8fcabef 1984
55c9e7ca 1985 /* /$element_target_id */
e8fcabef
JG
1986 ret = config_writer_close_element(writer);
1987 if (ret) {
1988 ret = LTTNG_ERR_SAVE_IO_FAIL;
1989 goto end;
1990 }
1991 }
55c9e7ca 1992 }
e8fcabef 1993
88ac6301 1994 /* /values */
55c9e7ca
JR
1995 ret = config_writer_close_element(writer);
1996 if (ret) {
1997 ret = LTTNG_ERR_SAVE_IO_FAIL;
1998 goto end;
1999 }
e8fcabef 2000
55c9e7ca
JR
2001 /* /$element_id_tracker */
2002 ret = config_writer_close_element(writer);
2003 if (ret) {
2004 ret = LTTNG_ERR_SAVE_IO_FAIL;
2005 goto end;
e8fcabef 2006 }
55c9e7ca
JR
2007
2008 ret = LTTNG_OK;
e8fcabef 2009end:
159b042f 2010 lttng_process_attr_values_destroy(values);
e8fcabef
JG
2011 return ret;
2012}
2013
55c9e7ca 2014/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
159b042f 2015static int save_process_attr_trackers(struct config_writer *writer,
55c9e7ca
JR
2016 struct ltt_session *sess,
2017 int domain)
2018{
2019 int ret;
2020
2021 switch (domain) {
2022 case LTTNG_DOMAIN_KERNEL:
159b042f
JG
2023 ret = save_process_attr_tracker(writer, sess, domain,
2024 LTTNG_PROCESS_ATTR_PROCESS_ID);
2025 if (ret != LTTNG_OK) {
2026 goto end;
2027 }
2028 ret = save_process_attr_tracker(writer, sess, domain,
2029 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
2030 if (ret != LTTNG_OK) {
2031 goto end;
2032 }
2033 ret = save_process_attr_tracker(writer, sess, domain,
2034 LTTNG_PROCESS_ATTR_USER_ID);
2035 if (ret != LTTNG_OK) {
2036 goto end;
2037 }
2038 ret = save_process_attr_tracker(writer, sess, domain,
2039 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
2040 if (ret != LTTNG_OK) {
2041 goto end;
2042 }
2043 ret = save_process_attr_tracker(writer, sess, domain,
2044 LTTNG_PROCESS_ATTR_GROUP_ID);
2045 if (ret != LTTNG_OK) {
2046 goto end;
2047 }
2048 ret = save_process_attr_tracker(writer, sess, domain,
2049 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
2050 if (ret != LTTNG_OK) {
2051 goto end;
2052 }
55c9e7ca
JR
2053 break;
2054 case LTTNG_DOMAIN_UST:
159b042f
JG
2055 ret = save_process_attr_tracker(writer, sess, domain,
2056 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
2057 if (ret != LTTNG_OK) {
2058 goto end;
2059 }
2060 ret = save_process_attr_tracker(writer, sess, domain,
2061 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
2062 if (ret != LTTNG_OK) {
2063 goto end;
2064 }
2065 ret = save_process_attr_tracker(writer, sess, domain,
2066 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
2067 if (ret != LTTNG_OK) {
2068 goto end;
2069 }
55c9e7ca
JR
2070 break;
2071 default:
159b042f 2072 ret = LTTNG_ERR_INVALID;
74675e31 2073 goto end;
55c9e7ca 2074 }
159b042f
JG
2075 ret = LTTNG_OK;
2076end:
2077 return ret;
55c9e7ca
JR
2078}
2079
2080/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
51755dc8
JG
2081static
2082int save_ust_domain(struct config_writer *writer,
2083 struct ltt_session *session, enum lttng_domain_type domain)
fb198a11
JG
2084{
2085 int ret;
2086 struct ltt_ust_channel *ust_chan;
2087 const char *buffer_type_string;
2088 struct lttng_ht_node_str *node;
2089 struct lttng_ht_iter iter;
51755dc8 2090 const char *config_domain_name;
fb198a11
JG
2091
2092 assert(writer);
2093 assert(session);
2094
51755dc8
JG
2095 ret = config_writer_open_element(writer,
2096 config_element_domain);
2097 if (ret) {
2098 ret = LTTNG_ERR_SAVE_IO_FAIL;
2099 goto end;
2100 }
2101
2102 config_domain_name = get_config_domain_str(domain);
2103 if (!config_domain_name) {
2104 ret = LTTNG_ERR_INVALID;
2105 goto end;
2106 }
2107
2108 ret = config_writer_write_element_string(writer,
2109 config_element_type, config_domain_name);
fb198a11
JG
2110 if (ret) {
2111 ret = LTTNG_ERR_SAVE_IO_FAIL;
2112 goto end;
2113 }
2114
2115 buffer_type_string = get_buffer_type_string(
2116 session->ust_session->buffer_type);
2117 if (!buffer_type_string) {
2118 ERR("Unsupported buffer type.");
2119 ret = LTTNG_ERR_INVALID;
2120 goto end;
2121 }
2122
2123 ret = config_writer_write_element_string(writer,
2124 config_element_buffer_type, buffer_type_string);
2125 if (ret) {
2126 ret = LTTNG_ERR_SAVE_IO_FAIL;
2127 goto end;
2128 }
2129
2130 ret = config_writer_open_element(writer, config_element_channels);
2131 if (ret) {
2132 ret = LTTNG_ERR_SAVE_IO_FAIL;
2133 goto end;
2134 }
2135
2136 rcu_read_lock();
2137 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
2138 &iter.iter, node, node) {
fb198a11 2139 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
51755dc8 2140 if (domain == ust_chan->domain) {
fb198a11 2141 ret = save_ust_channel(writer, ust_chan, session->ust_session);
55c9e7ca 2142 if (ret != LTTNG_OK) {
fb198a11
JG
2143 rcu_read_unlock();
2144 goto end;
2145 }
2146 }
2147 }
2148 rcu_read_unlock();
2149
2150 /* /channels */
2151 ret = config_writer_close_element(writer);
2152 if (ret) {
2153 ret = LTTNG_ERR_SAVE_IO_FAIL;
2154 goto end;
2155 }
51755dc8 2156
e8fcabef 2157 if (domain == LTTNG_DOMAIN_UST) {
159b042f
JG
2158 ret = config_writer_open_element(
2159 writer, config_element_process_attr_trackers);
847a5916
JR
2160 if (ret) {
2161 ret = LTTNG_ERR_SAVE_IO_FAIL;
2162 goto end;
2163 }
2164
159b042f
JG
2165 ret = save_process_attr_trackers(
2166 writer, session, LTTNG_DOMAIN_UST);
55c9e7ca 2167 if (ret != LTTNG_OK) {
847a5916
JR
2168 goto end;
2169 }
2170
e8fcabef 2171 /* /trackers */
847a5916
JR
2172 ret = config_writer_close_element(writer);
2173 if (ret) {
55c9e7ca 2174 ret = LTTNG_ERR_SAVE_IO_FAIL;
847a5916
JR
2175 goto end;
2176 }
e8fcabef 2177 }
847a5916 2178
e8fcabef
JG
2179 /* /domain */
2180 ret = config_writer_close_element(writer);
2181 if (ret) {
2182 ret = LTTNG_ERR_SAVE_IO_FAIL;
2183 goto end;
847a5916 2184 }
e8fcabef 2185
55c9e7ca 2186 ret = LTTNG_OK;
847a5916 2187end:
847a5916
JR
2188 return ret;
2189}
2190
55c9e7ca 2191/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
2192static
2193int save_domains(struct config_writer *writer, struct ltt_session *session)
2194{
55c9e7ca 2195 int ret = LTTNG_OK;
fb198a11
JG
2196
2197 assert(writer);
2198 assert(session);
2199
2200 if (!session->kernel_session && !session->ust_session) {
2201 goto end;
2202 }
2203
2204 ret = config_writer_open_element(writer, config_element_domains);
2205 if (ret) {
2206 ret = LTTNG_ERR_SAVE_IO_FAIL;
2207 goto end;
2208 }
2209
fb198a11
JG
2210 if (session->kernel_session) {
2211 ret = config_writer_open_element(writer,
2212 config_element_domain);
2213 if (ret) {
2214 ret = LTTNG_ERR_SAVE_IO_FAIL;
2215 goto end;
2216 }
2217
2218 ret = save_kernel_session(writer, session);
55c9e7ca 2219 if (ret != LTTNG_OK) {
fb198a11
JG
2220 goto end;
2221 }
2222
159b042f
JG
2223 ret = config_writer_open_element(
2224 writer, config_element_process_attr_trackers);
847a5916
JR
2225 if (ret) {
2226 ret = LTTNG_ERR_SAVE_IO_FAIL;
2227 goto end;
2228 }
2229
159b042f
JG
2230 ret = save_process_attr_trackers(
2231 writer, session, LTTNG_DOMAIN_KERNEL);
55c9e7ca 2232 if (ret != LTTNG_OK) {
847a5916
JR
2233 goto end;
2234 }
2235
2236 /* /trackers */
2237 ret = config_writer_close_element(writer);
2238 if (ret) {
2239 ret = LTTNG_ERR_SAVE_IO_FAIL;
2240 goto end;
2241 }
fb198a11
JG
2242 /* /domain */
2243 ret = config_writer_close_element(writer);
2244 if (ret) {
2245 ret = LTTNG_ERR_SAVE_IO_FAIL;
2246 goto end;
2247 }
2248 }
2249
2250 if (session->ust_session) {
51755dc8 2251 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_UST);
55c9e7ca 2252 if (ret != LTTNG_OK) {
fb198a11
JG
2253 goto end;
2254 }
2255
51755dc8 2256 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_JUL);
55c9e7ca 2257 if (ret != LTTNG_OK) {
fb198a11
JG
2258 goto end;
2259 }
fb198a11 2260
51755dc8 2261 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J);
55c9e7ca 2262 if (ret != LTTNG_OK) {
51755dc8
JG
2263 goto end;
2264 }
65d72c41 2265
51755dc8 2266 ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON);
55c9e7ca 2267 if (ret != LTTNG_OK) {
51755dc8 2268 goto end;
fb198a11
JG
2269 }
2270 }
2271
2272 /* /domains */
2273 ret = config_writer_close_element(writer);
2274 if (ret) {
2275 ret = LTTNG_ERR_SAVE_IO_FAIL;
2276 goto end;
2277 }
55c9e7ca
JR
2278
2279 ret = LTTNG_OK;
fb198a11
JG
2280end:
2281 return ret;
2282}
2283
55c9e7ca 2284/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
2285static
2286int save_consumer_output(struct config_writer *writer,
2287 struct consumer_output *output)
2288{
2289 int ret;
2290
2291 assert(writer);
2292 assert(output);
2293
2294 ret = config_writer_open_element(writer, config_element_consumer_output);
2295 if (ret) {
2296 ret = LTTNG_ERR_SAVE_IO_FAIL;
2297 goto end;
2298 }
2299
2300 ret = config_writer_write_element_bool(writer, config_element_enabled,
2301 output->enabled);
2302 if (ret) {
2303 ret = LTTNG_ERR_SAVE_IO_FAIL;
2304 goto end;
2305 }
2306
2307 ret = config_writer_open_element(writer, config_element_destination);
2308 if (ret) {
2309 ret = LTTNG_ERR_SAVE_IO_FAIL;
2310 goto end;
2311 }
2312
2313 switch (output->type) {
2314 case CONSUMER_DST_LOCAL:
2315 ret = config_writer_write_element_string(writer,
366a9222 2316 config_element_path, output->dst.session_root_path);
fb198a11
JG
2317 if (ret) {
2318 ret = LTTNG_ERR_SAVE_IO_FAIL;
2319 goto end;
2320 }
2321 break;
2322 case CONSUMER_DST_NET:
2323 {
2324 char *uri;
2325
2326 uri = zmalloc(PATH_MAX);
2327 if (!uri) {
2328 ret = LTTNG_ERR_NOMEM;
2329 goto end;
2330 }
2331
2332 ret = config_writer_open_element(writer, config_element_net_output);
2333 if (ret) {
2334 ret = LTTNG_ERR_SAVE_IO_FAIL;
2335 goto end_net_output;
2336 }
2337
2338 if (output->dst.net.control_isset &&
2339 output->dst.net.data_isset) {
2340 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
2341 if (ret < 0) {
2342 ret = LTTNG_ERR_INVALID;
2343 goto end_net_output;
2344 }
2345
2346 ret = config_writer_write_element_string(writer,
2347 config_element_control_uri, uri);
2348 if (ret) {
2349 ret = LTTNG_ERR_SAVE_IO_FAIL;
2350 goto end_net_output;
2351 }
2352
2353 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
2354 if (ret < 0) {
2355 ret = LTTNG_ERR_INVALID;
2356 goto end_net_output;
2357 }
2358
2359 ret = config_writer_write_element_string(writer,
2360 config_element_data_uri, uri);
2361 if (ret) {
2362 ret = LTTNG_ERR_SAVE_IO_FAIL;
2363 goto end_net_output;
2364 }
55c9e7ca 2365 ret = LTTNG_OK;
fb198a11
JG
2366end_net_output:
2367 free(uri);
55c9e7ca 2368 if (ret != LTTNG_OK) {
fb198a11
JG
2369 goto end;
2370 }
2371 } else {
2372 ret = !output->dst.net.control_isset ?
2373 LTTNG_ERR_URL_CTRL_MISS :
2374 LTTNG_ERR_URL_DATA_MISS;
c39270e5 2375 free(uri);
fb198a11
JG
2376 goto end;
2377 }
2378
2379 ret = config_writer_close_element(writer);
2380 if (ret) {
2381 ret = LTTNG_ERR_SAVE_IO_FAIL;
2382 goto end;
2383 }
2384 break;
2385 }
2386 default:
2387 ERR("Unsupported consumer output type.");
2388 ret = LTTNG_ERR_INVALID;
2389 goto end;
2390 }
2391
2392 /* /destination */
2393 ret = config_writer_close_element(writer);
2394 if (ret) {
2395 ret = LTTNG_ERR_SAVE_IO_FAIL;
2396 goto end;
2397 }
2398
2399 /* /consumer_output */
2400 ret = config_writer_close_element(writer);
2401 if (ret) {
2402 ret = LTTNG_ERR_SAVE_IO_FAIL;
2403 goto end;
2404 }
55c9e7ca
JR
2405
2406 ret = LTTNG_OK;
fb198a11
JG
2407end:
2408 return ret;
2409}
2410
55c9e7ca 2411/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
2412static
2413int save_snapshot_outputs(struct config_writer *writer,
2414 struct snapshot *snapshot)
2415{
2416 int ret;
2417 struct lttng_ht_iter iter;
2418 struct snapshot_output *output;
2419
2420 assert(writer);
2421 assert(snapshot);
2422
2423 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
2424 if (ret) {
2425 ret = LTTNG_ERR_SAVE_IO_FAIL;
2426 goto end;
2427 }
2428
2429 rcu_read_lock();
2430 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
2431 node.node) {
2432 ret = config_writer_open_element(writer,
2433 config_element_output);
2434 if (ret) {
2435 ret = LTTNG_ERR_SAVE_IO_FAIL;
2436 goto end_unlock;
2437 }
2438
2439 ret = config_writer_write_element_string(writer,
2440 config_element_name, output->name);
2441 if (ret) {
2442 ret = LTTNG_ERR_SAVE_IO_FAIL;
2443 goto end_unlock;
2444 }
2445
2446 ret = config_writer_write_element_unsigned_int(writer,
2447 config_element_max_size, output->max_size);
2448 if (ret) {
2449 ret = LTTNG_ERR_SAVE_IO_FAIL;
2450 goto end_unlock;
2451 }
2452
2453 ret = save_consumer_output(writer, output->consumer);
55c9e7ca 2454 if (ret != LTTNG_OK) {
fb198a11
JG
2455 goto end_unlock;
2456 }
2457
2458 /* /output */
2459 ret = config_writer_close_element(writer);
2460 if (ret) {
2461 ret = LTTNG_ERR_SAVE_IO_FAIL;
2462 goto end_unlock;
2463 }
2464 }
2465 rcu_read_unlock();
2466
2467 /* /snapshot_outputs */
2468 ret = config_writer_close_element(writer);
2469 if (ret) {
2470 ret = LTTNG_ERR_SAVE_IO_FAIL;
2471 goto end;
2472 }
2473
55c9e7ca 2474 ret = LTTNG_OK;
fb198a11
JG
2475end:
2476 return ret;
2477end_unlock:
2478 rcu_read_unlock();
2479 return ret;
2480}
2481
55c9e7ca 2482/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
fb198a11
JG
2483static
2484int save_session_output(struct config_writer *writer,
2485 struct ltt_session *session)
2486{
2487 int ret;
2488
2489 assert(writer);
2490 assert(session);
2491
2492 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
2493 (!session->snapshot_mode && !session->consumer)) {
2494 /* Session is in no output mode */
55c9e7ca 2495 ret = LTTNG_OK;
fb198a11
JG
2496 goto end;
2497 }
2498
2499 ret = config_writer_open_element(writer, config_element_output);
2500 if (ret) {
2501 ret = LTTNG_ERR_SAVE_IO_FAIL;
2502 goto end;
2503 }
2504
2505 if (session->snapshot_mode) {
2506 ret = save_snapshot_outputs(writer, &session->snapshot);
55c9e7ca 2507 if (ret != LTTNG_OK) {
fb198a11
JG
2508 goto end;
2509 }
2510 } else {
2511 if (session->consumer) {
2512 ret = save_consumer_output(writer, session->consumer);
55c9e7ca 2513 if (ret != LTTNG_OK) {
fb198a11
JG
2514 goto end;
2515 }
2516 }
2517 }
2518
2519 /* /output */
2520 ret = config_writer_close_element(writer);
2521 if (ret) {
2522 ret = LTTNG_ERR_SAVE_IO_FAIL;
2523 goto end;
2524 }
55c9e7ca 2525 ret = LTTNG_OK;
fb198a11
JG
2526end:
2527 return ret;
2528}
2529
ce6176f2
JG
2530static
2531int save_session_rotation_schedule(struct config_writer *writer,
2532 enum lttng_rotation_schedule_type type, uint64_t value)
2533{
2534 int ret = 0;
2535 const char *element_name;
2536 const char *value_name;
2537
2538 switch (type) {
2539 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
2540 element_name = config_element_rotation_schedule_periodic;
2541 value_name = config_element_rotation_schedule_periodic_time_us;
2542 break;
2543 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
2544 element_name = config_element_rotation_schedule_size_threshold;
2545 value_name = config_element_rotation_schedule_size_threshold_bytes;
2546 break;
2547 default:
2548 ret = -1;
2549 goto end;
2550 }
2551
2552 ret = config_writer_open_element(writer, element_name);
2553 if (ret) {
2554 goto end;
2555 }
2556
2557 ret = config_writer_write_element_unsigned_int(writer,
2558 value_name, value);
2559 if (ret) {
2560 goto end;
2561 }
2562
2563 /* Close schedule descriptor element. */
2564 ret = config_writer_close_element(writer);
2565 if (ret) {
2566 goto end;
2567 }
2568end:
2569 return ret;
2570}
2571
2572static
2573int save_session_rotation_schedules(struct config_writer *writer,
2574 struct ltt_session *session)
2575{
2576 int ret;
2577
2578 ret = config_writer_open_element(writer,
2579 config_element_rotation_schedules);
f829d17a
JG
2580 if (ret) {
2581 goto end;
2582 }
ce6176f2
JG
2583 if (session->rotate_timer_period) {
2584 ret = save_session_rotation_schedule(writer,
2585 LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC,
2586 session->rotate_timer_period);
2587 if (ret) {
2588 goto close_schedules;
2589 }
2590 }
2591 if (session->rotate_size) {
2592 ret = save_session_rotation_schedule(writer,
2593 LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD,
2594 session->rotate_size);
2595 if (ret) {
2596 goto close_schedules;
2597 }
2598 }
2599
2600close_schedules:
2601 /* Close rotation schedules element. */
2602 ret = config_writer_close_element(writer);
2603 if (ret) {
2604 goto end;
2605 }
2606end:
2607 return ret;
2608}
2609
fb198a11
JG
2610/*
2611 * Save the given session.
2612 *
55c9e7ca 2613 * Return LTTNG_OK on success else a LTTNG_ERR* code.
fb198a11
JG
2614 */
2615static
2616int save_session(struct ltt_session *session,
2617 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
2618{
b45f9ad2 2619 int ret, fd = -1;
511653c3 2620 char config_file_path[LTTNG_PATH_MAX];
fb198a11
JG
2621 size_t len;
2622 struct config_writer *writer = NULL;
2623 size_t session_name_len;
2624 const char *provided_path;
f376ad9c 2625 int file_open_flags = O_CREAT | O_WRONLY | O_TRUNC;
fb198a11
JG
2626
2627 assert(session);
2628 assert(attr);
2629 assert(creds);
2630
2631 session_name_len = strlen(session->name);
95a29ab8 2632 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
2633
2634 if (!session_access_ok(session,
d7b377ed 2635 LTTNG_SOCK_GET_UID_CRED(creds)) || session->destroyed) {
fb198a11
JG
2636 ret = LTTNG_ERR_EPERM;
2637 goto end;
2638 }
2639
2640 provided_path = lttng_save_session_attr_get_output_url(attr);
2641 if (provided_path) {
95a29ab8 2642 DBG3("Save session in provided path %s", provided_path);
fb198a11 2643 len = strlen(provided_path);
d2992717 2644 if (len >= sizeof(config_file_path)) {
fb198a11
JG
2645 ret = LTTNG_ERR_SET_URL;
2646 goto end;
2647 }
511653c3 2648 strncpy(config_file_path, provided_path, sizeof(config_file_path));
fb198a11 2649 } else {
7e078ad1 2650 ssize_t ret_len;
fb198a11
JG
2651 char *home_dir = utils_get_user_home_dir(
2652 LTTNG_SOCK_GET_UID_CRED(creds));
2653 if (!home_dir) {
2654 ret = LTTNG_ERR_SET_URL;
2655 goto end;
2656 }
2657
d2992717 2658 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
2659 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
2660 free(home_dir);
7e078ad1 2661 if (ret_len < 0) {
fb198a11
JG
2662 PERROR("snprintf save session");
2663 ret = LTTNG_ERR_SET_URL;
2664 goto end;
2665 }
7e078ad1 2666 len = ret_len;
fb198a11
JG
2667 }
2668
2669 /*
d2992717
DG
2670 * Check the path fits in the config file path dst including the '/'
2671 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 2672 */
d2992717
DG
2673 if ((len + session_name_len + 2 +
2674 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
2675 > sizeof(config_file_path)) {
fb198a11
JG
2676 ret = LTTNG_ERR_SET_URL;
2677 goto end;
2678 }
2679
2680 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
2681 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
2682 if (ret) {
2683 ret = LTTNG_ERR_SET_URL;
2684 goto end;
2685 }
2686
d2992717
DG
2687 /*
2688 * At this point, we know that everything fits in the buffer. Validation
2689 * was done just above.
2690 */
fb198a11 2691 config_file_path[len++] = '/';
511653c3 2692 strncpy(config_file_path + len, session->name, sizeof(config_file_path) - len);
fb198a11
JG
2693 len += session_name_len;
2694 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
2695 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
2696 config_file_path[len] = '\0';
fb198a11 2697
f376ad9c
JG
2698 if (!attr->overwrite) {
2699 file_open_flags |= O_EXCL;
fb198a11
JG
2700 }
2701
f376ad9c 2702 fd = run_as_open(config_file_path, file_open_flags,
fb198a11
JG
2703 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
2704 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
2705 if (fd < 0) {
2706 PERROR("Could not create configuration file");
f376ad9c
JG
2707 switch (errno) {
2708 case EEXIST:
2709 ret = LTTNG_ERR_SAVE_FILE_EXIST;
2710 break;
2711 case EACCES:
2712 ret = LTTNG_ERR_EPERM;
2713 break;
2714 default:
2715 ret = LTTNG_ERR_SAVE_IO_FAIL;
2716 break;
2717 }
fb198a11
JG
2718 goto end;
2719 }
2720
705bb62f 2721 writer = config_writer_create(fd, 1);
fb198a11
JG
2722 if (!writer) {
2723 ret = LTTNG_ERR_NOMEM;
2724 goto end;
2725 }
2726
2727 ret = config_writer_open_element(writer, config_element_sessions);
2728 if (ret) {
2729 ret = LTTNG_ERR_SAVE_IO_FAIL;
2730 goto end;
2731 }
2732
2733 ret = config_writer_open_element(writer, config_element_session);
2734 if (ret) {
2735 ret = LTTNG_ERR_SAVE_IO_FAIL;
2736 goto end;
2737 }
2738
2739 ret = config_writer_write_element_string(writer, config_element_name,
2740 session->name);
2741 if (ret) {
2742 ret = LTTNG_ERR_SAVE_IO_FAIL;
2743 goto end;
2744 }
2745
55c9e7ca 2746 if (session->shm_path[0] != '\0') {
9e7c9f56
JR
2747 ret = config_writer_write_element_string(writer,
2748 config_element_shared_memory_path,
2749 session->shm_path);
2750 if (ret) {
2751 ret = LTTNG_ERR_SAVE_IO_FAIL;
2752 goto end;
2753 }
2754 }
2755
fb198a11 2756 ret = save_domains(writer, session);
55c9e7ca 2757 if (ret != LTTNG_OK) {
fb198a11
JG
2758 goto end;
2759 }
2760
2761 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 2762 session->active);
fb198a11
JG
2763 if (ret) {
2764 ret = LTTNG_ERR_SAVE_IO_FAIL;
2765 goto end;
2766 }
2767
329f3443
JD
2768 if (session->snapshot_mode || session->live_timer ||
2769 session->rotate_timer_period || session->rotate_size) {
fb198a11
JG
2770 ret = config_writer_open_element(writer, config_element_attributes);
2771 if (ret) {
2772 ret = LTTNG_ERR_SAVE_IO_FAIL;
2773 goto end;
2774 }
2775
2776 if (session->snapshot_mode) {
2777 ret = config_writer_write_element_bool(writer,
2778 config_element_snapshot_mode, 1);
2779 if (ret) {
2780 ret = LTTNG_ERR_SAVE_IO_FAIL;
2781 goto end;
2782 }
329f3443 2783 } else if (session->live_timer) {
d98ad589 2784 ret = config_writer_write_element_unsigned_int(writer,
fb198a11
JG
2785 config_element_live_timer_interval, session->live_timer);
2786 if (ret) {
2787 ret = LTTNG_ERR_SAVE_IO_FAIL;
2788 goto end;
2789 }
2790 }
ce6176f2
JG
2791 if (session->rotate_timer_period || session->rotate_size) {
2792 ret = save_session_rotation_schedules(writer,
2793 session);
329f3443
JD
2794 if (ret) {
2795 ret = LTTNG_ERR_SAVE_IO_FAIL;
2796 goto end;
2797 }
2798 }
fb198a11
JG
2799
2800 /* /attributes */
2801 ret = config_writer_close_element(writer);
2802 if (ret) {
2803 ret = LTTNG_ERR_SAVE_IO_FAIL;
2804 goto end;
2805 }
2806 }
2807
2808 ret = save_session_output(writer, session);
55c9e7ca 2809 if (ret != LTTNG_OK) {
fb198a11
JG
2810 goto end;
2811 }
2812
2813 /* /session */
2814 ret = config_writer_close_element(writer);
2815 if (ret) {
2816 ret = LTTNG_ERR_SAVE_IO_FAIL;
2817 goto end;
2818 }
2819
2820 /* /sessions */
2821 ret = config_writer_close_element(writer);
2822 if (ret) {
2823 ret = LTTNG_ERR_SAVE_IO_FAIL;
2824 goto end;
2825 }
55c9e7ca
JR
2826
2827 ret = LTTNG_OK;
fb198a11
JG
2828end:
2829 if (writer && config_writer_destroy(writer)) {
2830 /* Preserve the original error code */
55c9e7ca 2831 ret = ret != LTTNG_OK ? ret : LTTNG_ERR_SAVE_IO_FAIL;
fb198a11 2832 }
55c9e7ca 2833 if (ret != LTTNG_OK) {
fb198a11 2834 /* Delete file in case of error */
b45f9ad2 2835 if ((fd >= 0) && unlink(config_file_path)) {
fb198a11
JG
2836 PERROR("Unlinking XML session configuration.");
2837 }
2838 }
2839
b45f9ad2 2840 if (fd >= 0) {
55c9e7ca
JR
2841 int closeret;
2842
2843 closeret = close(fd);
2844 if (closeret) {
1d12100d
JR
2845 PERROR("Closing XML session configuration");
2846 }
2847 }
2848
fb198a11
JG
2849 return ret;
2850}
2851
2852int cmd_save_sessions(struct lttng_save_session_attr *attr,
2853 lttng_sock_cred *creds)
2854{
2855 int ret;
2856 const char *session_name;
2857 struct ltt_session *session;
2858
2859 session_lock_list();
2860
2861 session_name = lttng_save_session_attr_get_session_name(attr);
2862 if (session_name) {
2863 session = session_find_by_name(session_name);
2864 if (!session) {
2865 ret = LTTNG_ERR_SESS_NOT_FOUND;
2866 goto end;
2867 }
2868
2869 session_lock(session);
2870 ret = save_session(session, attr, creds);
2871 session_unlock(session);
e32d7f27 2872 session_put(session);
55c9e7ca 2873 if (ret != LTTNG_OK) {
fb198a11
JG
2874 goto end;
2875 }
2876 } else {
2877 struct ltt_session_list *list = session_get_list();
2878
2879 cds_list_for_each_entry(session, &list->head, list) {
e32d7f27
JG
2880 if (!session_get(session)) {
2881 continue;
2882 }
fb198a11
JG
2883 session_lock(session);
2884 ret = save_session(session, attr, creds);
2885 session_unlock(session);
e32d7f27 2886 session_put(session);
fb198a11 2887 /* Don't abort if we don't have the required permissions. */
55c9e7ca 2888 if (ret != LTTNG_OK && ret != LTTNG_ERR_EPERM) {
fb198a11
JG
2889 goto end;
2890 }
2891 }
2892 }
2893 ret = LTTNG_OK;
2894
2895end:
2896 session_unlock_list();
2897 return ret;
2898}
This page took 0.185442 seconds and 4 git commands to generate.