Add log4j default event and channel name handling
[lttng-tools.git] / src / bin / lttng-sessiond / save.c
CommitLineData
fb198a11
JG
1/*
2 * Copyright (C) 2014 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18#define _GNU_SOURCE
19#include <assert.h>
20#include <inttypes.h>
21#include <string.h>
22#include <urcu/uatomic.h>
23#include <unistd.h>
24
25#include <common/defaults.h>
26#include <common/error.h>
27#include <common/config/config.h>
fb198a11
JG
28#include <common/utils.h>
29#include <common/runas.h>
30#include <lttng/save-internal.h>
31
32#include "save.h"
33#include "session.h"
34#include "trace-ust.h"
35
36static
37int save_kernel_channel_attributes(struct config_writer *writer,
38 struct lttng_channel_attr *attr)
39{
40 int ret;
41
42 ret = config_writer_write_element_string(writer,
43 config_element_overwrite_mode,
44 attr->overwrite ? config_overwrite_mode_overwrite :
45 config_overwrite_mode_discard);
46 if (ret) {
47 goto end;
48 }
49
50 ret = config_writer_write_element_unsigned_int(writer,
51 config_element_subbuf_size, attr->subbuf_size);
52 if (ret) {
53 goto end;
54 }
55
56 ret = config_writer_write_element_unsigned_int(writer,
57 config_element_num_subbuf,
58 attr->num_subbuf);
59 if (ret) {
60 goto end;
61 }
62
63 ret = config_writer_write_element_unsigned_int(writer,
64 config_element_switch_timer_interval,
65 attr->switch_timer_interval);
66 if (ret) {
67 goto end;
68 }
69
70 ret = config_writer_write_element_unsigned_int(writer,
71 config_element_read_timer_interval,
72 attr->read_timer_interval);
73 if (ret) {
74 goto end;
75 }
76
77 ret = config_writer_write_element_string(writer,
78 config_element_output_type,
79 attr->output == LTTNG_EVENT_SPLICE ?
80 config_output_type_splice : config_output_type_mmap);
81 if (ret) {
82 goto end;
83 }
84
85 ret = config_writer_write_element_unsigned_int(writer,
86 config_element_tracefile_size, attr->tracefile_size);
87 if (ret) {
88 goto end;
89 }
90
91 ret = config_writer_write_element_unsigned_int(writer,
92 config_element_tracefile_count,
93 attr->tracefile_count);
94 if (ret) {
95 goto end;
96 }
97
98 ret = config_writer_write_element_unsigned_int(writer,
99 config_element_live_timer_interval,
100 attr->live_timer_interval);
101 if (ret) {
102 goto end;
103 }
104end:
105 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
106}
107
108static
109int save_ust_channel_attributes(struct config_writer *writer,
110 struct lttng_ust_channel_attr *attr)
111{
112 int ret;
113
114 ret = config_writer_write_element_string(writer,
115 config_element_overwrite_mode,
116 attr->overwrite ? config_overwrite_mode_overwrite :
117 config_overwrite_mode_discard);
118 if (ret) {
119 goto end;
120 }
121
122 ret = config_writer_write_element_unsigned_int(writer,
123 config_element_subbuf_size, attr->subbuf_size);
124 if (ret) {
125 goto end;
126 }
127
128 ret = config_writer_write_element_unsigned_int(writer,
129 config_element_num_subbuf,
130 attr->num_subbuf);
131 if (ret) {
132 goto end;
133 }
134
135 ret = config_writer_write_element_unsigned_int(writer,
136 config_element_switch_timer_interval,
137 attr->switch_timer_interval);
138 if (ret) {
139 goto end;
140 }
141
142 ret = config_writer_write_element_unsigned_int(writer,
143 config_element_read_timer_interval,
144 attr->read_timer_interval);
145 if (ret) {
146 goto end;
147 }
148
149 ret = config_writer_write_element_string(writer,
150 config_element_output_type,
151 attr->output == LTTNG_UST_MMAP ?
152 config_output_type_mmap : config_output_type_splice);
153 if (ret) {
154 goto end;
155 }
156end:
157 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
158}
159
160static
161const char *get_kernel_instrumentation_string(
162 enum lttng_kernel_instrumentation instrumentation)
163{
164 const char *instrumentation_string;
165
166 switch (instrumentation) {
167 case LTTNG_KERNEL_ALL:
168 instrumentation_string = config_event_type_all;
169 break;
170 case LTTNG_KERNEL_TRACEPOINT:
171 instrumentation_string = config_event_type_tracepoint;
172 break;
173 case LTTNG_KERNEL_KPROBE:
174 instrumentation_string = config_event_type_kprobe;
175 break;
176 case LTTNG_KERNEL_FUNCTION:
177 instrumentation_string = config_event_type_function;
178 break;
179 case LTTNG_KERNEL_KRETPROBE:
180 instrumentation_string = config_event_type_kretprobe;
181 break;
182 case LTTNG_KERNEL_NOOP:
183 instrumentation_string = config_event_type_noop;
184 break;
185 case LTTNG_KERNEL_SYSCALL:
186 instrumentation_string = config_event_type_syscall;
187 break;
188 default:
189 instrumentation_string = NULL;
190 }
191
192 return instrumentation_string;
193}
194
195static
196const char *get_kernel_context_type_string(
197 enum lttng_kernel_context_type context_type)
198{
199 const char *context_type_string;
200
201 switch (context_type) {
202 case LTTNG_KERNEL_CONTEXT_PID:
203 context_type_string = config_event_context_pid;
204 break;
205 case LTTNG_KERNEL_CONTEXT_PROCNAME:
206 context_type_string = config_event_context_procname;
207 break;
208 case LTTNG_KERNEL_CONTEXT_PRIO:
209 context_type_string = config_event_context_prio;
210 break;
211 case LTTNG_KERNEL_CONTEXT_NICE:
212 context_type_string = config_event_context_nice;
213 break;
214 case LTTNG_KERNEL_CONTEXT_VPID:
215 context_type_string = config_event_context_vpid;
216 break;
217 case LTTNG_KERNEL_CONTEXT_TID:
218 context_type_string = config_event_context_tid;
219 break;
220 case LTTNG_KERNEL_CONTEXT_VTID:
221 context_type_string = config_event_context_vtid;
222 break;
223 case LTTNG_KERNEL_CONTEXT_PPID:
224 context_type_string = config_event_context_ppid;
225 break;
226 case LTTNG_KERNEL_CONTEXT_VPPID:
227 context_type_string = config_event_context_vppid;
228 break;
229 case LTTNG_KERNEL_CONTEXT_HOSTNAME:
230 context_type_string = config_event_context_hostname;
231 break;
232 default:
233 context_type_string = NULL;
234 }
235
236 return context_type_string;
237}
238
239static
240const char *get_ust_context_type_string(
241 enum lttng_ust_context_type context_type)
242{
243 const char *context_type_string;
244
245 switch (context_type) {
246 case LTTNG_UST_CONTEXT_PROCNAME:
247 context_type_string = config_event_context_procname;
248 break;
249 case LTTNG_UST_CONTEXT_VPID:
250 context_type_string = config_event_context_vpid;
251 break;
252 case LTTNG_UST_CONTEXT_VTID:
253 context_type_string = config_event_context_vtid;
254 break;
255 case LTTNG_UST_CONTEXT_IP:
256 context_type_string = config_event_context_ip;
257 break;
258 case LTTNG_UST_CONTEXT_PTHREAD_ID:
259 context_type_string = config_event_context_pthread_id;
260 break;
e885a367
JRJ
261 case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
262 context_type_string = config_event_context_perf_thread_counter;
263 break;
fb198a11
JG
264 default:
265 context_type_string = NULL;
e885a367 266 break;
fb198a11
JG
267 }
268
269 return context_type_string;
270}
271
272static
273const char *get_buffer_type_string(
274 enum lttng_buffer_type buffer_type)
275{
276 const char *buffer_type_string;
277
278 switch (buffer_type) {
279 case LTTNG_BUFFER_PER_PID:
280 buffer_type_string = config_buffer_type_per_pid;
281 break;
282 case LTTNG_BUFFER_PER_UID:
283 buffer_type_string = config_buffer_type_per_uid;
284 break;
285 case LTTNG_BUFFER_GLOBAL:
286 buffer_type_string = config_buffer_type_global;
287 break;
288 default:
289 buffer_type_string = NULL;
290 }
291
292 return buffer_type_string;
293}
294
295static
296const char *get_loglevel_type_string(
297 enum lttng_ust_loglevel_type loglevel_type)
298{
299 const char *loglevel_type_string;
300
301 switch (loglevel_type) {
302 case LTTNG_UST_LOGLEVEL_ALL:
303 loglevel_type_string = config_loglevel_type_all;
304 break;
305 case LTTNG_UST_LOGLEVEL_RANGE:
306 loglevel_type_string = config_loglevel_type_range;
307 break;
308 case LTTNG_UST_LOGLEVEL_SINGLE:
309 loglevel_type_string = config_loglevel_type_single;
310 break;
311 default:
312 loglevel_type_string = NULL;
313 }
314
315 return loglevel_type_string;
316}
317
318static
319int save_kernel_event(struct config_writer *writer,
320 struct ltt_kernel_event *event)
321{
322 int ret;
323 const char *instrumentation_type;
324
325 ret = config_writer_open_element(writer, config_element_event);
326 if (ret) {
327 ret = LTTNG_ERR_SAVE_IO_FAIL;
328 goto end;
329 }
330
331 if (event->event->name[0]) {
332 ret = config_writer_write_element_string(writer,
333 config_element_name, event->event->name);
334 if (ret) {
335 ret = LTTNG_ERR_SAVE_IO_FAIL;
336 goto end;
337 }
338 }
339
340 ret = config_writer_write_element_bool(writer, config_element_enabled,
341 event->enabled);
342 if (ret) {
343 ret = LTTNG_ERR_SAVE_IO_FAIL;
344 goto end;
345 }
346
347 instrumentation_type = get_kernel_instrumentation_string(
348 event->event->instrumentation);
349 if (!instrumentation_type) {
350 ret = LTTNG_ERR_INVALID;
351 goto end;
352 }
353
354 ret = config_writer_write_element_string(writer, config_element_type,
355 instrumentation_type);
356 if (ret) {
357 ret = LTTNG_ERR_SAVE_IO_FAIL;
358 goto end;
359 }
360
361 if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
362 event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
363 event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
364
365 ret = config_writer_open_element(writer,
366 config_element_attributes);
367 if (ret) {
368 ret = LTTNG_ERR_SAVE_IO_FAIL;
369 goto end;
370 }
371
372 switch (event->event->instrumentation) {
373 case LTTNG_KERNEL_FUNCTION:
374 ret = config_writer_open_element(writer,
375 config_element_function_attributes);
376 if (ret) {
377 ret = LTTNG_ERR_SAVE_IO_FAIL;
378 goto end;
379 }
380
381 ret = config_writer_write_element_string(writer,
382 config_element_name,
383 event->event->u.ftrace.symbol_name);
384 if (ret) {
385 ret = LTTNG_ERR_SAVE_IO_FAIL;
386 goto end;
387 }
388
389 /* /function attributes */
390 ret = config_writer_close_element(writer);
391 if (ret) {
392 ret = LTTNG_ERR_SAVE_IO_FAIL;
393 goto end;
394 }
395 break;
396 case LTTNG_KERNEL_KPROBE:
397 case LTTNG_KERNEL_KRETPROBE:
398 {
399 const char *symbol_name;
400 uint64_t addr;
401 uint64_t offset;
402
403 if (event->event->instrumentation ==
404 LTTNG_KERNEL_KPROBE) {
405 /*
406 * Comments in lttng-kernel.h mention that
407 * either addr or symbol_name are set, not both.
408 */
409 addr = event->event->u.kprobe.addr;
410 offset = event->event->u.kprobe.offset;
411 symbol_name = addr ? NULL :
412 event->event->u.kprobe.symbol_name;
413 } else {
414 symbol_name =
415 event->event->u.kretprobe.symbol_name;
416 addr = event->event->u.kretprobe.addr;
417 offset = event->event->u.kretprobe.offset;
418 }
419
420 ret = config_writer_open_element(writer,
421 config_element_probe_attributes);
422 if (ret) {
423 ret = LTTNG_ERR_SAVE_IO_FAIL;
424 goto end;
425 }
426
427 if (symbol_name) {
428 ret = config_writer_write_element_string(writer,
429 config_element_symbol_name,
430 symbol_name);
431 if (ret) {
432 ret = LTTNG_ERR_SAVE_IO_FAIL;
433 goto end;
434 }
435 }
436
437 if (addr) {
438 ret = config_writer_write_element_unsigned_int(
439 writer, config_element_address, addr);
440 if (ret) {
441 ret = LTTNG_ERR_SAVE_IO_FAIL;
442 goto end;
443 }
444 }
445
446 if (offset) {
447 ret = config_writer_write_element_unsigned_int(
448 writer, config_element_offset, offset);
449 if (ret) {
450 ret = LTTNG_ERR_SAVE_IO_FAIL;
451 goto end;
452 }
453 }
454
455 ret = config_writer_close_element(writer);
456 if (ret) {
457 ret = LTTNG_ERR_SAVE_IO_FAIL;
458 goto end;
459 }
460 break;
461 }
462 default:
463 ERR("Unsupported kernel instrumentation type.");
464 ret = LTTNG_ERR_INVALID;
465 goto end;
466 }
467
468 /* /attributes */
469 ret = config_writer_close_element(writer);
470 if (ret) {
471 ret = LTTNG_ERR_SAVE_IO_FAIL;
472 goto end;
473 }
474 }
475
476 /* /event */
477 ret = config_writer_close_element(writer);
478 if (ret) {
479 ret = LTTNG_ERR_SAVE_IO_FAIL;
480 goto end;
481 }
482end:
483 return ret;
484}
485
486static
487int save_kernel_events(struct config_writer *writer,
488 struct ltt_kernel_event_list *event_list)
489{
490 int ret;
491 struct ltt_kernel_event *event;
492
493 ret = config_writer_open_element(writer, config_element_events);
494 if (ret) {
495 ret = LTTNG_ERR_SAVE_IO_FAIL;
496 goto end;
497 }
498
499 cds_list_for_each_entry(event, &event_list->head, list) {
500 ret = save_kernel_event(writer, event);
501 if (ret) {
502 goto end;
503 }
504 }
505
506 /* /events */
507 ret = config_writer_close_element(writer);
508 if (ret) {
509 ret = LTTNG_ERR_SAVE_IO_FAIL;
510 goto end;
511 }
512end:
513 return ret;
514}
515
516static
517int save_ust_event(struct config_writer *writer,
518 struct ltt_ust_event *event)
519{
520 int ret;
521 const char *loglevel_type_string;
522
523 ret = config_writer_open_element(writer, config_element_event);
524 if (ret) {
525 ret = LTTNG_ERR_SAVE_IO_FAIL;
526 goto end;
527 }
528
529 if (event->attr.name[0]) {
530 ret = config_writer_write_element_string(writer,
531 config_element_name, event->attr.name);
532 if (ret) {
533 ret = LTTNG_ERR_SAVE_IO_FAIL;
534 goto end;
535 }
536 }
537
538 ret = config_writer_write_element_bool(writer, config_element_enabled,
539 event->enabled);
540 if (ret) {
541 ret = LTTNG_ERR_SAVE_IO_FAIL;
542 goto end;
543 }
544
545 if (event->attr.instrumentation != LTTNG_UST_TRACEPOINT) {
546 ERR("Unsupported UST instrumentation type.");
547 ret = LTTNG_ERR_INVALID;
548 goto end;
549 }
550 ret = config_writer_write_element_string(writer, config_element_type,
551 config_event_type_tracepoint);
552 if (ret) {
553 ret = LTTNG_ERR_SAVE_IO_FAIL;
554 goto end;
555 }
556
557 loglevel_type_string = get_loglevel_type_string(
558 event->attr.loglevel_type);
559 if (!loglevel_type_string) {
560 ERR("Unsupported UST loglevel type.");
561 ret = LTTNG_ERR_INVALID;
562 goto end;
563 }
564
565 ret = config_writer_write_element_string(writer,
566 config_element_loglevel_type, loglevel_type_string);
567 if (ret) {
568 ret = LTTNG_ERR_SAVE_IO_FAIL;
569 goto end;
570 }
571
572 ret = config_writer_write_element_signed_int(writer,
573 config_element_loglevel, event->attr.loglevel);
574 if (ret) {
575 ret = LTTNG_ERR_SAVE_IO_FAIL;
576 goto end;
577 }
578
579 if (event->filter_expression) {
580 ret = config_writer_write_element_string(writer,
581 config_element_filter, event->filter_expression);
582 if (ret) {
583 ret = LTTNG_ERR_SAVE_IO_FAIL;
584 goto end;
585 }
586 }
587
588 if (event->exclusion && event->exclusion->count) {
589 uint32_t i;
590
591 ret = config_writer_open_element(writer,
592 config_element_exclusions);
593 if (ret) {
594 ret = LTTNG_ERR_SAVE_IO_FAIL;
595 goto end;
596 }
597
598 for (i = 0; i < event->exclusion->count; i++) {
599 ret = config_writer_write_element_string(writer,
600 config_element_exclusion,
601 &event->exclusion->names[0][i]);
602 if (ret) {
603 ret = LTTNG_ERR_SAVE_IO_FAIL;
604 goto end;
605 }
606 }
607
608 /* /exclusions */
609 ret = config_writer_close_element(writer);
610 if (ret) {
611 ret = LTTNG_ERR_SAVE_IO_FAIL;
612 goto end;
613 }
614 }
615
616 /* /event */
617 ret = config_writer_close_element(writer);
618 if (ret) {
619 ret = LTTNG_ERR_SAVE_IO_FAIL;
620 goto end;
621 }
622end:
623 return ret;
624}
625
626static
627int save_ust_events(struct config_writer *writer,
628 struct lttng_ht *events)
629{
630 int ret;
631 struct ltt_ust_event *event;
632 struct lttng_ht_node_str *node;
633 struct lttng_ht_iter iter;
634
635 ret = config_writer_open_element(writer, config_element_events);
636 if (ret) {
637 ret = LTTNG_ERR_SAVE_IO_FAIL;
638 goto end;
639 }
640
641 rcu_read_lock();
642 cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) {
643 event = caa_container_of(node, struct ltt_ust_event, node);
644
645 ret = save_ust_event(writer, event);
646 if (ret) {
647 rcu_read_unlock();
648 goto end;
649 }
650 }
651 rcu_read_unlock();
652
653 /* /events */
654 ret = config_writer_close_element(writer);
655 if (ret) {
656 ret = LTTNG_ERR_SAVE_IO_FAIL;
657 goto end;
658 }
659end:
660 return ret;
661}
662
663static
664int save_kernel_context(struct config_writer *writer,
665 struct lttng_kernel_context *ctx)
666{
667 int ret = 0;
668
669 if (!ctx) {
670 goto end;
671 }
672
fb198a11
JG
673 ret = config_writer_open_element(writer, config_element_context);
674 if (ret) {
675 ret = LTTNG_ERR_SAVE_IO_FAIL;
676 goto end;
677 }
678
cba45eda 679 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
fb198a11
JG
680 ret = config_writer_open_element(writer, config_element_perf);
681 if (ret) {
682 ret = LTTNG_ERR_SAVE_IO_FAIL;
683 goto end;
684 }
685
686 ret = config_writer_write_element_unsigned_int(writer,
687 config_element_type, ctx->u.perf_counter.type);
688 if (ret) {
689 ret = LTTNG_ERR_SAVE_IO_FAIL;
690 goto end;
691 }
692
693 ret = config_writer_write_element_unsigned_int(writer,
694 config_element_config, ctx->u.perf_counter.config);
695 if (ret) {
696 ret = LTTNG_ERR_SAVE_IO_FAIL;
697 goto end;
698 }
699
700 ret = config_writer_write_element_string(writer,
701 config_element_name, ctx->u.perf_counter.name);
702 if (ret) {
703 ret = LTTNG_ERR_SAVE_IO_FAIL;
704 goto end;
705 }
706
707 /* /perf */
708 ret = config_writer_close_element(writer);
709 if (ret) {
710 ret = LTTNG_ERR_SAVE_IO_FAIL;
711 goto end;
712 }
713 } else {
714 const char *context_type_string =
715 get_kernel_context_type_string(ctx->ctx);
716
717 if (!context_type_string) {
718 ERR("Unsupported kernel context type.");
719 ret = LTTNG_ERR_INVALID;
720 goto end;
721 }
722
723 ret = config_writer_write_element_string(writer,
724 config_element_type, context_type_string);
725 if (ret) {
726 ret = LTTNG_ERR_SAVE_IO_FAIL;
727 goto end;
728 }
729 }
730
731 /* /context */
732 ret = config_writer_close_element(writer);
733 if (ret) {
734 ret = LTTNG_ERR_SAVE_IO_FAIL;
735 goto end;
736 }
737
645328ae
DG
738end:
739 return ret;
740}
741
742static
743int save_kernel_contexts(struct config_writer *writer,
744 struct ltt_kernel_channel *kchan)
745{
746 int ret;
747 struct ltt_kernel_context *ctx;
748
749 ret = config_writer_open_element(writer, config_element_contexts);
750 if (ret) {
751 ret = LTTNG_ERR_SAVE_IO_FAIL;
752 goto end;
753 }
754
755 cds_list_for_each_entry(ctx, &kchan->ctx_list, list) {
756 ret = save_kernel_context(writer, &ctx->ctx);
757 if (ret) {
758 goto end;
759 }
760 }
761
fb198a11
JG
762 /* /contexts */
763 ret = config_writer_close_element(writer);
764 if (ret) {
765 ret = LTTNG_ERR_SAVE_IO_FAIL;
766 goto end;
767 }
768end:
769 return ret;
770}
771
772static
773int save_ust_context(struct config_writer *writer,
774 struct cds_list_head *ctx_list)
775{
776 int ret;
777 struct ltt_ust_context *ctx;
778
779 assert(writer);
780 assert(ctx_list);
781
782 ret = config_writer_open_element(writer, config_element_contexts);
783 if (ret) {
784 ret = LTTNG_ERR_SAVE_IO_FAIL;
785 goto end;
786 }
787
788 cds_list_for_each_entry(ctx, ctx_list, list) {
789 const char *context_type_string;
790
791 context_type_string = get_ust_context_type_string(ctx->ctx.ctx);
792 if (!context_type_string) {
793 ERR("Unsupported UST context type.")
794 ret = LTTNG_ERR_INVALID;
795 goto end;
796 }
797
798 ret = config_writer_open_element(writer,
799 config_element_context);
800 if (ret) {
801 ret = LTTNG_ERR_SAVE_IO_FAIL;
802 goto end;
803 }
804
805 ret = config_writer_write_element_string(writer,
806 config_element_type, context_type_string);
807 if (ret) {
808 ret = LTTNG_ERR_SAVE_IO_FAIL;
809 goto end;
810 }
811
812 /* /context */
813 ret = config_writer_close_element(writer);
814 if (ret) {
815 ret = LTTNG_ERR_SAVE_IO_FAIL;
816 goto end;
817 }
818 }
819
820 /* /contexts */
821 ret = config_writer_close_element(writer);
822 if (ret) {
823 ret = LTTNG_ERR_SAVE_IO_FAIL;
824 goto end;
825 }
826end:
827 return ret;
828}
829
830static
831int save_kernel_channel(struct config_writer *writer,
832 struct ltt_kernel_channel *kchan)
833{
834 int ret;
835
836 assert(writer);
837 assert(kchan);
838
839 ret = config_writer_open_element(writer, config_element_channel);
840 if (ret) {
841 ret = LTTNG_ERR_SAVE_IO_FAIL;
842 goto end;
843 }
844
845 ret = config_writer_write_element_string(writer, config_element_name,
846 kchan->channel->name);
847 if (ret) {
848 ret = LTTNG_ERR_SAVE_IO_FAIL;
849 goto end;
850 }
851
852 ret = config_writer_write_element_bool(writer, config_element_enabled,
853 kchan->channel->enabled);
854 if (ret) {
855 ret = LTTNG_ERR_SAVE_IO_FAIL;
856 goto end;
857 }
858
859 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
860 if (ret) {
861 goto end;
862 }
863
864 ret = save_kernel_events(writer, &kchan->events_list);
865 if (ret) {
866 goto end;
867 }
868
645328ae 869 ret = save_kernel_contexts(writer, kchan);
fb198a11
JG
870 if (ret) {
871 goto end;
872 }
873
874 /* /channel */
875 ret = config_writer_close_element(writer);
876 if (ret) {
877 ret = LTTNG_ERR_SAVE_IO_FAIL;
878 goto end;
879 }
880end:
881 return ret;
882}
883
884static
885int save_ust_channel(struct config_writer *writer,
886 struct ltt_ust_channel *ust_chan,
887 struct ltt_ust_session *session)
888{
889 int ret;
890
891 assert(writer);
892 assert(ust_chan);
893 assert(session);
894
895 ret = config_writer_open_element(writer, config_element_channel);
896 if (ret) {
897 ret = LTTNG_ERR_SAVE_IO_FAIL;
898 goto end;
899 }
900
901 ret = config_writer_write_element_string(writer, config_element_name,
902 ust_chan->name);
903 if (ret) {
904 ret = LTTNG_ERR_SAVE_IO_FAIL;
905 goto end;
906 }
907
908 ret = config_writer_write_element_bool(writer, config_element_enabled,
909 ust_chan->enabled);
910 if (ret) {
911 ret = LTTNG_ERR_SAVE_IO_FAIL;
912 goto end;
913 }
914
915 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
916 if (ret) {
917 goto end;
918 }
919
920 ret = config_writer_write_element_unsigned_int(writer,
921 config_element_tracefile_size, ust_chan->tracefile_size);
922 if (ret) {
923 ret = LTTNG_ERR_SAVE_IO_FAIL;
924 goto end;
925 }
926
927 ret = config_writer_write_element_unsigned_int(writer,
928 config_element_tracefile_count, ust_chan->tracefile_count);
929 if (ret) {
930 ret = LTTNG_ERR_SAVE_IO_FAIL;
931 goto end;
932 }
933
934 ret = config_writer_write_element_unsigned_int(writer,
935 config_element_live_timer_interval,
936 session->live_timer_interval);
937 if (ret) {
938 ret = LTTNG_ERR_SAVE_IO_FAIL;
939 goto end;
940 }
941
942 ret = save_ust_events(writer, ust_chan->events);
943 if (ret) {
944 ret = LTTNG_ERR_SAVE_IO_FAIL;
945 goto end;
946 }
947
948 ret = save_ust_context(writer, &ust_chan->ctx_list);
949 if (ret) {
950 goto end;
951 }
952
953 /* /channel */
954 ret = config_writer_close_element(writer);
955 if (ret) {
956 ret = LTTNG_ERR_SAVE_IO_FAIL;
957 goto end;
958 }
959end:
960 return ret;
961}
962
963static
964int save_kernel_session(struct config_writer *writer,
965 struct ltt_session *session)
966{
967 int ret;
968 struct ltt_kernel_channel *kchan;
969
970 assert(writer);
971 assert(session);
972
973 ret = config_writer_write_element_string(writer, config_element_type,
974 config_domain_type_kernel);
975 if (ret) {
976 ret = LTTNG_ERR_SAVE_IO_FAIL;
977 goto end;
978 }
979
980 ret = config_writer_write_element_string(writer,
981 config_element_buffer_type, config_buffer_type_global);
982 if (ret) {
983 ret = LTTNG_ERR_SAVE_IO_FAIL;
984 goto end;
985 }
986
987 ret = config_writer_open_element(writer,
988 config_element_channels);
989 if (ret) {
990 ret = LTTNG_ERR_SAVE_IO_FAIL;
991 goto end;
992 }
993
994 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
995 list) {
996 ret = save_kernel_channel(writer, kchan);
997 if (ret) {
998 goto end;
999 }
1000 }
1001
1002 /* /channels */
1003 ret = config_writer_close_element(writer);
1004 if (ret) {
1005 ret = LTTNG_ERR_SAVE_IO_FAIL;
1006 goto end;
1007 }
1008end:
1009 return ret;
1010}
1011
1012static
1013int save_ust_session(struct config_writer *writer,
022d91ba 1014 struct ltt_session *session, int save_agent)
fb198a11
JG
1015{
1016 int ret;
1017 struct ltt_ust_channel *ust_chan;
1018 const char *buffer_type_string;
1019 struct lttng_ht_node_str *node;
1020 struct lttng_ht_iter iter;
1021
1022 assert(writer);
1023 assert(session);
1024
1025 ret = config_writer_write_element_string(writer, config_element_type,
022d91ba 1026 save_agent ? config_domain_type_jul : config_domain_type_ust);
fb198a11
JG
1027 if (ret) {
1028 ret = LTTNG_ERR_SAVE_IO_FAIL;
1029 goto end;
1030 }
1031
1032 buffer_type_string = get_buffer_type_string(
1033 session->ust_session->buffer_type);
1034 if (!buffer_type_string) {
1035 ERR("Unsupported buffer type.");
1036 ret = LTTNG_ERR_INVALID;
1037 goto end;
1038 }
1039
1040 ret = config_writer_write_element_string(writer,
1041 config_element_buffer_type, buffer_type_string);
1042 if (ret) {
1043 ret = LTTNG_ERR_SAVE_IO_FAIL;
1044 goto end;
1045 }
1046
1047 ret = config_writer_open_element(writer, config_element_channels);
1048 if (ret) {
1049 ret = LTTNG_ERR_SAVE_IO_FAIL;
1050 goto end;
1051 }
1052
1053 rcu_read_lock();
1054 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1055 &iter.iter, node, node) {
022d91ba 1056 int agent_channel;
fb198a11
JG
1057
1058 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
da6c3a50
DG
1059 agent_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name) ||
1060 !strcmp(DEFAULT_LOG4J_CHANNEL_NAME, ust_chan->name);
022d91ba 1061 if (!(save_agent ^ agent_channel)) {
fb198a11
JG
1062 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1063 if (ret) {
1064 rcu_read_unlock();
1065 goto end;
1066 }
1067 }
1068 }
1069 rcu_read_unlock();
1070
1071 /* /channels */
1072 ret = config_writer_close_element(writer);
1073 if (ret) {
1074 ret = LTTNG_ERR_SAVE_IO_FAIL;
1075 goto end;
1076 }
1077end:
1078 return ret;
1079}
1080
1081static
1082int save_domains(struct config_writer *writer, struct ltt_session *session)
1083{
1084 int ret = 0;
1085
1086 assert(writer);
1087 assert(session);
1088
1089 if (!session->kernel_session && !session->ust_session) {
1090 goto end;
1091 }
1092
1093 ret = config_writer_open_element(writer, config_element_domains);
1094 if (ret) {
1095 ret = LTTNG_ERR_SAVE_IO_FAIL;
1096 goto end;
1097 }
1098
1099
1100 if (session->kernel_session) {
1101 ret = config_writer_open_element(writer,
1102 config_element_domain);
1103 if (ret) {
1104 ret = LTTNG_ERR_SAVE_IO_FAIL;
1105 goto end;
1106 }
1107
1108 ret = save_kernel_session(writer, session);
1109 if (ret) {
1110 goto end;
1111 }
1112
1113 /* /domain */
1114 ret = config_writer_close_element(writer);
1115 if (ret) {
1116 ret = LTTNG_ERR_SAVE_IO_FAIL;
1117 goto end;
1118 }
1119 }
1120
1121 if (session->ust_session) {
1122 ret = config_writer_open_element(writer,
1123 config_element_domain);
1124 if (ret) {
1125 ret = LTTNG_ERR_SAVE_IO_FAIL;
1126 goto end;
1127 }
1128
1129 ret = save_ust_session(writer, session, 0);
1130 if (ret) {
1131 goto end;
1132 }
1133
1134 /* /domain */
1135 ret = config_writer_close_element(writer);
1136 if (ret) {
1137 ret = LTTNG_ERR_SAVE_IO_FAIL;
1138 goto end;
1139 }
1140 }
1141
1142 if (session->ust_session &&
fefd409b 1143 lttng_ht_get_count(session->ust_session->agents) > 0) {
fb198a11
JG
1144 ret = config_writer_open_element(writer,
1145 config_element_domain);
1146 if (ret) {
1147 ret = LTTNG_ERR_SAVE_IO_FAIL;
1148 goto end;
1149 }
1150
1151 ret = save_ust_session(writer, session, 1);
1152 if (ret) {
1153 goto end;
1154 }
1155
1156 /* /domain */
1157 ret = config_writer_close_element(writer);
1158 if (ret) {
1159 ret = LTTNG_ERR_SAVE_IO_FAIL;
1160 goto end;
1161 }
1162 }
1163
1164 /* /domains */
1165 ret = config_writer_close_element(writer);
1166 if (ret) {
1167 ret = LTTNG_ERR_SAVE_IO_FAIL;
1168 goto end;
1169 }
1170end:
1171 return ret;
1172}
1173
1174static
1175int save_consumer_output(struct config_writer *writer,
1176 struct consumer_output *output)
1177{
1178 int ret;
1179
1180 assert(writer);
1181 assert(output);
1182
1183 ret = config_writer_open_element(writer, config_element_consumer_output);
1184 if (ret) {
1185 ret = LTTNG_ERR_SAVE_IO_FAIL;
1186 goto end;
1187 }
1188
1189 ret = config_writer_write_element_bool(writer, config_element_enabled,
1190 output->enabled);
1191 if (ret) {
1192 ret = LTTNG_ERR_SAVE_IO_FAIL;
1193 goto end;
1194 }
1195
1196 ret = config_writer_open_element(writer, config_element_destination);
1197 if (ret) {
1198 ret = LTTNG_ERR_SAVE_IO_FAIL;
1199 goto end;
1200 }
1201
1202 switch (output->type) {
1203 case CONSUMER_DST_LOCAL:
1204 ret = config_writer_write_element_string(writer,
1205 config_element_path, output->dst.trace_path);
1206 if (ret) {
1207 ret = LTTNG_ERR_SAVE_IO_FAIL;
1208 goto end;
1209 }
1210 break;
1211 case CONSUMER_DST_NET:
1212 {
1213 char *uri;
1214
1215 uri = zmalloc(PATH_MAX);
1216 if (!uri) {
1217 ret = LTTNG_ERR_NOMEM;
1218 goto end;
1219 }
1220
1221 ret = config_writer_open_element(writer, config_element_net_output);
1222 if (ret) {
1223 ret = LTTNG_ERR_SAVE_IO_FAIL;
1224 goto end_net_output;
1225 }
1226
1227 if (output->dst.net.control_isset &&
1228 output->dst.net.data_isset) {
1229 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1230 if (ret < 0) {
1231 ret = LTTNG_ERR_INVALID;
1232 goto end_net_output;
1233 }
1234
1235 ret = config_writer_write_element_string(writer,
1236 config_element_control_uri, uri);
1237 if (ret) {
1238 ret = LTTNG_ERR_SAVE_IO_FAIL;
1239 goto end_net_output;
1240 }
1241
1242 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1243 if (ret < 0) {
1244 ret = LTTNG_ERR_INVALID;
1245 goto end_net_output;
1246 }
1247
1248 ret = config_writer_write_element_string(writer,
1249 config_element_data_uri, uri);
1250 if (ret) {
1251 ret = LTTNG_ERR_SAVE_IO_FAIL;
1252 goto end_net_output;
1253 }
1254
1255end_net_output:
1256 free(uri);
1257 if (ret) {
1258 goto end;
1259 }
1260 } else {
1261 ret = !output->dst.net.control_isset ?
1262 LTTNG_ERR_URL_CTRL_MISS :
1263 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1264 free(uri);
fb198a11
JG
1265 goto end;
1266 }
1267
1268 ret = config_writer_close_element(writer);
1269 if (ret) {
1270 ret = LTTNG_ERR_SAVE_IO_FAIL;
1271 goto end;
1272 }
1273 break;
1274 }
1275 default:
1276 ERR("Unsupported consumer output type.");
1277 ret = LTTNG_ERR_INVALID;
1278 goto end;
1279 }
1280
1281 /* /destination */
1282 ret = config_writer_close_element(writer);
1283 if (ret) {
1284 ret = LTTNG_ERR_SAVE_IO_FAIL;
1285 goto end;
1286 }
1287
1288 /* /consumer_output */
1289 ret = config_writer_close_element(writer);
1290 if (ret) {
1291 ret = LTTNG_ERR_SAVE_IO_FAIL;
1292 goto end;
1293 }
1294end:
1295 return ret;
1296}
1297
1298static
1299int save_snapshot_outputs(struct config_writer *writer,
1300 struct snapshot *snapshot)
1301{
1302 int ret;
1303 struct lttng_ht_iter iter;
1304 struct snapshot_output *output;
1305
1306 assert(writer);
1307 assert(snapshot);
1308
1309 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1310 if (ret) {
1311 ret = LTTNG_ERR_SAVE_IO_FAIL;
1312 goto end;
1313 }
1314
1315 rcu_read_lock();
1316 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1317 node.node) {
1318 ret = config_writer_open_element(writer,
1319 config_element_output);
1320 if (ret) {
1321 ret = LTTNG_ERR_SAVE_IO_FAIL;
1322 goto end_unlock;
1323 }
1324
1325 ret = config_writer_write_element_string(writer,
1326 config_element_name, output->name);
1327 if (ret) {
1328 ret = LTTNG_ERR_SAVE_IO_FAIL;
1329 goto end_unlock;
1330 }
1331
1332 ret = config_writer_write_element_unsigned_int(writer,
1333 config_element_max_size, output->max_size);
1334 if (ret) {
1335 ret = LTTNG_ERR_SAVE_IO_FAIL;
1336 goto end_unlock;
1337 }
1338
1339 ret = save_consumer_output(writer, output->consumer);
1340 if (ret) {
1341 goto end_unlock;
1342 }
1343
1344 /* /output */
1345 ret = config_writer_close_element(writer);
1346 if (ret) {
1347 ret = LTTNG_ERR_SAVE_IO_FAIL;
1348 goto end_unlock;
1349 }
1350 }
1351 rcu_read_unlock();
1352
1353 /* /snapshot_outputs */
1354 ret = config_writer_close_element(writer);
1355 if (ret) {
1356 ret = LTTNG_ERR_SAVE_IO_FAIL;
1357 goto end;
1358 }
1359
1360end:
1361 return ret;
1362end_unlock:
1363 rcu_read_unlock();
1364 return ret;
1365}
1366
1367static
1368int save_session_output(struct config_writer *writer,
1369 struct ltt_session *session)
1370{
1371 int ret;
1372
1373 assert(writer);
1374 assert(session);
1375
1376 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1377 (!session->snapshot_mode && !session->consumer)) {
1378 /* Session is in no output mode */
1379 ret = 0;
1380 goto end;
1381 }
1382
1383 ret = config_writer_open_element(writer, config_element_output);
1384 if (ret) {
1385 ret = LTTNG_ERR_SAVE_IO_FAIL;
1386 goto end;
1387 }
1388
1389 if (session->snapshot_mode) {
1390 ret = save_snapshot_outputs(writer, &session->snapshot);
1391 if (ret) {
1392 goto end;
1393 }
1394 } else {
1395 if (session->consumer) {
1396 ret = save_consumer_output(writer, session->consumer);
1397 if (ret) {
1398 goto end;
1399 }
1400 }
1401 }
1402
1403 /* /output */
1404 ret = config_writer_close_element(writer);
1405 if (ret) {
1406 ret = LTTNG_ERR_SAVE_IO_FAIL;
1407 goto end;
1408 }
1409end:
1410 return ret;
1411}
1412
1413/*
1414 * Save the given session.
1415 *
1416 * Return 0 on success else a LTTNG_ERR* code.
1417 */
1418static
1419int save_session(struct ltt_session *session,
1420 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1421{
1422 int ret, fd;
db471218 1423 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
1424 char config_file_path[PATH_MAX];
1425 size_t len;
1426 struct config_writer *writer = NULL;
1427 size_t session_name_len;
1428 const char *provided_path;
1429
1430 assert(session);
1431 assert(attr);
1432 assert(creds);
1433
1434 session_name_len = strlen(session->name);
95a29ab8 1435 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
1436
1437 if (!session_access_ok(session,
1438 LTTNG_SOCK_GET_UID_CRED(creds),
1439 LTTNG_SOCK_GET_GID_CRED(creds))) {
1440 ret = LTTNG_ERR_EPERM;
1441 goto end;
1442 }
1443
1444 provided_path = lttng_save_session_attr_get_output_url(attr);
1445 if (provided_path) {
95a29ab8 1446 DBG3("Save session in provided path %s", provided_path);
fb198a11 1447 len = strlen(provided_path);
d2992717 1448 if (len >= sizeof(config_file_path)) {
fb198a11
JG
1449 ret = LTTNG_ERR_SET_URL;
1450 goto end;
1451 }
1452 strncpy(config_file_path, provided_path, len);
1453 } else {
7e078ad1 1454 ssize_t ret_len;
fb198a11
JG
1455 char *home_dir = utils_get_user_home_dir(
1456 LTTNG_SOCK_GET_UID_CRED(creds));
1457 if (!home_dir) {
1458 ret = LTTNG_ERR_SET_URL;
1459 goto end;
1460 }
1461
d2992717 1462 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
1463 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1464 free(home_dir);
7e078ad1 1465 if (ret_len < 0) {
fb198a11
JG
1466 PERROR("snprintf save session");
1467 ret = LTTNG_ERR_SET_URL;
1468 goto end;
1469 }
7e078ad1 1470 len = ret_len;
fb198a11
JG
1471 }
1472
1473 /*
d2992717
DG
1474 * Check the path fits in the config file path dst including the '/'
1475 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 1476 */
d2992717
DG
1477 if ((len + session_name_len + 2 +
1478 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1479 > sizeof(config_file_path)) {
fb198a11
JG
1480 ret = LTTNG_ERR_SET_URL;
1481 goto end;
1482 }
1483
1484 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1485 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1486 if (ret) {
1487 ret = LTTNG_ERR_SET_URL;
1488 goto end;
1489 }
1490
d2992717
DG
1491 /*
1492 * At this point, we know that everything fits in the buffer. Validation
1493 * was done just above.
1494 */
fb198a11
JG
1495 config_file_path[len++] = '/';
1496 strncpy(config_file_path + len, session->name, session_name_len);
1497 len += session_name_len;
1498 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
1499 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1500 config_file_path[len] = '\0';
fb198a11
JG
1501
1502 if (!access(config_file_path, F_OK) && !attr->overwrite) {
f9b57ab2
DG
1503 /* File exists, notify the user since the overwrite flag is off. */
1504 ret = LTTNG_ERR_SAVE_FILE_EXIST;
fb198a11
JG
1505 goto end;
1506 }
1507
1508 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1509 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1510 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1511 if (fd < 0) {
1512 PERROR("Could not create configuration file");
1513 ret = LTTNG_ERR_SAVE_IO_FAIL;
1514 goto end;
1515 }
db471218 1516 file_opened = 1;
fb198a11 1517
705bb62f 1518 writer = config_writer_create(fd, 1);
fb198a11
JG
1519 if (!writer) {
1520 ret = LTTNG_ERR_NOMEM;
1521 goto end;
1522 }
1523
1524 ret = config_writer_open_element(writer, config_element_sessions);
1525 if (ret) {
1526 ret = LTTNG_ERR_SAVE_IO_FAIL;
1527 goto end;
1528 }
1529
1530 ret = config_writer_open_element(writer, config_element_session);
1531 if (ret) {
1532 ret = LTTNG_ERR_SAVE_IO_FAIL;
1533 goto end;
1534 }
1535
1536 ret = config_writer_write_element_string(writer, config_element_name,
1537 session->name);
1538 if (ret) {
1539 ret = LTTNG_ERR_SAVE_IO_FAIL;
1540 goto end;
1541 }
1542
1543 ret = save_domains(writer, session);
1544 if (ret) {
1545 goto end;
1546 }
1547
1548 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 1549 session->active);
fb198a11
JG
1550 if (ret) {
1551 ret = LTTNG_ERR_SAVE_IO_FAIL;
1552 goto end;
1553 }
1554
1555 if (session->snapshot_mode || session->live_timer) {
1556 ret = config_writer_open_element(writer, config_element_attributes);
1557 if (ret) {
1558 ret = LTTNG_ERR_SAVE_IO_FAIL;
1559 goto end;
1560 }
1561
1562 if (session->snapshot_mode) {
1563 ret = config_writer_write_element_bool(writer,
1564 config_element_snapshot_mode, 1);
1565 if (ret) {
1566 ret = LTTNG_ERR_SAVE_IO_FAIL;
1567 goto end;
1568 }
1569 } else {
d98ad589 1570 ret = config_writer_write_element_unsigned_int(writer,
fb198a11
JG
1571 config_element_live_timer_interval, session->live_timer);
1572 if (ret) {
1573 ret = LTTNG_ERR_SAVE_IO_FAIL;
1574 goto end;
1575 }
1576 }
1577
1578 /* /attributes */
1579 ret = config_writer_close_element(writer);
1580 if (ret) {
1581 ret = LTTNG_ERR_SAVE_IO_FAIL;
1582 goto end;
1583 }
1584 }
1585
1586 ret = save_session_output(writer, session);
1587 if (ret) {
1588 goto end;
1589 }
1590
1591 /* /session */
1592 ret = config_writer_close_element(writer);
1593 if (ret) {
1594 ret = LTTNG_ERR_SAVE_IO_FAIL;
1595 goto end;
1596 }
1597
1598 /* /sessions */
1599 ret = config_writer_close_element(writer);
1600 if (ret) {
1601 ret = LTTNG_ERR_SAVE_IO_FAIL;
1602 goto end;
1603 }
1604end:
1605 if (writer && config_writer_destroy(writer)) {
1606 /* Preserve the original error code */
1607 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1608 }
1609 if (ret) {
1610 /* Delete file in case of error */
db471218 1611 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
1612 PERROR("Unlinking XML session configuration.");
1613 }
1614 }
1615
1616 return ret;
1617}
1618
1619int cmd_save_sessions(struct lttng_save_session_attr *attr,
1620 lttng_sock_cred *creds)
1621{
1622 int ret;
1623 const char *session_name;
1624 struct ltt_session *session;
1625
1626 session_lock_list();
1627
1628 session_name = lttng_save_session_attr_get_session_name(attr);
1629 if (session_name) {
1630 session = session_find_by_name(session_name);
1631 if (!session) {
1632 ret = LTTNG_ERR_SESS_NOT_FOUND;
1633 goto end;
1634 }
1635
1636 session_lock(session);
1637 ret = save_session(session, attr, creds);
1638 session_unlock(session);
1639 if (ret) {
1640 goto end;
1641 }
1642 } else {
1643 struct ltt_session_list *list = session_get_list();
1644
1645 cds_list_for_each_entry(session, &list->head, list) {
1646 session_lock(session);
1647 ret = save_session(session, attr, creds);
1648 session_unlock(session);
1649
1650 /* Don't abort if we don't have the required permissions. */
1651 if (ret && ret != LTTNG_ERR_EPERM) {
1652 goto end;
1653 }
1654 }
1655 }
1656 ret = LTTNG_OK;
1657
1658end:
1659 session_unlock_list();
1660 return ret;
1661}
This page took 0.111494 seconds and 4 git commands to generate.