Improve trace output path and config path
[lttng-tools.git] / ltt-sessiond / kernel-ctl.c
CommitLineData
20fe2104
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
8c0faa1d 19#define _GNU_SOURCE
20fe2104 20#include <errno.h>
7b395890 21#include <fcntl.h>
20fe2104
DG
22#include <stdlib.h>
23#include <stdio.h>
f34daff7 24#include <string.h>
8c0faa1d 25#include <unistd.h>
20fe2104 26
8c0faa1d 27#include "lttngerr.h"
20fe2104
DG
28#include "ltt-sessiond.h"
29#include "libkernelctl.h"
30#include "kernel-ctl.h"
20fe2104 31
d65106b1
DG
32/*
33 * kernel_add_channel_context
34 *
35 * Add context on a kernel channel.
36 */
37int kernel_add_channel_context(struct ltt_kernel_channel *chan,
38 struct lttng_kernel_context *ctx)
39{
40 int ret;
41
42 DBG("Adding context to channel %s", chan->channel->name);
43 ret = kernctl_add_context(chan->fd, ctx);
44 if (ret < 0) {
45 perror("add context ioctl");
46 goto error;
47 }
48
49 chan->ctx = malloc(sizeof(struct lttng_kernel_context));
50 if (chan->ctx == NULL) {
51 perror("malloc event context");
52 goto error;
53 }
54
55 memcpy(chan->ctx, ctx, sizeof(struct lttng_kernel_context));
56
57 return 0;
58
59error:
60 return ret;
61}
62
63/*
64 * kernel_add_event_context
65 *
66 * Add context on a kernel event.
67 */
68int kernel_add_event_context(struct ltt_kernel_event *event,
69 struct lttng_kernel_context *ctx)
70{
71 int ret;
72
73 DBG("Adding context to event %s", event->event->name);
74 ret = kernctl_add_context(event->fd, ctx);
75 if (ret < 0) {
76 perror("add context ioctl");
77 goto error;
78 }
79
80 event->ctx = malloc(sizeof(struct lttng_kernel_context));
81 if (event->ctx == NULL) {
82 perror("malloc event context");
83 goto error;
84 }
85
86 memcpy(event->ctx, ctx, sizeof(struct lttng_kernel_context));
87
88 return 0;
89
90error:
91 return ret;
92}
93
20fe2104
DG
94/*
95 * kernel_create_session
96 *
54012638
DG
97 * Create a new kernel session, register it to the kernel tracer and add it to
98 * the session daemon session.
20fe2104 99 */
8c0faa1d 100int kernel_create_session(struct ltt_session *session, int tracer_fd)
20fe2104
DG
101{
102 int ret;
103 struct ltt_kernel_session *lks;
104
54012638
DG
105 /* Allocate data structure */
106 lks = trace_create_kernel_session();
20fe2104 107 if (lks == NULL) {
54012638 108 ret = -1;
20fe2104
DG
109 goto error;
110 }
111
54012638 112 /* Kernel tracer session creation */
20fe2104
DG
113 ret = kernctl_create_session(tracer_fd);
114 if (ret < 0) {
54012638 115 perror("ioctl kernel create session");
20fe2104
DG
116 goto error;
117 }
118
20fe2104 119 lks->fd = ret;
7b395890
DG
120 /* Prevent fd duplication after execlp() */
121 ret = fcntl(lks->fd, F_SETFD, FD_CLOEXEC);
122 if (ret < 0) {
123 perror("fcntl session fd");
124 }
125
f3ed775e 126 lks->kconsumer_fds_sent = 0;
8c0faa1d
DG
127 session->kernel_session = lks;
128 session->kern_session_count++;
8c0faa1d
DG
129
130 DBG("Kernel session created (fd: %d)", lks->fd);
20fe2104
DG
131
132 return 0;
133
134error:
135 return ret;
136}
137
138/*
139 * kernel_create_channel
140 *
54012638
DG
141 * Create a kernel channel, register it to the kernel tracer and add it to the
142 * kernel session.
20fe2104 143 */
b082db07 144int kernel_create_channel(struct ltt_kernel_session *session, struct lttng_channel *chan, char *path)
20fe2104
DG
145{
146 int ret;
147 struct ltt_kernel_channel *lkc;
20fe2104 148
54012638 149 /* Allocate kernel channel */
b082db07 150 lkc = trace_create_kernel_channel(chan, path);
54012638 151 if (lkc == NULL) {
20fe2104
DG
152 goto error;
153 }
154
54012638 155 /* Kernel tracer channel creation */
f3ed775e 156 ret = kernctl_create_channel(session->fd, &lkc->channel->attr);
20fe2104 157 if (ret < 0) {
54012638 158 perror("ioctl kernel create channel");
20fe2104
DG
159 goto error;
160 }
161
54012638 162 /* Setup the channel fd */
20fe2104 163 lkc->fd = ret;
7b395890
DG
164 /* Prevent fd duplication after execlp() */
165 ret = fcntl(lkc->fd, F_SETFD, FD_CLOEXEC);
166 if (ret < 0) {
167 perror("fcntl session fd");
168 }
169
54012638 170 /* Add channel to session */
8c0faa1d
DG
171 cds_list_add(&lkc->list, &session->channel_list.head);
172 session->channel_count++;
20fe2104 173
f3ed775e
DG
174 DBG("Kernel channel %s created (fd: %d and path: %s)",
175 lkc->channel->name, lkc->fd, lkc->pathname);
20fe2104
DG
176
177 return 0;
178
179error:
54012638 180 return -1;
20fe2104 181}
f34daff7
DG
182
183/*
f3ed775e 184 * kernel_create_event
f34daff7 185 *
54012638
DG
186 * Create a kernel event, enable it to the kernel tracer and add it to the
187 * channel event list of the kernel session.
f34daff7 188 */
19e70852 189int kernel_create_event(struct lttng_event *ev, struct ltt_kernel_channel *channel)
f34daff7
DG
190{
191 int ret;
192 struct ltt_kernel_event *event;
f34daff7 193
f3ed775e 194 event = trace_create_kernel_event(ev);
54012638 195 if (event == NULL) {
f34daff7
DG
196 goto error;
197 }
198
f3ed775e
DG
199 ret = kernctl_create_event(channel->fd, event->event);
200 if (ret < 0) {
e953ef25
DG
201 perror("create event ioctl");
202 goto free_event;
8c0faa1d 203 }
f34daff7 204
f3ed775e 205 event->fd = ret;
7b395890
DG
206 /* Prevent fd duplication after execlp() */
207 ret = fcntl(event->fd, F_SETFD, FD_CLOEXEC);
208 if (ret < 0) {
209 perror("fcntl session fd");
210 }
211
f3ed775e
DG
212 /* Add event to event list */
213 cds_list_add(&event->list, &channel->events_list.head);
e953ef25
DG
214 DBG("Event %s created (fd: %d)", ev->name, event->fd);
215
216 return 0;
217
218free_event:
219 free(event);
220error:
221 return -1;
222}
223
26cc6b4e
DG
224/*
225 * kernel_disable_channel
226 *
227 * Disable a kernel channel.
228 */
229int kernel_disable_channel(struct ltt_kernel_channel *chan)
230{
231 int ret;
232
233 ret = kernctl_disable(chan->fd);
234 if (ret < 0) {
235 perror("disable chan ioctl");
236 ret = errno;
237 goto error;
238 }
239
240 chan->enabled = 0;
241 DBG("Kernel channel %s disabled (fd: %d)", chan->channel->name, chan->fd);
242
243 return 0;
244
245error:
246 return ret;
247}
248
d36b8583
DG
249/*
250 * kernel_enable_channel
251 *
252 * Enable a kernel channel.
253 */
254int kernel_enable_channel(struct ltt_kernel_channel *chan)
255{
256 int ret;
257
258 ret = kernctl_enable(chan->fd);
259 if (ret < 0) {
260 perror("enable chan ioctl");
261 ret = errno;
262 goto error;
263 }
264
265 chan->enabled = 1;
266 DBG("Kernel channel %s enabled (fd: %d)", chan->channel->name, chan->fd);
267
268 return 0;
269
270error:
271 return ret;
272}
273
19e70852
DG
274/*
275 * kernel_enable_event
276 *
277 * Enable a kernel event.
278 */
279int kernel_enable_event(struct ltt_kernel_event *event)
280{
281 int ret;
282
283 ret = kernctl_enable(event->fd);
284 if (ret < 0) {
285 perror("enable event ioctl");
286 goto error;
287 }
288
289 event->enabled = 1;
290 DBG("Kernel event %s enabled (fd: %d)", event->event->name, event->fd);
291
292 return 0;
293
294error:
d36b8583 295 return ret;
19e70852
DG
296}
297
e953ef25
DG
298/*
299 * kernel_disable_event
300 *
19e70852 301 * Disable a kernel event.
e953ef25 302 */
19e70852 303int kernel_disable_event(struct ltt_kernel_event *event)
e953ef25
DG
304{
305 int ret;
19e70852
DG
306
307 ret = kernctl_disable(event->fd);
308 if (ret < 0) {
309 perror("disable event ioctl");
310 goto error;
e953ef25 311 }
f3ed775e 312
19e70852
DG
313 event->enabled = 0;
314 DBG("Kernel event %s disabled (fd: %d)", event->event->name, event->fd);
315
f34daff7
DG
316 return 0;
317
318error:
d36b8583 319 return ret;
f34daff7 320}
aaf26714
DG
321
322/*
323 * kernel_open_metadata
324 *
54012638
DG
325 * Create kernel metadata, open from the kernel tracer and add it to the
326 * kernel session.
aaf26714
DG
327 */
328int kernel_open_metadata(struct ltt_kernel_session *session)
329{
330 int ret;
331 struct ltt_kernel_metadata *lkm;
aaf26714 332
54012638
DG
333 /* Allocate kernel metadata */
334 lkm = trace_create_kernel_metadata();
335 if (lkm == NULL) {
aaf26714
DG
336 goto error;
337 }
338
54012638 339 /* Kernel tracer metadata creation */
f3ed775e 340 ret = kernctl_open_metadata(session->fd, &lkm->conf->attr);
aaf26714
DG
341 if (ret < 0) {
342 goto error;
343 }
344
8c0faa1d 345 lkm->fd = ret;
7b395890
DG
346 /* Prevent fd duplication after execlp() */
347 ret = fcntl(lkm->fd, F_SETFD, FD_CLOEXEC);
348 if (ret < 0) {
349 perror("fcntl session fd");
350 }
351
aaf26714 352 session->metadata = lkm;
8c0faa1d 353
54012638 354 DBG("Kernel metadata opened (fd: %d and path: %s)", lkm->fd, lkm->pathname);
8c0faa1d
DG
355
356 return 0;
357
358error:
54012638 359 return -1;
8c0faa1d
DG
360}
361
362/*
363 * kernel_start_session
364 *
365 * Start tracing session.
366 */
367int kernel_start_session(struct ltt_kernel_session *session)
368{
369 int ret;
370
371 ret = kernctl_start_session(session->fd);
372 if (ret < 0) {
f3ed775e 373 perror("ioctl start session");
8c0faa1d
DG
374 goto error;
375 }
376
377 DBG("Kernel session started");
378
379 return 0;
380
381error:
382 return ret;
383}
384
f3ed775e
DG
385/*
386 * kernel_wait_quiescent
387 *
388 * Make a kernel wait to make sure in-flight probe have completed.
389 */
390void kernel_wait_quiescent(int fd)
391{
392 int ret;
393
394 DBG("Kernel quiescent wait on %d", fd);
395
396 ret = kernctl_wait_quiescent(fd);
397 if (ret < 0) {
398 perror("wait quiescent ioctl");
399 ERR("Kernel quiescent wait failed");
400 }
401}
402
403/*
404 * kernel_metadata_flush_buffer
405 *
406 * Force flush buffer of metadata.
407 */
408int kernel_metadata_flush_buffer(int fd)
409{
410 int ret;
411
412 ret = kernctl_buffer_flush(fd);
413 if (ret < 0) {
414 ERR("Fail to flush metadata buffers %d (ret: %d", fd, ret);
415 }
416
417 return 0;
418}
419
420/*
421 * kernel_flush_buffer
422 *
423 * Force flush buffer for channel.
424 */
425int kernel_flush_buffer(struct ltt_kernel_channel *channel)
426{
427 int ret;
428 struct ltt_kernel_stream *stream;
429
430 DBG("Flush buffer for channel %s", channel->channel->name);
431
432 cds_list_for_each_entry(stream, &channel->stream_list.head, list) {
433 DBG("Flushing channel stream %d", stream->fd);
434 ret = kernctl_buffer_flush(stream->fd);
435 if (ret < 0) {
436 perror("ioctl");
437 ERR("Fail to flush buffer for stream %d (ret: %d)",
438 stream->fd, ret);
439 }
440 }
441
442 return 0;
443}
444
8c0faa1d
DG
445/*
446 * kernel_stop_session
447 *
448 * Stop tracing session.
449 */
450int kernel_stop_session(struct ltt_kernel_session *session)
451{
452 int ret;
453
454 ret = kernctl_stop_session(session->fd);
455 if (ret < 0) {
456 goto error;
457 }
458
459 DBG("Kernel session stopped");
460
461 return 0;
462
463error:
464 return ret;
465}
466
467/*
f3ed775e 468 * kernel_open_channel_stream
8c0faa1d 469 *
f3ed775e 470 * Open stream of channel, register it to the kernel tracer and add it
54012638 471 * to the stream list of the channel.
8c0faa1d
DG
472 *
473 * Return the number of created stream. Else, a negative value.
474 */
f3ed775e 475int kernel_open_channel_stream(struct ltt_kernel_channel *channel)
8c0faa1d
DG
476{
477 int ret;
478 struct ltt_kernel_stream *lks;
479
480 while ((ret = kernctl_create_stream(channel->fd)) > 0) {
54012638 481 lks = trace_create_kernel_stream();
8c0faa1d 482 if (lks == NULL) {
54012638 483 close(ret);
8c0faa1d
DG
484 goto error;
485 }
486
487 lks->fd = ret;
7b395890
DG
488 /* Prevent fd duplication after execlp() */
489 ret = fcntl(lks->fd, F_SETFD, FD_CLOEXEC);
490 if (ret < 0) {
491 perror("fcntl session fd");
492 }
493
8e68d1c8
DG
494 ret = asprintf(&lks->pathname, "%s/%s_%d",
495 channel->pathname, channel->channel->name, channel->stream_count);
8c0faa1d
DG
496 if (ret < 0) {
497 perror("asprintf kernel create stream");
498 goto error;
499 }
8c0faa1d 500
54012638 501 /* Add stream to channe stream list */
8c0faa1d
DG
502 cds_list_add(&lks->list, &channel->stream_list.head);
503 channel->stream_count++;
8c0faa1d 504
54012638
DG
505 DBG("Kernel stream %d created (fd: %d, state: %d, path: %s)",
506 channel->stream_count, lks->fd, lks->state, lks->pathname);
507 }
8c0faa1d
DG
508
509 return channel->stream_count;
510
511error:
54012638 512 return -1;
8c0faa1d
DG
513}
514
515/*
f3ed775e 516 * kernel_open_metadata_stream
8c0faa1d 517 *
f3ed775e 518 * Open the metadata stream and set it to the kernel session.
8c0faa1d 519 */
f3ed775e 520int kernel_open_metadata_stream(struct ltt_kernel_session *session)
8c0faa1d
DG
521{
522 int ret;
523
524 ret = kernctl_create_stream(session->metadata->fd);
525 if (ret < 0) {
526 perror("kernel create metadata stream");
8c0faa1d
DG
527 goto error;
528 }
529
530 DBG("Kernel metadata stream created (fd: %d)", ret);
531 session->metadata_stream_fd = ret;
7b395890
DG
532 /* Prevent fd duplication after execlp() */
533 ret = fcntl(session->metadata_stream_fd, F_SETFD, FD_CLOEXEC);
534 if (ret < 0) {
535 perror("fcntl session fd");
536 }
aaf26714
DG
537
538 return 0;
539
540error:
54012638 541 return -1;
aaf26714 542}
2ef84c95
DG
543
544/*
545 * kernel_list_events
546 *
547 * Get the event list from the kernel tracer and return that list in the CTF
548 * format.
549 */
550ssize_t kernel_list_events(int tracer_fd, char **list)
551{
552 int fd;
553 char *buf, *line = NULL;
554 size_t nb, nbmem, total = 0;
555 ssize_t size;
556 FILE *fp;
557
558 fd = kernctl_tracepoint_list(tracer_fd);
559 if (fd < 0) {
560 perror("kernel tracepoint list");
561 goto error;
562 }
563
564 fp = fdopen(fd, "r");
565 if (fp == NULL) {
566 perror("kernel tracepoint list fdopen");
567 goto error;
568 }
569
570 /*
571 * Init memory size counter
572 * See kernel-ctl.h for explanation of this value
573 */
574 nbmem = KERNEL_EVENT_LIST_SIZE;
575 buf = malloc(nbmem);
576
577 while ((size = getline(&line, &nb, fp)) != -1) {
578 if (total + size > nbmem) {
d686b40f 579 DBG("Reallocating event list from %zd to %zd bytes", nbmem,
2ef84c95
DG
580 total + size + KERNEL_EVENT_LIST_SIZE);
581 /* Adding the default size again */
582 nbmem = total + size + KERNEL_EVENT_LIST_SIZE;
583 buf = realloc(buf, nbmem);
584 if (buf == NULL) {
585 perror("realloc list events");
586 goto error;
587 }
588 }
589 memcpy(buf + total, line, size);
590 total += size;
591 }
592
593 *list = buf;
594
595 DBG("Kernel list events done");
596
597 return total;
598
599error:
600 return -1;
601}
This page took 0.047129 seconds and 4 git commands to generate.