X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=ltt-sessiond%2Ftrace.c;h=0ae80adbc465e49ba270cfc5f7268ffec0eab9a6;hp=c5d700fd1450b17d842c20a93eef220d75e83d5d;hb=050349bbb362ea993533591532643022efeab864;hpb=1657e9bb835a28e66396deac871270fe373d5ff4 diff --git a/ltt-sessiond/trace.c b/ltt-sessiond/trace.c index c5d700fd1..0ae80adbc 100644 --- a/ltt-sessiond/trace.c +++ b/ltt-sessiond/trace.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2011 - David Goulet + * Copyright (C) 2011 - David Goulet * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * as published by the Free Software Foundation; only version 2 + * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,83 +17,370 @@ */ #define _GNU_SOURCE -#include -#include #include #include #include +#include #include #include "lttngerr.h" #include "trace.h" -#include "session.h" /* - * find_session_ust_trace_by_pid - * - * Iterate over the session ust_traces and - * return a pointer or NULL if not found. + * Find the channel name for the given kernel session. + */ +struct ltt_kernel_channel *get_kernel_channel_by_name( + char *name, struct ltt_kernel_session *session) +{ + struct ltt_kernel_channel *chan; + + if (session == NULL) { + ERR("Undefine session"); + goto error; + } + + cds_list_for_each_entry(chan, &session->channel_list.head, list) { + if (strcmp(name, chan->channel->name) == 0) { + DBG("Found channel by name %s", name); + return chan; + } + } + +error: + return NULL; +} + +/* + * Find the event name for the given channel. */ -struct ltt_ust_trace *find_session_ust_trace_by_pid(struct ltt_session *session, pid_t pid) +struct ltt_kernel_event *get_kernel_event_by_name( + char *name, struct ltt_kernel_channel *channel) { - struct ltt_ust_trace *iter; + struct ltt_kernel_event *ev; + + if (channel == NULL) { + ERR("Undefine channel"); + goto error; + } - cds_list_for_each_entry(iter, &session->ust_traces, list) { - if (iter->pid == pid) { - /* Found */ - return iter; + cds_list_for_each_entry(ev, &channel->events_list.head, list) { + if (strcmp(name, ev->event->name) == 0) { + DBG("Found event by name %s for channel %s", name, + channel->channel->name); + return ev; } } +error: + return NULL; +} + +/* + * Allocate and initialize a kernel session data structure. + * + * Return pointer to structure or NULL. + */ +struct ltt_kernel_session *trace_create_kernel_session(void) +{ + struct ltt_kernel_session *lks; + + /* Allocate a new ltt kernel session */ + lks = malloc(sizeof(struct ltt_kernel_session)); + if (lks == NULL) { + perror("create kernel session malloc"); + goto error; + } + + /* Init data structure */ + lks->fd = 0; + lks->metadata_stream_fd = 0; + lks->channel_count = 0; + lks->stream_count_global = 0; + lks->metadata = NULL; + lks->consumer_fd = 0; + CDS_INIT_LIST_HEAD(&lks->channel_list.head); + + return lks; + +error: + return NULL; +} + +/* + * Allocate and initialize a kernel channel data structure. + * + * Return pointer to structure or NULL. + */ +struct ltt_kernel_channel *trace_create_kernel_channel(struct lttng_channel *chan, char *path) +{ + int ret; + struct ltt_kernel_channel *lkc; + + lkc = malloc(sizeof(struct ltt_kernel_channel)); + if (lkc == NULL) { + perror("ltt_kernel_channel malloc"); + goto error; + } + + lkc->channel = malloc(sizeof(struct lttng_channel)); + if (lkc->channel == NULL) { + perror("lttng_channel malloc"); + goto error; + } + memcpy(lkc->channel, chan, sizeof(struct lttng_channel)); + + lkc->fd = 0; + lkc->stream_count = 0; + lkc->event_count = 0; + lkc->enabled = 1; + lkc->ctx = NULL; + /* Init linked list */ + CDS_INIT_LIST_HEAD(&lkc->events_list.head); + CDS_INIT_LIST_HEAD(&lkc->stream_list.head); + /* Set default trace output path */ + ret = asprintf(&lkc->pathname, "%s", path); + if (ret < 0) { + perror("asprintf kernel create channel"); + goto error; + } + + return lkc; + +error: return NULL; } /* - * get_trace_count_per_session + * Allocate and initialize a kernel event. Set name and event type. * - * Return the total count of traces (ust and kernel) - * for the specified session. + * Return pointer to structure or NULL. */ -int get_trace_count_per_session(struct ltt_session *session) +struct ltt_kernel_event *trace_create_kernel_event(struct lttng_event *ev) { - return session->ust_trace_count + session->kern_trace_count; + struct ltt_kernel_event *lke; + struct lttng_kernel_event *attr; + + lke = malloc(sizeof(struct ltt_kernel_event)); + attr = malloc(sizeof(struct lttng_kernel_event)); + if (lke == NULL || attr == NULL) { + perror("kernel event malloc"); + goto error; + } + + switch (ev->type) { + case LTTNG_EVENT_PROBE: + attr->instrumentation = LTTNG_KERNEL_KPROBE; + attr->u.kprobe.addr = ev->attr.probe.addr; + attr->u.kprobe.offset = ev->attr.probe.offset; + strncpy(attr->u.kprobe.symbol_name, + ev->attr.probe.symbol_name, LTTNG_SYM_NAME_LEN); + attr->u.kprobe.symbol_name[LTTNG_SYM_NAME_LEN - 1] = '\0'; + break; + case LTTNG_EVENT_FUNCTION: + attr->instrumentation = LTTNG_KERNEL_KRETPROBE; + attr->u.kretprobe.addr = ev->attr.probe.addr; + attr->u.kretprobe.offset = ev->attr.probe.offset; + attr->u.kretprobe.offset = ev->attr.probe.offset; + strncpy(attr->u.kretprobe.symbol_name, + ev->attr.probe.symbol_name, LTTNG_SYM_NAME_LEN); + attr->u.kretprobe.symbol_name[LTTNG_SYM_NAME_LEN - 1] = '\0'; + break; + case LTTNG_EVENT_FUNCTION_ENTRY: + attr->instrumentation = LTTNG_KERNEL_FUNCTION; + strncpy(attr->u.ftrace.symbol_name, + ev->attr.ftrace.symbol_name, LTTNG_SYM_NAME_LEN); + attr->u.ftrace.symbol_name[LTTNG_SYM_NAME_LEN - 1] = '\0'; + break; + case LTTNG_EVENT_TRACEPOINT: + attr->instrumentation = LTTNG_KERNEL_TRACEPOINT; + break; + default: + ERR("Unknown kernel instrumentation type (%d)", ev->type); + goto error; + } + + /* Copy event name */ + strncpy(attr->name, ev->name, LTTNG_SYM_NAME_LEN); + attr->name[LTTNG_SYM_NAME_LEN - 1] = '\0'; + + /* Setting up a kernel event */ + lke->fd = 0; + lke->event = attr; + lke->enabled = 1; + lke->ctx = NULL; + + return lke; + +error: + return NULL; } /* - * get_traces_per_session + * Allocate and initialize a kernel metadata. * - * Fill the lttng_trace array of all the - * available trace of the session. + * Return pointer to structure or NULL. */ -void get_traces_per_session(struct ltt_session *session, struct lttng_trace *traces) +struct ltt_kernel_metadata *trace_create_kernel_metadata(char *path) { - int i = 0; - struct ltt_ust_trace *ust_iter; - struct ltt_kernel_trace *kern_iter; - struct lttng_trace trace; - - DBG("Getting userspace traces for session %s", session->name); - - /* Getting userspace traces */ - cds_list_for_each_entry(ust_iter, &session->ust_traces, list) { - trace.type = USERSPACE; - trace.pid = ust_iter->pid; - strncpy(trace.name, ust_iter->name, sizeof(trace.name)); - trace.name[sizeof(trace.name) - 1] = '\0'; - memcpy(&traces[i], &trace, sizeof(trace)); - memset(&trace, 0, sizeof(trace)); - i++; - } - - DBG("Getting kernel traces for session %s", session->name); - - /* Getting kernel traces */ - cds_list_for_each_entry(kern_iter, &session->kernel_traces, list) { - trace.type = KERNEL; - strncpy(trace.name, kern_iter->name, sizeof(trace.name)); - trace.name[sizeof(trace.name) - 1] = '\0'; - memcpy(&traces[i], &trace, sizeof(trace)); - memset(&trace, 0, sizeof(trace)); - i++; + int ret; + struct ltt_kernel_metadata *lkm; + struct lttng_channel *chan; + + lkm = malloc(sizeof(struct ltt_kernel_metadata)); + chan = malloc(sizeof(struct lttng_channel)); + if (lkm == NULL || chan == NULL) { + perror("kernel metadata malloc"); + goto error; } + + /* Set default attributes */ + chan->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE; + chan->attr.subbuf_size = DEFAULT_METADATA_SUBBUF_SIZE; + chan->attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; + chan->attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; + chan->attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; + chan->attr.output = DEFAULT_KERNEL_CHANNEL_OUTPUT; + + /* Init metadata */ + lkm->fd = 0; + lkm->conf = chan; + /* Set default metadata path */ + ret = asprintf(&lkm->pathname, "%s/metadata", path); + if (ret < 0) { + perror("asprintf kernel metadata"); + goto error; + } + + return lkm; + +error: + return NULL; +} + +/* + * Allocate and initialize a kernel stream. The stream is set to ACTIVE_FD by + * default. + * + * Return pointer to structure or NULL. + */ +struct ltt_kernel_stream *trace_create_kernel_stream(void) +{ + struct ltt_kernel_stream *lks; + + lks = malloc(sizeof(struct ltt_kernel_stream)); + if (lks == NULL) { + perror("kernel stream malloc"); + goto error; + } + + /* Init stream */ + lks->fd = 0; + lks->pathname = NULL; + lks->state = 0; + + return lks; + +error: + return NULL; +} + +/* + * Cleanup kernel stream structure. + */ +void trace_destroy_kernel_stream(struct ltt_kernel_stream *stream) +{ + DBG("[trace] Closing stream fd %d", stream->fd); + /* Close kernel fd */ + close(stream->fd); + free(stream->pathname); + + /* Remove from stream list */ + cds_list_del(&stream->list); + free(stream); +} + +/* + * Cleanup kernel event structure. + */ +void trace_destroy_kernel_event(struct ltt_kernel_event *event) +{ + DBG("[trace] Closing event fd %d", event->fd); + /* Close kernel fd */ + close(event->fd); + /* Free attributes */ + free(event->event); + + /* Remove from event list */ + cds_list_del(&event->list); + free(event); +} + +/* + * Cleanup kernel channel structure. + */ +void trace_destroy_kernel_channel(struct ltt_kernel_channel *channel) +{ + struct ltt_kernel_stream *stream, *stmp; + struct ltt_kernel_event *event, *etmp; + + DBG("[trace] Closing channel fd %d", channel->fd); + /* Close kernel fd */ + close(channel->fd); + free(channel->pathname); + /* Free attributes structure */ + free(channel->channel); + + /* For each stream in the channel list */ + cds_list_for_each_entry_safe(stream, stmp, &channel->stream_list.head, list) { + trace_destroy_kernel_stream(stream); + } + + /* For each event in the channel list */ + cds_list_for_each_entry_safe(event, etmp, &channel->events_list.head, list) { + trace_destroy_kernel_event(event); + } + + /* Remove from channel list */ + cds_list_del(&channel->list); + free(channel); +} + +/* + * Cleanup kernel metadata structure. + */ +void trace_destroy_kernel_metadata(struct ltt_kernel_metadata *metadata) +{ + DBG("[trace] Closing metadata fd %d", metadata->fd); + /* Close kernel fd */ + close(metadata->fd); + /* Free attributes */ + free(metadata->conf); + + free(metadata); +} + +/* + * Cleanup kernel session structure + */ +void trace_destroy_kernel_session(struct ltt_kernel_session *session) +{ + struct ltt_kernel_channel *channel, *ctmp; + + DBG("[trace] Closing session fd %d", session->fd); + /* Close kernel fds */ + close(session->fd); + if (session->metadata_stream_fd != 0) { + DBG("[trace] Closing metadata stream fd %d", session->metadata_stream_fd); + close(session->metadata_stream_fd); + } + + if (session->metadata != NULL) { + trace_destroy_kernel_metadata(session->metadata); + } + + cds_list_for_each_entry_safe(channel, ctmp, &session->channel_list.head, list) { + trace_destroy_kernel_channel(channel); + } + + free(session); }