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