X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Ftrace-kernel.c;h=044fc98d2510ddd17c1bb36353e99f9780b8d933;hp=54bdc667575ec48a0b2d5ac3fadcc999148150ae;hb=d42266a417afa6e8ca6024590b8282002aebca07;hpb=df3c77c8dbbd102718f7149b075ba026d70a9e27 diff --git a/src/bin/lttng-sessiond/trace-kernel.c b/src/bin/lttng-sessiond/trace-kernel.c index 54bdc6675..044fc98d2 100644 --- a/src/bin/lttng-sessiond/trace-kernel.c +++ b/src/bin/lttng-sessiond/trace-kernel.c @@ -1,18 +1,8 @@ /* - * 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, version 2 only, - * as published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0-only * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _LGPL_SOURCE @@ -21,8 +11,15 @@ #include #include +#include +#include +#include +#include + #include #include +#include +#include #include "consumer.h" #include "trace-kernel.h" @@ -33,7 +30,7 @@ * Find the channel name for the given kernel session. */ struct ltt_kernel_channel *trace_kernel_get_channel_by_name( - char *name, struct ltt_kernel_session *session) + const char *name, struct ltt_kernel_session *session) { struct ltt_kernel_channel *chan; @@ -158,6 +155,30 @@ struct ltt_kernel_session *trace_kernel_create_session(void) lks->metadata = NULL; CDS_INIT_LIST_HEAD(&lks->channel_list.head); + lks->tracker_pid = process_attr_tracker_create(); + if (!lks->tracker_pid) { + goto error; + } + lks->tracker_vpid = process_attr_tracker_create(); + if (!lks->tracker_vpid) { + goto error; + } + lks->tracker_uid = process_attr_tracker_create(); + if (!lks->tracker_uid) { + goto error; + } + lks->tracker_vuid = process_attr_tracker_create(); + if (!lks->tracker_vuid) { + goto error; + } + lks->tracker_gid = process_attr_tracker_create(); + if (!lks->tracker_gid) { + goto error; + } + lks->tracker_vgid = process_attr_tracker_create(); + if (!lks->tracker_vgid) { + goto error; + } lks->consumer = consumer_create_output(CONSUMER_DST_LOCAL); if (lks->consumer == NULL) { goto error; @@ -166,6 +187,12 @@ struct ltt_kernel_session *trace_kernel_create_session(void) return lks; error: + process_attr_tracker_destroy(lks->tracker_pid); + process_attr_tracker_destroy(lks->tracker_vpid); + process_attr_tracker_destroy(lks->tracker_uid); + process_attr_tracker_destroy(lks->tracker_vuid); + process_attr_tracker_destroy(lks->tracker_gid); + process_attr_tracker_destroy(lks->tracker_vgid); free(lks); alloc_error: @@ -292,18 +319,23 @@ error: * * Return pointer to structure or NULL. */ -struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev, - char *filter_expression, struct lttng_filter_bytecode *filter) +enum lttng_error_code trace_kernel_create_event( + struct lttng_event *ev, char *filter_expression, + struct lttng_filter_bytecode *filter, + struct ltt_kernel_event **kernel_event) { - struct ltt_kernel_event *lke; + enum lttng_error_code ret; struct lttng_kernel_event *attr; + struct ltt_kernel_event *local_kernel_event; + struct lttng_userspace_probe_location *userspace_probe_location = NULL; assert(ev); - lke = zmalloc(sizeof(struct ltt_kernel_event)); + local_kernel_event = zmalloc(sizeof(struct ltt_kernel_event)); attr = zmalloc(sizeof(struct lttng_kernel_event)); - if (lke == NULL || attr == NULL) { + if (local_kernel_event == NULL || attr == NULL) { PERROR("kernel event zmalloc"); + ret = LTTNG_ERR_NOMEM; goto error; } @@ -316,6 +348,84 @@ struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev, ev->attr.probe.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); attr->u.kprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; break; + case LTTNG_EVENT_USERSPACE_PROBE: + { + const struct lttng_userspace_probe_location* location = NULL; + const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; + + location = lttng_event_get_userspace_probe_location(ev); + if (!location) { + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto error; + } + + /* + * From this point on, the specific term 'uprobe' is used + * instead of the generic 'userspace probe' because it's the + * technology used at the moment for this instrumentation. + * LTTng currently implements userspace probes using uprobes. + * In the interactions with the kernel tracer, we use the + * uprobe term. + */ + attr->instrumentation = LTTNG_KERNEL_UPROBE; + + /* + * Only the elf lookup method is supported at the moment. + */ + lookup = lttng_userspace_probe_location_get_lookup_method( + location); + if (!lookup) { + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto error; + } + + /* + * From the kernel tracer's perspective, all userspace probe + * event types are all the same: a file and an offset. + */ + switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) { + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: + /* Get the file descriptor on the target binary. */ + attr->u.uprobe.fd = + lttng_userspace_probe_location_function_get_binary_fd(location); + + /* + * Save a reference to the probe location used during + * the listing of events. Close its FD since it won't + * be needed for listing. + */ + userspace_probe_location = + lttng_userspace_probe_location_copy(location); + ret = lttng_userspace_probe_location_function_set_binary_fd( + userspace_probe_location, -1); + if (ret) { + goto error; + } + break; + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: + /* Get the file descriptor on the target binary. */ + attr->u.uprobe.fd = + lttng_userspace_probe_location_tracepoint_get_binary_fd(location); + + /* + * Save a reference to the probe location used during the listing of + * events. Close its FD since it won't be needed for listing. + */ + userspace_probe_location = + lttng_userspace_probe_location_copy(location); + ret = lttng_userspace_probe_location_tracepoint_set_binary_fd( + userspace_probe_location, -1); + if (ret) { + goto error; + } + break; + default: + DBG("Unsupported lookup method type"); + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto error; + } + break; + } case LTTNG_EVENT_FUNCTION: attr->instrumentation = LTTNG_KERNEL_KRETPROBE; attr->u.kretprobe.addr = ev->attr.probe.addr; @@ -341,6 +451,7 @@ struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev, break; default: ERR("Unknown kernel instrumentation type (%d)", ev->type); + ret = LTTNG_ERR_INVALID; goto error; } @@ -349,20 +460,23 @@ struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev, attr->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; /* Setting up a kernel event */ - lke->fd = -1; - lke->event = attr; - lke->enabled = 1; - lke->filter_expression = filter_expression; - lke->filter = filter; + local_kernel_event->fd = -1; + local_kernel_event->event = attr; + local_kernel_event->enabled = 1; + local_kernel_event->filter_expression = filter_expression; + local_kernel_event->filter = filter; + local_kernel_event->userspace_probe_location = userspace_probe_location; + + *kernel_event = local_kernel_event; - return lke; + return LTTNG_OK; error: free(filter_expression); free(filter); - free(lke); + free(local_kernel_event); free(attr); - return NULL; + return ret; } /* @@ -372,6 +486,7 @@ error: */ struct ltt_kernel_metadata *trace_kernel_create_metadata(void) { + int ret; struct ltt_kernel_metadata *lkm; struct lttng_channel *chan; @@ -382,13 +497,38 @@ struct ltt_kernel_metadata *trace_kernel_create_metadata(void) goto error; } + ret = lttng_strncpy( + chan->name, DEFAULT_METADATA_NAME, sizeof(chan->name)); + if (ret) { + ERR("Failed to initialize metadata channel name to `%s`", + DEFAULT_METADATA_NAME); + goto error; + } + /* Set default attributes */ - chan->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE; + chan->attr.overwrite = DEFAULT_METADATA_OVERWRITE; chan->attr.subbuf_size = default_get_metadata_subbuf_size(); chan->attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; - chan->attr.switch_timer_interval = DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER; - chan->attr.read_timer_interval = DEFAULT_KERNEL_CHANNEL_READ_TIMER; - chan->attr.output = DEFAULT_KERNEL_CHANNEL_OUTPUT; + chan->attr.switch_timer_interval = DEFAULT_METADATA_SWITCH_TIMER; + chan->attr.read_timer_interval = DEFAULT_METADATA_READ_TIMER;; + + + /* + * The metadata channel of kernel sessions must use the "mmap" + * back-end since the consumer daemon accumulates complete + * metadata units before sending them to the relay daemon in + * live mode. The consumer daemon also needs to extract the contents + * of the metadata cache when computing a rotation position. + * + * In both cases, it is not possible to rely on the splice + * back-end as the consumer daemon may need to accumulate more + * content than can be backed by the ring buffer's underlying + * pages. + */ + chan->attr.output = LTTNG_EVENT_MMAP; + chan->attr.tracefile_size = 0; + chan->attr.tracefile_count = 0; + chan->attr.live_timer_interval = 0; /* Init metadata */ lkm->fd = -1; @@ -501,7 +641,9 @@ void trace_kernel_destroy_context(struct ltt_kernel_context *ctx) { assert(ctx); - cds_list_del(&ctx->list); + if (ctx->in_list) { + cds_list_del(&ctx->list); + } free(ctx); } @@ -549,7 +691,7 @@ void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel) && channel->published_to_notification_thread) { status = notification_thread_command_remove_channel( notification_thread_handle, - channel->fd, LTTNG_DOMAIN_KERNEL); + channel->key, LTTNG_DOMAIN_KERNEL); assert(status == LTTNG_OK); } free(channel->channel->attr.extended.ptr); @@ -615,9 +757,20 @@ void trace_kernel_destroy_session(struct ltt_kernel_session *session) cds_list_for_each_entry_safe(channel, ctmp, &session->channel_list.head, list) { trace_kernel_destroy_channel(channel); } +} +/* Free elements needed by destroy notifiers. */ +void trace_kernel_free_session(struct ltt_kernel_session *session) +{ /* Wipe consumer output object */ consumer_output_put(session->consumer); + process_attr_tracker_destroy(session->tracker_pid); + process_attr_tracker_destroy(session->tracker_vpid); + process_attr_tracker_destroy(session->tracker_uid); + process_attr_tracker_destroy(session->tracker_vuid); + process_attr_tracker_destroy(session->tracker_gid); + process_attr_tracker_destroy(session->tracker_vgid); + free(session); }