X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=lttng-events.c;h=1308d949f73460e9b4fb13291828d67a7015a985;hb=858dfdcae1b1a73b9dfa6612ab49ad791708cf13;hp=2cd650fdf2c4ebed8fe9438273c728abb38d1d54;hpb=894ce5dc825733d1ccab25b1aede9ce0be2a7c4e;p=lttng-modules.git diff --git a/lttng-events.c b/lttng-events.c index 2cd650fd..1308d949 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -1,23 +1,10 @@ -/* +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * * lttng-events.c * * Holds LTTng per-session event registry. * * Copyright (C) 2010-2012 Mathieu Desnoyers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; only - * version 2.1 of the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* @@ -56,6 +43,7 @@ #include #include #include +#include #define METADATA_CACHE_DEFAULT_SIZE 4096 @@ -89,7 +77,12 @@ int _lttng_field_statedump(struct lttng_session *session, void synchronize_trace(void) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,1,0)) + synchronize_rcu(); +#else synchronize_sched(); +#endif + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) #ifdef CONFIG_PREEMPT_RT_FULL synchronize_rcu(); @@ -408,6 +401,7 @@ int lttng_event_enable(struct lttng_event *event) break; case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_FUNCTION: + case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_NOOP: WRITE_ONCE(event->enabled, 1); break; @@ -443,6 +437,7 @@ int lttng_event_disable(struct lttng_event *event) break; case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_FUNCTION: + case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_NOOP: WRITE_ONCE(event->enabled, 0); break; @@ -589,6 +584,7 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, event_name = event_desc->name; break; case LTTNG_KERNEL_KPROBE: + case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_KRETPROBE: case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: @@ -752,6 +748,28 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, goto register_error; } break; + case LTTNG_KERNEL_UPROBE: + /* + * Needs to be explicitly enabled after creation, since + * we may want to apply filters. + */ + event->enabled = 0; + event->registered = 1; + + /* + * Populate lttng_event structure before event + * registration. + */ + smp_wmb(); + + ret = lttng_uprobes_register(event_param->name, + event_param->u.uprobe.fd, + event); + if (ret) + goto register_error; + ret = try_module_get(event->desc->owner); + WARN_ON_ONCE(!ret); + break; default: WARN_ON_ONCE(1); ret = -EINVAL; @@ -814,6 +832,7 @@ void register_event(struct lttng_event *event) desc->name); break; case LTTNG_KERNEL_KPROBE: + case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_KRETPROBE: case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: @@ -863,6 +882,10 @@ int _lttng_event_unregister(struct lttng_event *event) case LTTNG_KERNEL_NOOP: ret = 0; break; + case LTTNG_KERNEL_UPROBE: + lttng_uprobes_unregister(event); + ret = 0; + break; default: WARN_ON_ONCE(1); } @@ -896,6 +919,10 @@ void _lttng_event_destroy(struct lttng_event *event) case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_SYSCALL: break; + case LTTNG_KERNEL_UPROBE: + module_put(event->desc->owner); + lttng_uprobes_destroy_private(event); + break; default: WARN_ON_ONCE(1); } @@ -1115,8 +1142,8 @@ int lttng_session_list_tracker_pids(struct lttng_session *session) ret = PTR_ERR(tracker_pids_list_file); goto file_error; } - if (atomic_long_add_unless(&session->file->f_count, - 1, INT_MAX) == INT_MAX) { + if (!atomic_long_add_unless(&session->file->f_count, 1, LONG_MAX)) { + ret = -EOVERFLOW; goto refcount_error; } ret = lttng_tracker_pids_list_fops.open(NULL, tracker_pids_list_file); @@ -1445,6 +1472,18 @@ error_free: return ret; } +int lttng_event_add_callsite(struct lttng_event *event, + struct lttng_kernel_event_callsite __user *callsite) +{ + + switch (event->instrumentation) { + case LTTNG_KERNEL_UPROBE: + return lttng_uprobes_add_callsite(event, callsite); + default: + return -EINVAL; + } +} + int lttng_enabler_attach_context(struct lttng_enabler *enabler, struct lttng_kernel_context *context_param) { @@ -2048,6 +2087,7 @@ int _lttng_field_statedump(struct lttng_session *session, ret = _lttng_enum_statedump(session, field, nesting); break; case atype_array: + case atype_array_bitfield: { const struct lttng_basic_type *elem_type; @@ -2086,6 +2126,7 @@ int _lttng_field_statedump(struct lttng_session *session, break; } case atype_sequence: + case atype_sequence_bitfield: { const struct lttng_basic_type *elem_type; const struct lttng_basic_type *length_type; @@ -2408,6 +2449,9 @@ int _lttng_event_header_declare(struct lttng_session *session) * in future versions. * This function may return a negative offset. It may happen if the * system sets the REALTIME clock to 0 after boot. + * + * Use 64bit timespec on kernels that have it, this makes 32bit arch + * y2038 compliant. */ static int64_t measure_clock_offset(void) @@ -2415,13 +2459,21 @@ int64_t measure_clock_offset(void) uint64_t monotonic_avg, monotonic[2], realtime; uint64_t tcf = trace_clock_freq(); int64_t offset; - struct timespec rts = { 0, 0 }; unsigned long flags; +#ifdef LTTNG_KERNEL_HAS_TIMESPEC64 + struct timespec64 rts = { 0, 0 }; +#else + struct timespec rts = { 0, 0 }; +#endif /* Disable interrupts to increase correlation precision. */ local_irq_save(flags); monotonic[0] = trace_clock_read64(); +#ifdef LTTNG_KERNEL_HAS_TIMESPEC64 + ktime_get_real_ts64(&rts); +#else getnstimeofday(&rts); +#endif monotonic[1] = trace_clock_read64(); local_irq_restore(flags); @@ -2439,6 +2491,61 @@ int64_t measure_clock_offset(void) return offset; } +static +int print_escaped_ctf_string(struct lttng_session *session, const char *string) +{ + int ret; + size_t i; + char cur; + + i = 0; + cur = string[i]; + while (cur != '\0') { + switch (cur) { + case '\n': + ret = lttng_metadata_printf(session, "%s", "\\n"); + break; + case '\\': + case '"': + ret = lttng_metadata_printf(session, "%c", '\\'); + if (ret) + goto error; + /* We still print the current char */ + /* Fallthrough */ + default: + ret = lttng_metadata_printf(session, "%c", cur); + break; + } + + if (ret) + goto error; + + cur = string[++i]; + } +error: + return ret; +} + +static +int print_metadata_escaped_field(struct lttng_session *session, const char *field, + const char *field_value) +{ + int ret; + + ret = lttng_metadata_printf(session, " %s = \"", field); + if (ret) + goto error; + + ret = print_escaped_ctf_string(session, field_value); + if (ret) + goto error; + + ret = lttng_metadata_printf(session, "\";\n"); + +error: + return ret; +} + /* * Output metadata into this session's metadata buffers. * Must be called with sessions_mutex held. @@ -2514,7 +2621,7 @@ int _lttng_session_metadata_statedump(struct lttng_session *session) " tracer_major = %d;\n" " tracer_minor = %d;\n" " tracer_patchlevel = %d;\n" - "};\n\n", + " trace_buffering_scheme = \"global\";\n", current->nsproxy->uts_ns->name.nodename, utsname()->sysname, utsname()->release, @@ -2526,6 +2633,19 @@ int _lttng_session_metadata_statedump(struct lttng_session *session) if (ret) goto end; + ret = print_metadata_escaped_field(session, "trace_name", session->name); + if (ret) + goto end; + ret = print_metadata_escaped_field(session, "trace_creation_datetime", + session->creation_time); + if (ret) + goto end; + + /* Close env */ + ret = lttng_metadata_printf(session, "};\n\n"); + if (ret) + goto end; + ret = lttng_metadata_printf(session, "clock {\n" " name = \"%s\";\n", @@ -2760,7 +2880,7 @@ static void __exit lttng_exit_cpu_hotplug(void) cpuhp_remove_multi_state(lttng_hp_prepare); } -#else /* #if (CONFIG_HOTPLUG_CPU && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0))) */ +#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ static int lttng_init_cpu_hotplug(void) { return 0; @@ -2768,7 +2888,7 @@ static int lttng_init_cpu_hotplug(void) static void lttng_exit_cpu_hotplug(void) { } -#endif /* #else #if (CONFIG_HOTPLUG_CPU && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0))) */ +#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ static int __init lttng_events_init(void) @@ -2807,12 +2927,22 @@ static int __init lttng_events_init(void) ret = lttng_init_cpu_hotplug(); if (ret) goto error_hotplug; - printk(KERN_NOTICE "LTTng: Loaded modules v%s.%s.%s%s (%s)\n", + printk(KERN_NOTICE "LTTng: Loaded modules v%s.%s.%s%s (%s)%s%s\n", __stringify(LTTNG_MODULES_MAJOR_VERSION), __stringify(LTTNG_MODULES_MINOR_VERSION), __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION), LTTNG_MODULES_EXTRAVERSION, - LTTNG_VERSION_NAME); + LTTNG_VERSION_NAME, +#ifdef LTTNG_EXTRA_VERSION_GIT + LTTNG_EXTRA_VERSION_GIT[0] == '\0' ? "" : " - " LTTNG_EXTRA_VERSION_GIT, +#else + "", +#endif +#ifdef LTTNG_EXTRA_VERSION_NAME + LTTNG_EXTRA_VERSION_NAME[0] == '\0' ? "" : " - " LTTNG_EXTRA_VERSION_NAME); +#else + ""); +#endif return 0; error_hotplug: @@ -2825,12 +2955,22 @@ error_kmem: lttng_tracepoint_exit(); error_tp: lttng_context_exit(); - printk(KERN_NOTICE "LTTng: Failed to load modules v%s.%s.%s%s (%s)\n", + printk(KERN_NOTICE "LTTng: Failed to load modules v%s.%s.%s%s (%s)%s%s\n", __stringify(LTTNG_MODULES_MAJOR_VERSION), __stringify(LTTNG_MODULES_MINOR_VERSION), __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION), LTTNG_MODULES_EXTRAVERSION, - LTTNG_VERSION_NAME); + LTTNG_VERSION_NAME, +#ifdef LTTNG_EXTRA_VERSION_GIT + LTTNG_EXTRA_VERSION_GIT[0] == '\0' ? "" : " - " LTTNG_EXTRA_VERSION_GIT, +#else + "", +#endif +#ifdef LTTNG_EXTRA_VERSION_NAME + LTTNG_EXTRA_VERSION_NAME[0] == '\0' ? "" : " - " LTTNG_EXTRA_VERSION_NAME); +#else + ""); +#endif return ret; } @@ -2848,19 +2988,36 @@ static void __exit lttng_events_exit(void) kmem_cache_destroy(event_cache); lttng_tracepoint_exit(); lttng_context_exit(); - printk(KERN_NOTICE "LTTng: Unloaded modules v%s.%s.%s%s (%s)\n", + printk(KERN_NOTICE "LTTng: Unloaded modules v%s.%s.%s%s (%s)%s%s\n", __stringify(LTTNG_MODULES_MAJOR_VERSION), __stringify(LTTNG_MODULES_MINOR_VERSION), __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION), LTTNG_MODULES_EXTRAVERSION, - LTTNG_VERSION_NAME); + LTTNG_VERSION_NAME, +#ifdef LTTNG_EXTRA_VERSION_GIT + LTTNG_EXTRA_VERSION_GIT[0] == '\0' ? "" : " - " LTTNG_EXTRA_VERSION_GIT, +#else + "", +#endif +#ifdef LTTNG_EXTRA_VERSION_NAME + LTTNG_EXTRA_VERSION_NAME[0] == '\0' ? "" : " - " LTTNG_EXTRA_VERSION_NAME); +#else + ""); +#endif } module_exit(lttng_events_exit); +#include "extra_version/patches.i" +#ifdef LTTNG_EXTRA_VERSION_GIT +MODULE_INFO(extra_version_git, LTTNG_EXTRA_VERSION_GIT); +#endif +#ifdef LTTNG_EXTRA_VERSION_NAME +MODULE_INFO(extra_version_name, LTTNG_EXTRA_VERSION_NAME); +#endif MODULE_LICENSE("GPL and additional rights"); MODULE_AUTHOR("Mathieu Desnoyers "); -MODULE_DESCRIPTION("LTTng Events"); +MODULE_DESCRIPTION("LTTng tracer"); MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "." __stringify(LTTNG_MODULES_MINOR_VERSION) "." __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)