Fix: Add vpid, vppid and vtid info in add-context help
[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
673 ret = config_writer_open_element(writer, config_element_contexts);
674 if (ret) {
675 ret = LTTNG_ERR_SAVE_IO_FAIL;
676 goto end;
677 }
678
679 ret = config_writer_open_element(writer, config_element_context);
680 if (ret) {
681 ret = LTTNG_ERR_SAVE_IO_FAIL;
682 goto end;
683 }
684
cba45eda 685 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
fb198a11
JG
686 ret = config_writer_open_element(writer, config_element_perf);
687 if (ret) {
688 ret = LTTNG_ERR_SAVE_IO_FAIL;
689 goto end;
690 }
691
692 ret = config_writer_write_element_unsigned_int(writer,
693 config_element_type, ctx->u.perf_counter.type);
694 if (ret) {
695 ret = LTTNG_ERR_SAVE_IO_FAIL;
696 goto end;
697 }
698
699 ret = config_writer_write_element_unsigned_int(writer,
700 config_element_config, ctx->u.perf_counter.config);
701 if (ret) {
702 ret = LTTNG_ERR_SAVE_IO_FAIL;
703 goto end;
704 }
705
706 ret = config_writer_write_element_string(writer,
707 config_element_name, ctx->u.perf_counter.name);
708 if (ret) {
709 ret = LTTNG_ERR_SAVE_IO_FAIL;
710 goto end;
711 }
712
713 /* /perf */
714 ret = config_writer_close_element(writer);
715 if (ret) {
716 ret = LTTNG_ERR_SAVE_IO_FAIL;
717 goto end;
718 }
719 } else {
720 const char *context_type_string =
721 get_kernel_context_type_string(ctx->ctx);
722
723 if (!context_type_string) {
724 ERR("Unsupported kernel context type.");
725 ret = LTTNG_ERR_INVALID;
726 goto end;
727 }
728
729 ret = config_writer_write_element_string(writer,
730 config_element_type, context_type_string);
731 if (ret) {
732 ret = LTTNG_ERR_SAVE_IO_FAIL;
733 goto end;
734 }
735 }
736
737 /* /context */
738 ret = config_writer_close_element(writer);
739 if (ret) {
740 ret = LTTNG_ERR_SAVE_IO_FAIL;
741 goto end;
742 }
743
744 /* /contexts */
745 ret = config_writer_close_element(writer);
746 if (ret) {
747 ret = LTTNG_ERR_SAVE_IO_FAIL;
748 goto end;
749 }
750end:
751 return ret;
752}
753
754static
755int save_ust_context(struct config_writer *writer,
756 struct cds_list_head *ctx_list)
757{
758 int ret;
759 struct ltt_ust_context *ctx;
760
761 assert(writer);
762 assert(ctx_list);
763
764 ret = config_writer_open_element(writer, config_element_contexts);
765 if (ret) {
766 ret = LTTNG_ERR_SAVE_IO_FAIL;
767 goto end;
768 }
769
770 cds_list_for_each_entry(ctx, ctx_list, list) {
771 const char *context_type_string;
772
773 context_type_string = get_ust_context_type_string(ctx->ctx.ctx);
774 if (!context_type_string) {
775 ERR("Unsupported UST context type.")
776 ret = LTTNG_ERR_INVALID;
777 goto end;
778 }
779
780 ret = config_writer_open_element(writer,
781 config_element_context);
782 if (ret) {
783 ret = LTTNG_ERR_SAVE_IO_FAIL;
784 goto end;
785 }
786
787 ret = config_writer_write_element_string(writer,
788 config_element_type, context_type_string);
789 if (ret) {
790 ret = LTTNG_ERR_SAVE_IO_FAIL;
791 goto end;
792 }
793
794 /* /context */
795 ret = config_writer_close_element(writer);
796 if (ret) {
797 ret = LTTNG_ERR_SAVE_IO_FAIL;
798 goto end;
799 }
800 }
801
802 /* /contexts */
803 ret = config_writer_close_element(writer);
804 if (ret) {
805 ret = LTTNG_ERR_SAVE_IO_FAIL;
806 goto end;
807 }
808end:
809 return ret;
810}
811
812static
813int save_kernel_channel(struct config_writer *writer,
814 struct ltt_kernel_channel *kchan)
815{
816 int ret;
817
818 assert(writer);
819 assert(kchan);
820
821 ret = config_writer_open_element(writer, config_element_channel);
822 if (ret) {
823 ret = LTTNG_ERR_SAVE_IO_FAIL;
824 goto end;
825 }
826
827 ret = config_writer_write_element_string(writer, config_element_name,
828 kchan->channel->name);
829 if (ret) {
830 ret = LTTNG_ERR_SAVE_IO_FAIL;
831 goto end;
832 }
833
834 ret = config_writer_write_element_bool(writer, config_element_enabled,
835 kchan->channel->enabled);
836 if (ret) {
837 ret = LTTNG_ERR_SAVE_IO_FAIL;
838 goto end;
839 }
840
841 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
842 if (ret) {
843 goto end;
844 }
845
846 ret = save_kernel_events(writer, &kchan->events_list);
847 if (ret) {
848 goto end;
849 }
850
851 ret = save_kernel_context(writer, kchan->ctx);
852 if (ret) {
853 goto end;
854 }
855
856 /* /channel */
857 ret = config_writer_close_element(writer);
858 if (ret) {
859 ret = LTTNG_ERR_SAVE_IO_FAIL;
860 goto end;
861 }
862end:
863 return ret;
864}
865
866static
867int save_ust_channel(struct config_writer *writer,
868 struct ltt_ust_channel *ust_chan,
869 struct ltt_ust_session *session)
870{
871 int ret;
872
873 assert(writer);
874 assert(ust_chan);
875 assert(session);
876
877 ret = config_writer_open_element(writer, config_element_channel);
878 if (ret) {
879 ret = LTTNG_ERR_SAVE_IO_FAIL;
880 goto end;
881 }
882
883 ret = config_writer_write_element_string(writer, config_element_name,
884 ust_chan->name);
885 if (ret) {
886 ret = LTTNG_ERR_SAVE_IO_FAIL;
887 goto end;
888 }
889
890 ret = config_writer_write_element_bool(writer, config_element_enabled,
891 ust_chan->enabled);
892 if (ret) {
893 ret = LTTNG_ERR_SAVE_IO_FAIL;
894 goto end;
895 }
896
897 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
898 if (ret) {
899 goto end;
900 }
901
902 ret = config_writer_write_element_unsigned_int(writer,
903 config_element_tracefile_size, ust_chan->tracefile_size);
904 if (ret) {
905 ret = LTTNG_ERR_SAVE_IO_FAIL;
906 goto end;
907 }
908
909 ret = config_writer_write_element_unsigned_int(writer,
910 config_element_tracefile_count, ust_chan->tracefile_count);
911 if (ret) {
912 ret = LTTNG_ERR_SAVE_IO_FAIL;
913 goto end;
914 }
915
916 ret = config_writer_write_element_unsigned_int(writer,
917 config_element_live_timer_interval,
918 session->live_timer_interval);
919 if (ret) {
920 ret = LTTNG_ERR_SAVE_IO_FAIL;
921 goto end;
922 }
923
924 ret = save_ust_events(writer, ust_chan->events);
925 if (ret) {
926 ret = LTTNG_ERR_SAVE_IO_FAIL;
927 goto end;
928 }
929
930 ret = save_ust_context(writer, &ust_chan->ctx_list);
931 if (ret) {
932 goto end;
933 }
934
935 /* /channel */
936 ret = config_writer_close_element(writer);
937 if (ret) {
938 ret = LTTNG_ERR_SAVE_IO_FAIL;
939 goto end;
940 }
941end:
942 return ret;
943}
944
945static
946int save_kernel_session(struct config_writer *writer,
947 struct ltt_session *session)
948{
949 int ret;
950 struct ltt_kernel_channel *kchan;
951
952 assert(writer);
953 assert(session);
954
955 ret = config_writer_write_element_string(writer, config_element_type,
956 config_domain_type_kernel);
957 if (ret) {
958 ret = LTTNG_ERR_SAVE_IO_FAIL;
959 goto end;
960 }
961
962 ret = config_writer_write_element_string(writer,
963 config_element_buffer_type, config_buffer_type_global);
964 if (ret) {
965 ret = LTTNG_ERR_SAVE_IO_FAIL;
966 goto end;
967 }
968
969 ret = config_writer_open_element(writer,
970 config_element_channels);
971 if (ret) {
972 ret = LTTNG_ERR_SAVE_IO_FAIL;
973 goto end;
974 }
975
976 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
977 list) {
978 ret = save_kernel_channel(writer, kchan);
979 if (ret) {
980 goto end;
981 }
982 }
983
984 /* /channels */
985 ret = config_writer_close_element(writer);
986 if (ret) {
987 ret = LTTNG_ERR_SAVE_IO_FAIL;
988 goto end;
989 }
990end:
991 return ret;
992}
993
994static
995int save_ust_session(struct config_writer *writer,
996 struct ltt_session *session, int save_jul)
997{
998 int ret;
999 struct ltt_ust_channel *ust_chan;
1000 const char *buffer_type_string;
1001 struct lttng_ht_node_str *node;
1002 struct lttng_ht_iter iter;
1003
1004 assert(writer);
1005 assert(session);
1006
1007 ret = config_writer_write_element_string(writer, config_element_type,
1008 save_jul ? config_domain_type_jul : config_domain_type_ust);
1009 if (ret) {
1010 ret = LTTNG_ERR_SAVE_IO_FAIL;
1011 goto end;
1012 }
1013
1014 buffer_type_string = get_buffer_type_string(
1015 session->ust_session->buffer_type);
1016 if (!buffer_type_string) {
1017 ERR("Unsupported buffer type.");
1018 ret = LTTNG_ERR_INVALID;
1019 goto end;
1020 }
1021
1022 ret = config_writer_write_element_string(writer,
1023 config_element_buffer_type, buffer_type_string);
1024 if (ret) {
1025 ret = LTTNG_ERR_SAVE_IO_FAIL;
1026 goto end;
1027 }
1028
1029 ret = config_writer_open_element(writer, config_element_channels);
1030 if (ret) {
1031 ret = LTTNG_ERR_SAVE_IO_FAIL;
1032 goto end;
1033 }
1034
1035 rcu_read_lock();
1036 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1037 &iter.iter, node, node) {
1038 int jul_channel;
1039
1040 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
1041 jul_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name);
1042 if (!(save_jul ^ jul_channel)) {
1043 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1044 if (ret) {
1045 rcu_read_unlock();
1046 goto end;
1047 }
1048 }
1049 }
1050 rcu_read_unlock();
1051
1052 /* /channels */
1053 ret = config_writer_close_element(writer);
1054 if (ret) {
1055 ret = LTTNG_ERR_SAVE_IO_FAIL;
1056 goto end;
1057 }
1058end:
1059 return ret;
1060}
1061
1062static
1063int save_domains(struct config_writer *writer, struct ltt_session *session)
1064{
1065 int ret = 0;
1066
1067 assert(writer);
1068 assert(session);
1069
1070 if (!session->kernel_session && !session->ust_session) {
1071 goto end;
1072 }
1073
1074 ret = config_writer_open_element(writer, config_element_domains);
1075 if (ret) {
1076 ret = LTTNG_ERR_SAVE_IO_FAIL;
1077 goto end;
1078 }
1079
1080
1081 if (session->kernel_session) {
1082 ret = config_writer_open_element(writer,
1083 config_element_domain);
1084 if (ret) {
1085 ret = LTTNG_ERR_SAVE_IO_FAIL;
1086 goto end;
1087 }
1088
1089 ret = save_kernel_session(writer, session);
1090 if (ret) {
1091 goto end;
1092 }
1093
1094 /* /domain */
1095 ret = config_writer_close_element(writer);
1096 if (ret) {
1097 ret = LTTNG_ERR_SAVE_IO_FAIL;
1098 goto end;
1099 }
1100 }
1101
1102 if (session->ust_session) {
1103 ret = config_writer_open_element(writer,
1104 config_element_domain);
1105 if (ret) {
1106 ret = LTTNG_ERR_SAVE_IO_FAIL;
1107 goto end;
1108 }
1109
1110 ret = save_ust_session(writer, session, 0);
1111 if (ret) {
1112 goto end;
1113 }
1114
1115 /* /domain */
1116 ret = config_writer_close_element(writer);
1117 if (ret) {
1118 ret = LTTNG_ERR_SAVE_IO_FAIL;
1119 goto end;
1120 }
1121 }
1122
1123 if (session->ust_session &&
1124 session->ust_session->domain_jul.being_used) {
1125 ret = config_writer_open_element(writer,
1126 config_element_domain);
1127 if (ret) {
1128 ret = LTTNG_ERR_SAVE_IO_FAIL;
1129 goto end;
1130 }
1131
1132 ret = save_ust_session(writer, session, 1);
1133 if (ret) {
1134 goto end;
1135 }
1136
1137 /* /domain */
1138 ret = config_writer_close_element(writer);
1139 if (ret) {
1140 ret = LTTNG_ERR_SAVE_IO_FAIL;
1141 goto end;
1142 }
1143 }
1144
1145 /* /domains */
1146 ret = config_writer_close_element(writer);
1147 if (ret) {
1148 ret = LTTNG_ERR_SAVE_IO_FAIL;
1149 goto end;
1150 }
1151end:
1152 return ret;
1153}
1154
1155static
1156int save_consumer_output(struct config_writer *writer,
1157 struct consumer_output *output)
1158{
1159 int ret;
1160
1161 assert(writer);
1162 assert(output);
1163
1164 ret = config_writer_open_element(writer, config_element_consumer_output);
1165 if (ret) {
1166 ret = LTTNG_ERR_SAVE_IO_FAIL;
1167 goto end;
1168 }
1169
1170 ret = config_writer_write_element_bool(writer, config_element_enabled,
1171 output->enabled);
1172 if (ret) {
1173 ret = LTTNG_ERR_SAVE_IO_FAIL;
1174 goto end;
1175 }
1176
1177 ret = config_writer_open_element(writer, config_element_destination);
1178 if (ret) {
1179 ret = LTTNG_ERR_SAVE_IO_FAIL;
1180 goto end;
1181 }
1182
1183 switch (output->type) {
1184 case CONSUMER_DST_LOCAL:
1185 ret = config_writer_write_element_string(writer,
1186 config_element_path, output->dst.trace_path);
1187 if (ret) {
1188 ret = LTTNG_ERR_SAVE_IO_FAIL;
1189 goto end;
1190 }
1191 break;
1192 case CONSUMER_DST_NET:
1193 {
1194 char *uri;
1195
1196 uri = zmalloc(PATH_MAX);
1197 if (!uri) {
1198 ret = LTTNG_ERR_NOMEM;
1199 goto end;
1200 }
1201
1202 ret = config_writer_open_element(writer, config_element_net_output);
1203 if (ret) {
1204 ret = LTTNG_ERR_SAVE_IO_FAIL;
1205 goto end_net_output;
1206 }
1207
1208 if (output->dst.net.control_isset &&
1209 output->dst.net.data_isset) {
1210 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1211 if (ret < 0) {
1212 ret = LTTNG_ERR_INVALID;
1213 goto end_net_output;
1214 }
1215
1216 ret = config_writer_write_element_string(writer,
1217 config_element_control_uri, uri);
1218 if (ret) {
1219 ret = LTTNG_ERR_SAVE_IO_FAIL;
1220 goto end_net_output;
1221 }
1222
1223 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1224 if (ret < 0) {
1225 ret = LTTNG_ERR_INVALID;
1226 goto end_net_output;
1227 }
1228
1229 ret = config_writer_write_element_string(writer,
1230 config_element_data_uri, uri);
1231 if (ret) {
1232 ret = LTTNG_ERR_SAVE_IO_FAIL;
1233 goto end_net_output;
1234 }
1235
1236end_net_output:
1237 free(uri);
1238 if (ret) {
1239 goto end;
1240 }
1241 } else {
1242 ret = !output->dst.net.control_isset ?
1243 LTTNG_ERR_URL_CTRL_MISS :
1244 LTTNG_ERR_URL_DATA_MISS;
c39270e5 1245 free(uri);
fb198a11
JG
1246 goto end;
1247 }
1248
1249 ret = config_writer_close_element(writer);
1250 if (ret) {
1251 ret = LTTNG_ERR_SAVE_IO_FAIL;
1252 goto end;
1253 }
1254 break;
1255 }
1256 default:
1257 ERR("Unsupported consumer output type.");
1258 ret = LTTNG_ERR_INVALID;
1259 goto end;
1260 }
1261
1262 /* /destination */
1263 ret = config_writer_close_element(writer);
1264 if (ret) {
1265 ret = LTTNG_ERR_SAVE_IO_FAIL;
1266 goto end;
1267 }
1268
1269 /* /consumer_output */
1270 ret = config_writer_close_element(writer);
1271 if (ret) {
1272 ret = LTTNG_ERR_SAVE_IO_FAIL;
1273 goto end;
1274 }
1275end:
1276 return ret;
1277}
1278
1279static
1280int save_snapshot_outputs(struct config_writer *writer,
1281 struct snapshot *snapshot)
1282{
1283 int ret;
1284 struct lttng_ht_iter iter;
1285 struct snapshot_output *output;
1286
1287 assert(writer);
1288 assert(snapshot);
1289
1290 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1291 if (ret) {
1292 ret = LTTNG_ERR_SAVE_IO_FAIL;
1293 goto end;
1294 }
1295
1296 rcu_read_lock();
1297 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1298 node.node) {
1299 ret = config_writer_open_element(writer,
1300 config_element_output);
1301 if (ret) {
1302 ret = LTTNG_ERR_SAVE_IO_FAIL;
1303 goto end_unlock;
1304 }
1305
1306 ret = config_writer_write_element_string(writer,
1307 config_element_name, output->name);
1308 if (ret) {
1309 ret = LTTNG_ERR_SAVE_IO_FAIL;
1310 goto end_unlock;
1311 }
1312
1313 ret = config_writer_write_element_unsigned_int(writer,
1314 config_element_max_size, output->max_size);
1315 if (ret) {
1316 ret = LTTNG_ERR_SAVE_IO_FAIL;
1317 goto end_unlock;
1318 }
1319
1320 ret = save_consumer_output(writer, output->consumer);
1321 if (ret) {
1322 goto end_unlock;
1323 }
1324
1325 /* /output */
1326 ret = config_writer_close_element(writer);
1327 if (ret) {
1328 ret = LTTNG_ERR_SAVE_IO_FAIL;
1329 goto end_unlock;
1330 }
1331 }
1332 rcu_read_unlock();
1333
1334 /* /snapshot_outputs */
1335 ret = config_writer_close_element(writer);
1336 if (ret) {
1337 ret = LTTNG_ERR_SAVE_IO_FAIL;
1338 goto end;
1339 }
1340
1341end:
1342 return ret;
1343end_unlock:
1344 rcu_read_unlock();
1345 return ret;
1346}
1347
1348static
1349int save_session_output(struct config_writer *writer,
1350 struct ltt_session *session)
1351{
1352 int ret;
1353
1354 assert(writer);
1355 assert(session);
1356
1357 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1358 (!session->snapshot_mode && !session->consumer)) {
1359 /* Session is in no output mode */
1360 ret = 0;
1361 goto end;
1362 }
1363
1364 ret = config_writer_open_element(writer, config_element_output);
1365 if (ret) {
1366 ret = LTTNG_ERR_SAVE_IO_FAIL;
1367 goto end;
1368 }
1369
1370 if (session->snapshot_mode) {
1371 ret = save_snapshot_outputs(writer, &session->snapshot);
1372 if (ret) {
1373 goto end;
1374 }
1375 } else {
1376 if (session->consumer) {
1377 ret = save_consumer_output(writer, session->consumer);
1378 if (ret) {
1379 goto end;
1380 }
1381 }
1382 }
1383
1384 /* /output */
1385 ret = config_writer_close_element(writer);
1386 if (ret) {
1387 ret = LTTNG_ERR_SAVE_IO_FAIL;
1388 goto end;
1389 }
1390end:
1391 return ret;
1392}
1393
1394/*
1395 * Save the given session.
1396 *
1397 * Return 0 on success else a LTTNG_ERR* code.
1398 */
1399static
1400int save_session(struct ltt_session *session,
1401 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1402{
1403 int ret, fd;
db471218 1404 unsigned int file_opened = 0; /* Indicate if the file has been opened */
fb198a11
JG
1405 char config_file_path[PATH_MAX];
1406 size_t len;
1407 struct config_writer *writer = NULL;
1408 size_t session_name_len;
1409 const char *provided_path;
1410
1411 assert(session);
1412 assert(attr);
1413 assert(creds);
1414
1415 session_name_len = strlen(session->name);
95a29ab8 1416 memset(config_file_path, 0, sizeof(config_file_path));
fb198a11
JG
1417
1418 if (!session_access_ok(session,
1419 LTTNG_SOCK_GET_UID_CRED(creds),
1420 LTTNG_SOCK_GET_GID_CRED(creds))) {
1421 ret = LTTNG_ERR_EPERM;
1422 goto end;
1423 }
1424
1425 provided_path = lttng_save_session_attr_get_output_url(attr);
1426 if (provided_path) {
95a29ab8 1427 DBG3("Save session in provided path %s", provided_path);
fb198a11 1428 len = strlen(provided_path);
d2992717 1429 if (len >= sizeof(config_file_path)) {
fb198a11
JG
1430 ret = LTTNG_ERR_SET_URL;
1431 goto end;
1432 }
1433 strncpy(config_file_path, provided_path, len);
1434 } else {
7e078ad1 1435 ssize_t ret_len;
fb198a11
JG
1436 char *home_dir = utils_get_user_home_dir(
1437 LTTNG_SOCK_GET_UID_CRED(creds));
1438 if (!home_dir) {
1439 ret = LTTNG_ERR_SET_URL;
1440 goto end;
1441 }
1442
d2992717 1443 ret_len = snprintf(config_file_path, sizeof(config_file_path),
fb198a11
JG
1444 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1445 free(home_dir);
7e078ad1 1446 if (ret_len < 0) {
fb198a11
JG
1447 PERROR("snprintf save session");
1448 ret = LTTNG_ERR_SET_URL;
1449 goto end;
1450 }
7e078ad1 1451 len = ret_len;
fb198a11
JG
1452 }
1453
1454 /*
d2992717
DG
1455 * Check the path fits in the config file path dst including the '/'
1456 * followed by trailing .lttng extension and the NULL terminated string.
fb198a11 1457 */
d2992717
DG
1458 if ((len + session_name_len + 2 +
1459 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1460 > sizeof(config_file_path)) {
fb198a11
JG
1461 ret = LTTNG_ERR_SET_URL;
1462 goto end;
1463 }
1464
1465 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1466 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1467 if (ret) {
1468 ret = LTTNG_ERR_SET_URL;
1469 goto end;
1470 }
1471
d2992717
DG
1472 /*
1473 * At this point, we know that everything fits in the buffer. Validation
1474 * was done just above.
1475 */
fb198a11
JG
1476 config_file_path[len++] = '/';
1477 strncpy(config_file_path + len, session->name, session_name_len);
1478 len += session_name_len;
1479 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
95a29ab8
DG
1480 len += sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1481 config_file_path[len] = '\0';
fb198a11
JG
1482
1483 if (!access(config_file_path, F_OK) && !attr->overwrite) {
f9b57ab2
DG
1484 /* File exists, notify the user since the overwrite flag is off. */
1485 ret = LTTNG_ERR_SAVE_FILE_EXIST;
fb198a11
JG
1486 goto end;
1487 }
1488
1489 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1490 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1491 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1492 if (fd < 0) {
1493 PERROR("Could not create configuration file");
1494 ret = LTTNG_ERR_SAVE_IO_FAIL;
1495 goto end;
1496 }
db471218 1497 file_opened = 1;
fb198a11
JG
1498
1499 writer = config_writer_create(fd);
1500 if (!writer) {
1501 ret = LTTNG_ERR_NOMEM;
1502 goto end;
1503 }
1504
1505 ret = config_writer_open_element(writer, config_element_sessions);
1506 if (ret) {
1507 ret = LTTNG_ERR_SAVE_IO_FAIL;
1508 goto end;
1509 }
1510
1511 ret = config_writer_open_element(writer, config_element_session);
1512 if (ret) {
1513 ret = LTTNG_ERR_SAVE_IO_FAIL;
1514 goto end;
1515 }
1516
1517 ret = config_writer_write_element_string(writer, config_element_name,
1518 session->name);
1519 if (ret) {
1520 ret = LTTNG_ERR_SAVE_IO_FAIL;
1521 goto end;
1522 }
1523
1524 ret = save_domains(writer, session);
1525 if (ret) {
1526 goto end;
1527 }
1528
1529 ret = config_writer_write_element_bool(writer, config_element_started,
8382cf6f 1530 session->active);
fb198a11
JG
1531 if (ret) {
1532 ret = LTTNG_ERR_SAVE_IO_FAIL;
1533 goto end;
1534 }
1535
1536 if (session->snapshot_mode || session->live_timer) {
1537 ret = config_writer_open_element(writer, config_element_attributes);
1538 if (ret) {
1539 ret = LTTNG_ERR_SAVE_IO_FAIL;
1540 goto end;
1541 }
1542
1543 if (session->snapshot_mode) {
1544 ret = config_writer_write_element_bool(writer,
1545 config_element_snapshot_mode, 1);
1546 if (ret) {
1547 ret = LTTNG_ERR_SAVE_IO_FAIL;
1548 goto end;
1549 }
1550 } else {
1551 ret = config_writer_write_element_signed_int(writer,
1552 config_element_live_timer_interval, session->live_timer);
1553 if (ret) {
1554 ret = LTTNG_ERR_SAVE_IO_FAIL;
1555 goto end;
1556 }
1557 }
1558
1559 /* /attributes */
1560 ret = config_writer_close_element(writer);
1561 if (ret) {
1562 ret = LTTNG_ERR_SAVE_IO_FAIL;
1563 goto end;
1564 }
1565 }
1566
1567 ret = save_session_output(writer, session);
1568 if (ret) {
1569 goto end;
1570 }
1571
1572 /* /session */
1573 ret = config_writer_close_element(writer);
1574 if (ret) {
1575 ret = LTTNG_ERR_SAVE_IO_FAIL;
1576 goto end;
1577 }
1578
1579 /* /sessions */
1580 ret = config_writer_close_element(writer);
1581 if (ret) {
1582 ret = LTTNG_ERR_SAVE_IO_FAIL;
1583 goto end;
1584 }
1585end:
1586 if (writer && config_writer_destroy(writer)) {
1587 /* Preserve the original error code */
1588 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1589 }
1590 if (ret) {
1591 /* Delete file in case of error */
db471218 1592 if (file_opened && unlink(config_file_path)) {
fb198a11
JG
1593 PERROR("Unlinking XML session configuration.");
1594 }
1595 }
1596
1597 return ret;
1598}
1599
1600int cmd_save_sessions(struct lttng_save_session_attr *attr,
1601 lttng_sock_cred *creds)
1602{
1603 int ret;
1604 const char *session_name;
1605 struct ltt_session *session;
1606
1607 session_lock_list();
1608
1609 session_name = lttng_save_session_attr_get_session_name(attr);
1610 if (session_name) {
1611 session = session_find_by_name(session_name);
1612 if (!session) {
1613 ret = LTTNG_ERR_SESS_NOT_FOUND;
1614 goto end;
1615 }
1616
1617 session_lock(session);
1618 ret = save_session(session, attr, creds);
1619 session_unlock(session);
1620 if (ret) {
1621 goto end;
1622 }
1623 } else {
1624 struct ltt_session_list *list = session_get_list();
1625
1626 cds_list_for_each_entry(session, &list->head, list) {
1627 session_lock(session);
1628 ret = save_session(session, attr, creds);
1629 session_unlock(session);
1630
1631 /* Don't abort if we don't have the required permissions. */
1632 if (ret && ret != LTTNG_ERR_EPERM) {
1633 goto end;
1634 }
1635 }
1636 }
1637 ret = LTTNG_OK;
1638
1639end:
1640 session_unlock_list();
1641 return ret;
1642}
This page took 0.086349 seconds and 4 git commands to generate.