Use common functions for module loading and unloading
[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;
261 default:
262 context_type_string = NULL;
263 }
264
265 return context_type_string;
266}
267
268static
269const char *get_buffer_type_string(
270 enum lttng_buffer_type buffer_type)
271{
272 const char *buffer_type_string;
273
274 switch (buffer_type) {
275 case LTTNG_BUFFER_PER_PID:
276 buffer_type_string = config_buffer_type_per_pid;
277 break;
278 case LTTNG_BUFFER_PER_UID:
279 buffer_type_string = config_buffer_type_per_uid;
280 break;
281 case LTTNG_BUFFER_GLOBAL:
282 buffer_type_string = config_buffer_type_global;
283 break;
284 default:
285 buffer_type_string = NULL;
286 }
287
288 return buffer_type_string;
289}
290
291static
292const char *get_loglevel_type_string(
293 enum lttng_ust_loglevel_type loglevel_type)
294{
295 const char *loglevel_type_string;
296
297 switch (loglevel_type) {
298 case LTTNG_UST_LOGLEVEL_ALL:
299 loglevel_type_string = config_loglevel_type_all;
300 break;
301 case LTTNG_UST_LOGLEVEL_RANGE:
302 loglevel_type_string = config_loglevel_type_range;
303 break;
304 case LTTNG_UST_LOGLEVEL_SINGLE:
305 loglevel_type_string = config_loglevel_type_single;
306 break;
307 default:
308 loglevel_type_string = NULL;
309 }
310
311 return loglevel_type_string;
312}
313
314static
315int save_kernel_event(struct config_writer *writer,
316 struct ltt_kernel_event *event)
317{
318 int ret;
319 const char *instrumentation_type;
320
321 ret = config_writer_open_element(writer, config_element_event);
322 if (ret) {
323 ret = LTTNG_ERR_SAVE_IO_FAIL;
324 goto end;
325 }
326
327 if (event->event->name[0]) {
328 ret = config_writer_write_element_string(writer,
329 config_element_name, event->event->name);
330 if (ret) {
331 ret = LTTNG_ERR_SAVE_IO_FAIL;
332 goto end;
333 }
334 }
335
336 ret = config_writer_write_element_bool(writer, config_element_enabled,
337 event->enabled);
338 if (ret) {
339 ret = LTTNG_ERR_SAVE_IO_FAIL;
340 goto end;
341 }
342
343 instrumentation_type = get_kernel_instrumentation_string(
344 event->event->instrumentation);
345 if (!instrumentation_type) {
346 ret = LTTNG_ERR_INVALID;
347 goto end;
348 }
349
350 ret = config_writer_write_element_string(writer, config_element_type,
351 instrumentation_type);
352 if (ret) {
353 ret = LTTNG_ERR_SAVE_IO_FAIL;
354 goto end;
355 }
356
357 if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
358 event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
359 event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
360
361 ret = config_writer_open_element(writer,
362 config_element_attributes);
363 if (ret) {
364 ret = LTTNG_ERR_SAVE_IO_FAIL;
365 goto end;
366 }
367
368 switch (event->event->instrumentation) {
369 case LTTNG_KERNEL_FUNCTION:
370 ret = config_writer_open_element(writer,
371 config_element_function_attributes);
372 if (ret) {
373 ret = LTTNG_ERR_SAVE_IO_FAIL;
374 goto end;
375 }
376
377 ret = config_writer_write_element_string(writer,
378 config_element_name,
379 event->event->u.ftrace.symbol_name);
380 if (ret) {
381 ret = LTTNG_ERR_SAVE_IO_FAIL;
382 goto end;
383 }
384
385 /* /function attributes */
386 ret = config_writer_close_element(writer);
387 if (ret) {
388 ret = LTTNG_ERR_SAVE_IO_FAIL;
389 goto end;
390 }
391 break;
392 case LTTNG_KERNEL_KPROBE:
393 case LTTNG_KERNEL_KRETPROBE:
394 {
395 const char *symbol_name;
396 uint64_t addr;
397 uint64_t offset;
398
399 if (event->event->instrumentation ==
400 LTTNG_KERNEL_KPROBE) {
401 /*
402 * Comments in lttng-kernel.h mention that
403 * either addr or symbol_name are set, not both.
404 */
405 addr = event->event->u.kprobe.addr;
406 offset = event->event->u.kprobe.offset;
407 symbol_name = addr ? NULL :
408 event->event->u.kprobe.symbol_name;
409 } else {
410 symbol_name =
411 event->event->u.kretprobe.symbol_name;
412 addr = event->event->u.kretprobe.addr;
413 offset = event->event->u.kretprobe.offset;
414 }
415
416 ret = config_writer_open_element(writer,
417 config_element_probe_attributes);
418 if (ret) {
419 ret = LTTNG_ERR_SAVE_IO_FAIL;
420 goto end;
421 }
422
423 if (symbol_name) {
424 ret = config_writer_write_element_string(writer,
425 config_element_symbol_name,
426 symbol_name);
427 if (ret) {
428 ret = LTTNG_ERR_SAVE_IO_FAIL;
429 goto end;
430 }
431 }
432
433 if (addr) {
434 ret = config_writer_write_element_unsigned_int(
435 writer, config_element_address, addr);
436 if (ret) {
437 ret = LTTNG_ERR_SAVE_IO_FAIL;
438 goto end;
439 }
440 }
441
442 if (offset) {
443 ret = config_writer_write_element_unsigned_int(
444 writer, config_element_offset, offset);
445 if (ret) {
446 ret = LTTNG_ERR_SAVE_IO_FAIL;
447 goto end;
448 }
449 }
450
451 ret = config_writer_close_element(writer);
452 if (ret) {
453 ret = LTTNG_ERR_SAVE_IO_FAIL;
454 goto end;
455 }
456 break;
457 }
458 default:
459 ERR("Unsupported kernel instrumentation type.");
460 ret = LTTNG_ERR_INVALID;
461 goto end;
462 }
463
464 /* /attributes */
465 ret = config_writer_close_element(writer);
466 if (ret) {
467 ret = LTTNG_ERR_SAVE_IO_FAIL;
468 goto end;
469 }
470 }
471
472 /* /event */
473 ret = config_writer_close_element(writer);
474 if (ret) {
475 ret = LTTNG_ERR_SAVE_IO_FAIL;
476 goto end;
477 }
478end:
479 return ret;
480}
481
482static
483int save_kernel_events(struct config_writer *writer,
484 struct ltt_kernel_event_list *event_list)
485{
486 int ret;
487 struct ltt_kernel_event *event;
488
489 ret = config_writer_open_element(writer, config_element_events);
490 if (ret) {
491 ret = LTTNG_ERR_SAVE_IO_FAIL;
492 goto end;
493 }
494
495 cds_list_for_each_entry(event, &event_list->head, list) {
496 ret = save_kernel_event(writer, event);
497 if (ret) {
498 goto end;
499 }
500 }
501
502 /* /events */
503 ret = config_writer_close_element(writer);
504 if (ret) {
505 ret = LTTNG_ERR_SAVE_IO_FAIL;
506 goto end;
507 }
508end:
509 return ret;
510}
511
512static
513int save_ust_event(struct config_writer *writer,
514 struct ltt_ust_event *event)
515{
516 int ret;
517 const char *loglevel_type_string;
518
519 ret = config_writer_open_element(writer, config_element_event);
520 if (ret) {
521 ret = LTTNG_ERR_SAVE_IO_FAIL;
522 goto end;
523 }
524
525 if (event->attr.name[0]) {
526 ret = config_writer_write_element_string(writer,
527 config_element_name, event->attr.name);
528 if (ret) {
529 ret = LTTNG_ERR_SAVE_IO_FAIL;
530 goto end;
531 }
532 }
533
534 ret = config_writer_write_element_bool(writer, config_element_enabled,
535 event->enabled);
536 if (ret) {
537 ret = LTTNG_ERR_SAVE_IO_FAIL;
538 goto end;
539 }
540
541 if (event->attr.instrumentation != LTTNG_UST_TRACEPOINT) {
542 ERR("Unsupported UST instrumentation type.");
543 ret = LTTNG_ERR_INVALID;
544 goto end;
545 }
546 ret = config_writer_write_element_string(writer, config_element_type,
547 config_event_type_tracepoint);
548 if (ret) {
549 ret = LTTNG_ERR_SAVE_IO_FAIL;
550 goto end;
551 }
552
553 loglevel_type_string = get_loglevel_type_string(
554 event->attr.loglevel_type);
555 if (!loglevel_type_string) {
556 ERR("Unsupported UST loglevel type.");
557 ret = LTTNG_ERR_INVALID;
558 goto end;
559 }
560
561 ret = config_writer_write_element_string(writer,
562 config_element_loglevel_type, loglevel_type_string);
563 if (ret) {
564 ret = LTTNG_ERR_SAVE_IO_FAIL;
565 goto end;
566 }
567
568 ret = config_writer_write_element_signed_int(writer,
569 config_element_loglevel, event->attr.loglevel);
570 if (ret) {
571 ret = LTTNG_ERR_SAVE_IO_FAIL;
572 goto end;
573 }
574
575 if (event->filter_expression) {
576 ret = config_writer_write_element_string(writer,
577 config_element_filter, event->filter_expression);
578 if (ret) {
579 ret = LTTNG_ERR_SAVE_IO_FAIL;
580 goto end;
581 }
582 }
583
584 if (event->exclusion && event->exclusion->count) {
585 uint32_t i;
586
587 ret = config_writer_open_element(writer,
588 config_element_exclusions);
589 if (ret) {
590 ret = LTTNG_ERR_SAVE_IO_FAIL;
591 goto end;
592 }
593
594 for (i = 0; i < event->exclusion->count; i++) {
595 ret = config_writer_write_element_string(writer,
596 config_element_exclusion,
597 &event->exclusion->names[0][i]);
598 if (ret) {
599 ret = LTTNG_ERR_SAVE_IO_FAIL;
600 goto end;
601 }
602 }
603
604 /* /exclusions */
605 ret = config_writer_close_element(writer);
606 if (ret) {
607 ret = LTTNG_ERR_SAVE_IO_FAIL;
608 goto end;
609 }
610 }
611
612 /* /event */
613 ret = config_writer_close_element(writer);
614 if (ret) {
615 ret = LTTNG_ERR_SAVE_IO_FAIL;
616 goto end;
617 }
618end:
619 return ret;
620}
621
622static
623int save_ust_events(struct config_writer *writer,
624 struct lttng_ht *events)
625{
626 int ret;
627 struct ltt_ust_event *event;
628 struct lttng_ht_node_str *node;
629 struct lttng_ht_iter iter;
630
631 ret = config_writer_open_element(writer, config_element_events);
632 if (ret) {
633 ret = LTTNG_ERR_SAVE_IO_FAIL;
634 goto end;
635 }
636
637 rcu_read_lock();
638 cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) {
639 event = caa_container_of(node, struct ltt_ust_event, node);
640
641 ret = save_ust_event(writer, event);
642 if (ret) {
643 rcu_read_unlock();
644 goto end;
645 }
646 }
647 rcu_read_unlock();
648
649 /* /events */
650 ret = config_writer_close_element(writer);
651 if (ret) {
652 ret = LTTNG_ERR_SAVE_IO_FAIL;
653 goto end;
654 }
655end:
656 return ret;
657}
658
659static
660int save_kernel_context(struct config_writer *writer,
661 struct lttng_kernel_context *ctx)
662{
663 int ret = 0;
664
665 if (!ctx) {
666 goto end;
667 }
668
669 ret = config_writer_open_element(writer, config_element_contexts);
670 if (ret) {
671 ret = LTTNG_ERR_SAVE_IO_FAIL;
672 goto end;
673 }
674
675 ret = config_writer_open_element(writer, config_element_context);
676 if (ret) {
677 ret = LTTNG_ERR_SAVE_IO_FAIL;
678 goto end;
679 }
680
cba45eda 681 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
fb198a11
JG
682 ret = config_writer_open_element(writer, config_element_perf);
683 if (ret) {
684 ret = LTTNG_ERR_SAVE_IO_FAIL;
685 goto end;
686 }
687
688 ret = config_writer_write_element_unsigned_int(writer,
689 config_element_type, ctx->u.perf_counter.type);
690 if (ret) {
691 ret = LTTNG_ERR_SAVE_IO_FAIL;
692 goto end;
693 }
694
695 ret = config_writer_write_element_unsigned_int(writer,
696 config_element_config, ctx->u.perf_counter.config);
697 if (ret) {
698 ret = LTTNG_ERR_SAVE_IO_FAIL;
699 goto end;
700 }
701
702 ret = config_writer_write_element_string(writer,
703 config_element_name, ctx->u.perf_counter.name);
704 if (ret) {
705 ret = LTTNG_ERR_SAVE_IO_FAIL;
706 goto end;
707 }
708
709 /* /perf */
710 ret = config_writer_close_element(writer);
711 if (ret) {
712 ret = LTTNG_ERR_SAVE_IO_FAIL;
713 goto end;
714 }
715 } else {
716 const char *context_type_string =
717 get_kernel_context_type_string(ctx->ctx);
718
719 if (!context_type_string) {
720 ERR("Unsupported kernel context type.");
721 ret = LTTNG_ERR_INVALID;
722 goto end;
723 }
724
725 ret = config_writer_write_element_string(writer,
726 config_element_type, context_type_string);
727 if (ret) {
728 ret = LTTNG_ERR_SAVE_IO_FAIL;
729 goto end;
730 }
731 }
732
733 /* /context */
734 ret = config_writer_close_element(writer);
735 if (ret) {
736 ret = LTTNG_ERR_SAVE_IO_FAIL;
737 goto end;
738 }
739
740 /* /contexts */
741 ret = config_writer_close_element(writer);
742 if (ret) {
743 ret = LTTNG_ERR_SAVE_IO_FAIL;
744 goto end;
745 }
746end:
747 return ret;
748}
749
750static
751int save_ust_context(struct config_writer *writer,
752 struct cds_list_head *ctx_list)
753{
754 int ret;
755 struct ltt_ust_context *ctx;
756
757 assert(writer);
758 assert(ctx_list);
759
760 ret = config_writer_open_element(writer, config_element_contexts);
761 if (ret) {
762 ret = LTTNG_ERR_SAVE_IO_FAIL;
763 goto end;
764 }
765
766 cds_list_for_each_entry(ctx, ctx_list, list) {
767 const char *context_type_string;
768
769 context_type_string = get_ust_context_type_string(ctx->ctx.ctx);
770 if (!context_type_string) {
771 ERR("Unsupported UST context type.")
772 ret = LTTNG_ERR_INVALID;
773 goto end;
774 }
775
776 ret = config_writer_open_element(writer,
777 config_element_context);
778 if (ret) {
779 ret = LTTNG_ERR_SAVE_IO_FAIL;
780 goto end;
781 }
782
783 ret = config_writer_write_element_string(writer,
784 config_element_type, context_type_string);
785 if (ret) {
786 ret = LTTNG_ERR_SAVE_IO_FAIL;
787 goto end;
788 }
789
790 /* /context */
791 ret = config_writer_close_element(writer);
792 if (ret) {
793 ret = LTTNG_ERR_SAVE_IO_FAIL;
794 goto end;
795 }
796 }
797
798 /* /contexts */
799 ret = config_writer_close_element(writer);
800 if (ret) {
801 ret = LTTNG_ERR_SAVE_IO_FAIL;
802 goto end;
803 }
804end:
805 return ret;
806}
807
808static
809int save_kernel_channel(struct config_writer *writer,
810 struct ltt_kernel_channel *kchan)
811{
812 int ret;
813
814 assert(writer);
815 assert(kchan);
816
817 ret = config_writer_open_element(writer, config_element_channel);
818 if (ret) {
819 ret = LTTNG_ERR_SAVE_IO_FAIL;
820 goto end;
821 }
822
823 ret = config_writer_write_element_string(writer, config_element_name,
824 kchan->channel->name);
825 if (ret) {
826 ret = LTTNG_ERR_SAVE_IO_FAIL;
827 goto end;
828 }
829
830 ret = config_writer_write_element_bool(writer, config_element_enabled,
831 kchan->channel->enabled);
832 if (ret) {
833 ret = LTTNG_ERR_SAVE_IO_FAIL;
834 goto end;
835 }
836
837 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
838 if (ret) {
839 goto end;
840 }
841
842 ret = save_kernel_events(writer, &kchan->events_list);
843 if (ret) {
844 goto end;
845 }
846
847 ret = save_kernel_context(writer, kchan->ctx);
848 if (ret) {
849 goto end;
850 }
851
852 /* /channel */
853 ret = config_writer_close_element(writer);
854 if (ret) {
855 ret = LTTNG_ERR_SAVE_IO_FAIL;
856 goto end;
857 }
858end:
859 return ret;
860}
861
862static
863int save_ust_channel(struct config_writer *writer,
864 struct ltt_ust_channel *ust_chan,
865 struct ltt_ust_session *session)
866{
867 int ret;
868
869 assert(writer);
870 assert(ust_chan);
871 assert(session);
872
873 ret = config_writer_open_element(writer, config_element_channel);
874 if (ret) {
875 ret = LTTNG_ERR_SAVE_IO_FAIL;
876 goto end;
877 }
878
879 ret = config_writer_write_element_string(writer, config_element_name,
880 ust_chan->name);
881 if (ret) {
882 ret = LTTNG_ERR_SAVE_IO_FAIL;
883 goto end;
884 }
885
886 ret = config_writer_write_element_bool(writer, config_element_enabled,
887 ust_chan->enabled);
888 if (ret) {
889 ret = LTTNG_ERR_SAVE_IO_FAIL;
890 goto end;
891 }
892
893 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
894 if (ret) {
895 goto end;
896 }
897
898 ret = config_writer_write_element_unsigned_int(writer,
899 config_element_tracefile_size, ust_chan->tracefile_size);
900 if (ret) {
901 ret = LTTNG_ERR_SAVE_IO_FAIL;
902 goto end;
903 }
904
905 ret = config_writer_write_element_unsigned_int(writer,
906 config_element_tracefile_count, ust_chan->tracefile_count);
907 if (ret) {
908 ret = LTTNG_ERR_SAVE_IO_FAIL;
909 goto end;
910 }
911
912 ret = config_writer_write_element_unsigned_int(writer,
913 config_element_live_timer_interval,
914 session->live_timer_interval);
915 if (ret) {
916 ret = LTTNG_ERR_SAVE_IO_FAIL;
917 goto end;
918 }
919
920 ret = save_ust_events(writer, ust_chan->events);
921 if (ret) {
922 ret = LTTNG_ERR_SAVE_IO_FAIL;
923 goto end;
924 }
925
926 ret = save_ust_context(writer, &ust_chan->ctx_list);
927 if (ret) {
928 goto end;
929 }
930
931 /* /channel */
932 ret = config_writer_close_element(writer);
933 if (ret) {
934 ret = LTTNG_ERR_SAVE_IO_FAIL;
935 goto end;
936 }
937end:
938 return ret;
939}
940
941static
942int save_kernel_session(struct config_writer *writer,
943 struct ltt_session *session)
944{
945 int ret;
946 struct ltt_kernel_channel *kchan;
947
948 assert(writer);
949 assert(session);
950
951 ret = config_writer_write_element_string(writer, config_element_type,
952 config_domain_type_kernel);
953 if (ret) {
954 ret = LTTNG_ERR_SAVE_IO_FAIL;
955 goto end;
956 }
957
958 ret = config_writer_write_element_string(writer,
959 config_element_buffer_type, config_buffer_type_global);
960 if (ret) {
961 ret = LTTNG_ERR_SAVE_IO_FAIL;
962 goto end;
963 }
964
965 ret = config_writer_open_element(writer,
966 config_element_channels);
967 if (ret) {
968 ret = LTTNG_ERR_SAVE_IO_FAIL;
969 goto end;
970 }
971
972 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
973 list) {
974 ret = save_kernel_channel(writer, kchan);
975 if (ret) {
976 goto end;
977 }
978 }
979
980 /* /channels */
981 ret = config_writer_close_element(writer);
982 if (ret) {
983 ret = LTTNG_ERR_SAVE_IO_FAIL;
984 goto end;
985 }
986end:
987 return ret;
988}
989
990static
991int save_ust_session(struct config_writer *writer,
992 struct ltt_session *session, int save_jul)
993{
994 int ret;
995 struct ltt_ust_channel *ust_chan;
996 const char *buffer_type_string;
997 struct lttng_ht_node_str *node;
998 struct lttng_ht_iter iter;
999
1000 assert(writer);
1001 assert(session);
1002
1003 ret = config_writer_write_element_string(writer, config_element_type,
1004 save_jul ? config_domain_type_jul : config_domain_type_ust);
1005 if (ret) {
1006 ret = LTTNG_ERR_SAVE_IO_FAIL;
1007 goto end;
1008 }
1009
1010 buffer_type_string = get_buffer_type_string(
1011 session->ust_session->buffer_type);
1012 if (!buffer_type_string) {
1013 ERR("Unsupported buffer type.");
1014 ret = LTTNG_ERR_INVALID;
1015 goto end;
1016 }
1017
1018 ret = config_writer_write_element_string(writer,
1019 config_element_buffer_type, buffer_type_string);
1020 if (ret) {
1021 ret = LTTNG_ERR_SAVE_IO_FAIL;
1022 goto end;
1023 }
1024
1025 ret = config_writer_open_element(writer, config_element_channels);
1026 if (ret) {
1027 ret = LTTNG_ERR_SAVE_IO_FAIL;
1028 goto end;
1029 }
1030
1031 rcu_read_lock();
1032 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1033 &iter.iter, node, node) {
1034 int jul_channel;
1035
1036 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
1037 jul_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name);
1038 if (!(save_jul ^ jul_channel)) {
1039 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1040 if (ret) {
1041 rcu_read_unlock();
1042 goto end;
1043 }
1044 }
1045 }
1046 rcu_read_unlock();
1047
1048 /* /channels */
1049 ret = config_writer_close_element(writer);
1050 if (ret) {
1051 ret = LTTNG_ERR_SAVE_IO_FAIL;
1052 goto end;
1053 }
1054end:
1055 return ret;
1056}
1057
1058static
1059int save_domains(struct config_writer *writer, struct ltt_session *session)
1060{
1061 int ret = 0;
1062
1063 assert(writer);
1064 assert(session);
1065
1066 if (!session->kernel_session && !session->ust_session) {
1067 goto end;
1068 }
1069
1070 ret = config_writer_open_element(writer, config_element_domains);
1071 if (ret) {
1072 ret = LTTNG_ERR_SAVE_IO_FAIL;
1073 goto end;
1074 }
1075
1076
1077 if (session->kernel_session) {
1078 ret = config_writer_open_element(writer,
1079 config_element_domain);
1080 if (ret) {
1081 ret = LTTNG_ERR_SAVE_IO_FAIL;
1082 goto end;
1083 }
1084
1085 ret = save_kernel_session(writer, session);
1086 if (ret) {
1087 goto end;
1088 }
1089
1090 /* /domain */
1091 ret = config_writer_close_element(writer);
1092 if (ret) {
1093 ret = LTTNG_ERR_SAVE_IO_FAIL;
1094 goto end;
1095 }
1096 }
1097
1098 if (session->ust_session) {
1099 ret = config_writer_open_element(writer,
1100 config_element_domain);
1101 if (ret) {
1102 ret = LTTNG_ERR_SAVE_IO_FAIL;
1103 goto end;
1104 }
1105
1106 ret = save_ust_session(writer, session, 0);
1107 if (ret) {
1108 goto end;
1109 }
1110
1111 /* /domain */
1112 ret = config_writer_close_element(writer);
1113 if (ret) {
1114 ret = LTTNG_ERR_SAVE_IO_FAIL;
1115 goto end;
1116 }
1117 }
1118
1119 if (session->ust_session &&
1120 session->ust_session->domain_jul.being_used) {
1121 ret = config_writer_open_element(writer,
1122 config_element_domain);
1123 if (ret) {
1124 ret = LTTNG_ERR_SAVE_IO_FAIL;
1125 goto end;
1126 }
1127
1128 ret = save_ust_session(writer, session, 1);
1129 if (ret) {
1130 goto end;
1131 }
1132
1133 /* /domain */
1134 ret = config_writer_close_element(writer);
1135 if (ret) {
1136 ret = LTTNG_ERR_SAVE_IO_FAIL;
1137 goto end;
1138 }
1139 }
1140
1141 /* /domains */
1142 ret = config_writer_close_element(writer);
1143 if (ret) {
1144 ret = LTTNG_ERR_SAVE_IO_FAIL;
1145 goto end;
1146 }
1147end:
1148 return ret;
1149}
1150
1151static
1152int save_consumer_output(struct config_writer *writer,
1153 struct consumer_output *output)
1154{
1155 int ret;
1156
1157 assert(writer);
1158 assert(output);
1159
1160 ret = config_writer_open_element(writer, config_element_consumer_output);
1161 if (ret) {
1162 ret = LTTNG_ERR_SAVE_IO_FAIL;
1163 goto end;
1164 }
1165
1166 ret = config_writer_write_element_bool(writer, config_element_enabled,
1167 output->enabled);
1168 if (ret) {
1169 ret = LTTNG_ERR_SAVE_IO_FAIL;
1170 goto end;
1171 }
1172
1173 ret = config_writer_open_element(writer, config_element_destination);
1174 if (ret) {
1175 ret = LTTNG_ERR_SAVE_IO_FAIL;
1176 goto end;
1177 }
1178
1179 switch (output->type) {
1180 case CONSUMER_DST_LOCAL:
1181 ret = config_writer_write_element_string(writer,
1182 config_element_path, output->dst.trace_path);
1183 if (ret) {
1184 ret = LTTNG_ERR_SAVE_IO_FAIL;
1185 goto end;
1186 }
1187 break;
1188 case CONSUMER_DST_NET:
1189 {
1190 char *uri;
1191
1192 uri = zmalloc(PATH_MAX);
1193 if (!uri) {
1194 ret = LTTNG_ERR_NOMEM;
1195 goto end;
1196 }
1197
1198 ret = config_writer_open_element(writer, config_element_net_output);
1199 if (ret) {
1200 ret = LTTNG_ERR_SAVE_IO_FAIL;
1201 goto end_net_output;
1202 }
1203
1204 if (output->dst.net.control_isset &&
1205 output->dst.net.data_isset) {
1206 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1207 if (ret < 0) {
1208 ret = LTTNG_ERR_INVALID;
1209 goto end_net_output;
1210 }
1211
1212 ret = config_writer_write_element_string(writer,
1213 config_element_control_uri, uri);
1214 if (ret) {
1215 ret = LTTNG_ERR_SAVE_IO_FAIL;
1216 goto end_net_output;
1217 }
1218
1219 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1220 if (ret < 0) {
1221 ret = LTTNG_ERR_INVALID;
1222 goto end_net_output;
1223 }
1224
1225 ret = config_writer_write_element_string(writer,
1226 config_element_data_uri, uri);
1227 if (ret) {
1228 ret = LTTNG_ERR_SAVE_IO_FAIL;
1229 goto end_net_output;
1230 }
1231
1232end_net_output:
1233 free(uri);
1234 if (ret) {
1235 goto end;
1236 }
1237 } else {
1238 ret = !output->dst.net.control_isset ?
1239 LTTNG_ERR_URL_CTRL_MISS :
1240 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1241 free(uri);
fb198a11
JG
1242 goto end;
1243 }
1244
1245 ret = config_writer_close_element(writer);
1246 if (ret) {
1247 ret = LTTNG_ERR_SAVE_IO_FAIL;
1248 goto end;
1249 }
1250 break;
1251 }
1252 default:
1253 ERR("Unsupported consumer output type.");
1254 ret = LTTNG_ERR_INVALID;
1255 goto end;
1256 }
1257
1258 /* /destination */
1259 ret = config_writer_close_element(writer);
1260 if (ret) {
1261 ret = LTTNG_ERR_SAVE_IO_FAIL;
1262 goto end;
1263 }
1264
1265 /* /consumer_output */
1266 ret = config_writer_close_element(writer);
1267 if (ret) {
1268 ret = LTTNG_ERR_SAVE_IO_FAIL;
1269 goto end;
1270 }
1271end:
1272 return ret;
1273}
1274
1275static
1276int save_snapshot_outputs(struct config_writer *writer,
1277 struct snapshot *snapshot)
1278{
1279 int ret;
1280 struct lttng_ht_iter iter;
1281 struct snapshot_output *output;
1282
1283 assert(writer);
1284 assert(snapshot);
1285
1286 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1287 if (ret) {
1288 ret = LTTNG_ERR_SAVE_IO_FAIL;
1289 goto end;
1290 }
1291
1292 rcu_read_lock();
1293 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1294 node.node) {
1295 ret = config_writer_open_element(writer,
1296 config_element_output);
1297 if (ret) {
1298 ret = LTTNG_ERR_SAVE_IO_FAIL;
1299 goto end_unlock;
1300 }
1301
1302 ret = config_writer_write_element_string(writer,
1303 config_element_name, output->name);
1304 if (ret) {
1305 ret = LTTNG_ERR_SAVE_IO_FAIL;
1306 goto end_unlock;
1307 }
1308
1309 ret = config_writer_write_element_unsigned_int(writer,
1310 config_element_max_size, output->max_size);
1311 if (ret) {
1312 ret = LTTNG_ERR_SAVE_IO_FAIL;
1313 goto end_unlock;
1314 }
1315
1316 ret = save_consumer_output(writer, output->consumer);
1317 if (ret) {
1318 goto end_unlock;
1319 }
1320
1321 /* /output */
1322 ret = config_writer_close_element(writer);
1323 if (ret) {
1324 ret = LTTNG_ERR_SAVE_IO_FAIL;
1325 goto end_unlock;
1326 }
1327 }
1328 rcu_read_unlock();
1329
1330 /* /snapshot_outputs */
1331 ret = config_writer_close_element(writer);
1332 if (ret) {
1333 ret = LTTNG_ERR_SAVE_IO_FAIL;
1334 goto end;
1335 }
1336
1337end:
1338 return ret;
1339end_unlock:
1340 rcu_read_unlock();
1341 return ret;
1342}
1343
1344static
1345int save_session_output(struct config_writer *writer,
1346 struct ltt_session *session)
1347{
1348 int ret;
1349
1350 assert(writer);
1351 assert(session);
1352
1353 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1354 (!session->snapshot_mode && !session->consumer)) {
1355 /* Session is in no output mode */
1356 ret = 0;
1357 goto end;
1358 }
1359
1360 ret = config_writer_open_element(writer, config_element_output);
1361 if (ret) {
1362 ret = LTTNG_ERR_SAVE_IO_FAIL;
1363 goto end;
1364 }
1365
1366 if (session->snapshot_mode) {
1367 ret = save_snapshot_outputs(writer, &session->snapshot);
1368 if (ret) {
1369 goto end;
1370 }
1371 } else {
1372 if (session->consumer) {
1373 ret = save_consumer_output(writer, session->consumer);
1374 if (ret) {
1375 goto end;
1376 }
1377 }
1378 }
1379
1380 /* /output */
1381 ret = config_writer_close_element(writer);
1382 if (ret) {
1383 ret = LTTNG_ERR_SAVE_IO_FAIL;
1384 goto end;
1385 }
1386end:
1387 return ret;
1388}
1389
1390/*
1391 * Save the given session.
1392 *
1393 * Return 0 on success else a LTTNG_ERR* code.
1394 */
1395static
1396int save_session(struct ltt_session *session,
1397 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1398{
1399 int ret, fd;
db471218 1400 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
1401 char config_file_path[PATH_MAX];
1402 size_t len;
1403 struct config_writer *writer = NULL;
1404 size_t session_name_len;
1405 const char *provided_path;
1406
1407 assert(session);
1408 assert(attr);
1409 assert(creds);
1410
1411 session_name_len = strlen(session->name);
95a29ab8 1412 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
1413
1414 if (!session_access_ok(session,
1415 LTTNG_SOCK_GET_UID_CRED(creds),
1416 LTTNG_SOCK_GET_GID_CRED(creds))) {
1417 ret = LTTNG_ERR_EPERM;
1418 goto end;
1419 }
1420
1421 provided_path = lttng_save_session_attr_get_output_url(attr);
1422 if (provided_path) {
95a29ab8 1423 DBG3("Save session in provided path %s", provided_path);
fb198a11 1424 len = strlen(provided_path);
d2992717 1425 if (len >= sizeof(config_file_path)) {
fb198a11
JG
1426 ret = LTTNG_ERR_SET_URL;
1427 goto end;
1428 }
1429 strncpy(config_file_path, provided_path, len);
1430 } else {
7e078ad1 1431 ssize_t ret_len;
fb198a11
JG
1432 char *home_dir = utils_get_user_home_dir(
1433 LTTNG_SOCK_GET_UID_CRED(creds));
1434 if (!home_dir) {
1435 ret = LTTNG_ERR_SET_URL;
1436 goto end;
1437 }
1438
d2992717 1439 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
1440 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1441 free(home_dir);
7e078ad1 1442 if (ret_len < 0) {
fb198a11
JG
1443 PERROR("snprintf save session");
1444 ret = LTTNG_ERR_SET_URL;
1445 goto end;
1446 }
7e078ad1 1447 len = ret_len;
fb198a11
JG
1448 }
1449
1450 /*
d2992717
DG
1451 * Check the path fits in the config file path dst including the '/'
1452 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 1453 */
d2992717
DG
1454 if ((len + session_name_len + 2 +
1455 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1456 > sizeof(config_file_path)) {
fb198a11
JG
1457 ret = LTTNG_ERR_SET_URL;
1458 goto end;
1459 }
1460
1461 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1462 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1463 if (ret) {
1464 ret = LTTNG_ERR_SET_URL;
1465 goto end;
1466 }
1467
d2992717
DG
1468 /*
1469 * At this point, we know that everything fits in the buffer. Validation
1470 * was done just above.
1471 */
fb198a11
JG
1472 config_file_path[len++] = '/';
1473 strncpy(config_file_path + len, session->name, session_name_len);
1474 len += session_name_len;
1475 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
1476 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1477 config_file_path[len] = '\0';
fb198a11
JG
1478
1479 if (!access(config_file_path, F_OK) && !attr->overwrite) {
f9b57ab2
DG
1480 /* File exists, notify the user since the overwrite flag is off. */
1481 ret = LTTNG_ERR_SAVE_FILE_EXIST;
fb198a11
JG
1482 goto end;
1483 }
1484
1485 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1486 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1487 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1488 if (fd < 0) {
1489 PERROR("Could not create configuration file");
1490 ret = LTTNG_ERR_SAVE_IO_FAIL;
1491 goto end;
1492 }
db471218 1493 file_opened = 1;
fb198a11
JG
1494
1495 writer = config_writer_create(fd);
1496 if (!writer) {
1497 ret = LTTNG_ERR_NOMEM;
1498 goto end;
1499 }
1500
1501 ret = config_writer_open_element(writer, config_element_sessions);
1502 if (ret) {
1503 ret = LTTNG_ERR_SAVE_IO_FAIL;
1504 goto end;
1505 }
1506
1507 ret = config_writer_open_element(writer, config_element_session);
1508 if (ret) {
1509 ret = LTTNG_ERR_SAVE_IO_FAIL;
1510 goto end;
1511 }
1512
1513 ret = config_writer_write_element_string(writer, config_element_name,
1514 session->name);
1515 if (ret) {
1516 ret = LTTNG_ERR_SAVE_IO_FAIL;
1517 goto end;
1518 }
1519
1520 ret = save_domains(writer, session);
1521 if (ret) {
1522 goto end;
1523 }
1524
1525 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 1526 session->active);
fb198a11
JG
1527 if (ret) {
1528 ret = LTTNG_ERR_SAVE_IO_FAIL;
1529 goto end;
1530 }
1531
1532 if (session->snapshot_mode || session->live_timer) {
1533 ret = config_writer_open_element(writer, config_element_attributes);
1534 if (ret) {
1535 ret = LTTNG_ERR_SAVE_IO_FAIL;
1536 goto end;
1537 }
1538
1539 if (session->snapshot_mode) {
1540 ret = config_writer_write_element_bool(writer,
1541 config_element_snapshot_mode, 1);
1542 if (ret) {
1543 ret = LTTNG_ERR_SAVE_IO_FAIL;
1544 goto end;
1545 }
1546 } else {
1547 ret = config_writer_write_element_signed_int(writer,
1548 config_element_live_timer_interval, session->live_timer);
1549 if (ret) {
1550 ret = LTTNG_ERR_SAVE_IO_FAIL;
1551 goto end;
1552 }
1553 }
1554
1555 /* /attributes */
1556 ret = config_writer_close_element(writer);
1557 if (ret) {
1558 ret = LTTNG_ERR_SAVE_IO_FAIL;
1559 goto end;
1560 }
1561 }
1562
1563 ret = save_session_output(writer, session);
1564 if (ret) {
1565 goto end;
1566 }
1567
1568 /* /session */
1569 ret = config_writer_close_element(writer);
1570 if (ret) {
1571 ret = LTTNG_ERR_SAVE_IO_FAIL;
1572 goto end;
1573 }
1574
1575 /* /sessions */
1576 ret = config_writer_close_element(writer);
1577 if (ret) {
1578 ret = LTTNG_ERR_SAVE_IO_FAIL;
1579 goto end;
1580 }
1581end:
1582 if (writer && config_writer_destroy(writer)) {
1583 /* Preserve the original error code */
1584 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1585 }
1586 if (ret) {
1587 /* Delete file in case of error */
db471218 1588 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
1589 PERROR("Unlinking XML session configuration.");
1590 }
1591 }
1592
1593 return ret;
1594}
1595
1596int cmd_save_sessions(struct lttng_save_session_attr *attr,
1597 lttng_sock_cred *creds)
1598{
1599 int ret;
1600 const char *session_name;
1601 struct ltt_session *session;
1602
1603 session_lock_list();
1604
1605 session_name = lttng_save_session_attr_get_session_name(attr);
1606 if (session_name) {
1607 session = session_find_by_name(session_name);
1608 if (!session) {
1609 ret = LTTNG_ERR_SESS_NOT_FOUND;
1610 goto end;
1611 }
1612
1613 session_lock(session);
1614 ret = save_session(session, attr, creds);
1615 session_unlock(session);
1616 if (ret) {
1617 goto end;
1618 }
1619 } else {
1620 struct ltt_session_list *list = session_get_list();
1621
1622 cds_list_for_each_entry(session, &list->head, list) {
1623 session_lock(session);
1624 ret = save_session(session, attr, creds);
1625 session_unlock(session);
1626
1627 /* Don't abort if we don't have the required permissions. */
1628 if (ret && ret != LTTNG_ERR_EPERM) {
1629 goto end;
1630 }
1631 }
1632 }
1633 ret = LTTNG_OK;
1634
1635end:
1636 session_unlock_list();
1637 return ret;
1638}
This page took 0.085942 seconds and 5 git commands to generate.