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