X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=lttng-events.c;h=fb45c612f9fed2cf6c7310f704d549fe335260d8;hb=b53047135828b997a4eeb2cae7344cb169aa9c8c;hp=1ccbffd67fe60a961de18cf6b4c58d7334d1c155;hpb=d1f652f8d4f6d1de8f6d32ae8711d6469c38892c;p=lttng-modules.git diff --git a/lttng-events.c b/lttng-events.c index 1ccbffd6..fb45c612 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) +/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only) * * lttng-events.c * @@ -7,12 +7,6 @@ * Copyright (C) 2010-2012 Mathieu Desnoyers */ -/* - * This page_alloc.h wrapper needs to be included before gfpflags.h because it - * overrides a function with a define. - */ -#include "wrapper/page_alloc.h" - #include #include #include @@ -23,26 +17,23 @@ #include #include #include -#include #include #include -#include #include #include - -#include /* for wrapper_vmalloc_sync_all() */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define METADATA_CACHE_DEFAULT_SIZE 4096 @@ -70,27 +61,17 @@ int _lttng_session_metadata_statedump(struct lttng_session *session); static void _lttng_metadata_channel_hangup(struct lttng_metadata_stream *stream); static +int _lttng_type_statedump(struct lttng_session *session, + const struct lttng_type *type, + size_t nesting); +static int _lttng_field_statedump(struct lttng_session *session, const struct lttng_event_field *field, size_t nesting); 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(); -#endif -#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) */ -#ifdef CONFIG_PREEMPT_RT - synchronize_rcu(); -#endif -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) */ } void lttng_lock_sessions(void) @@ -124,12 +105,13 @@ struct lttng_session *lttng_session_create(void) int i; mutex_lock(&sessions_mutex); - session = lttng_kvzalloc(sizeof(struct lttng_session), GFP_KERNEL); + session = kvzalloc_node(sizeof(struct lttng_session), GFP_KERNEL, + NUMA_NO_NODE); if (!session) goto err; INIT_LIST_HEAD(&session->chan); INIT_LIST_HEAD(&session->events); - uuid_le_gen(&session->uuid); + guid_gen(&session->uuid); metadata_cache = kzalloc(sizeof(struct lttng_metadata_cache), GFP_KERNEL); @@ -167,7 +149,7 @@ struct lttng_session *lttng_session_create(void) err_free_cache: kfree(metadata_cache); err_free_session: - lttng_kvfree(session); + kvfree(session); err: mutex_unlock(&sessions_mutex); return NULL; @@ -220,7 +202,7 @@ void lttng_session_destroy(struct lttng_session *session) kref_put(&session->metadata_cache->refcount, metadata_cache_destroy); list_del(&session->list); mutex_unlock(&sessions_mutex); - lttng_kvfree(session); + kvfree(session); } int lttng_session_statedump(struct lttng_session *session) @@ -415,7 +397,6 @@ int lttng_event_enable(struct lttng_event *event) ret = -EINVAL; break; case LTTNG_KERNEL_KPROBE: - case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_NOOP: WRITE_ONCE(event->enabled, 1); @@ -423,6 +404,7 @@ int lttng_event_enable(struct lttng_event *event) case LTTNG_KERNEL_KRETPROBE: ret = lttng_kretprobes_event_enable_state(event, 1); break; + case LTTNG_KERNEL_FUNCTION: /* Fall-through. */ default: WARN_ON_ONCE(1); ret = -EINVAL; @@ -451,7 +433,6 @@ int lttng_event_disable(struct lttng_event *event) ret = -EINVAL; break; case LTTNG_KERNEL_KPROBE: - case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_NOOP: WRITE_ONCE(event->enabled, 0); @@ -459,6 +440,7 @@ int lttng_event_disable(struct lttng_event *event) case LTTNG_KERNEL_KRETPROBE: ret = lttng_kretprobes_event_enable_state(event, 0); break; + case LTTNG_KERNEL_FUNCTION: /* Fall-through. */ default: WARN_ON_ONCE(1); ret = -EINVAL; @@ -601,11 +583,11 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_KRETPROBE: - case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_SYSCALL: event_name = event_param->name; break; + case LTTNG_KERNEL_FUNCTION: /* Fall-through. */ default: WARN_ON_ONCE(1); ret = -EINVAL; @@ -614,7 +596,7 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, name_len = strlen(event_name); hash = jhash(event_name, name_len, 0); head = &session->events_ht.table[hash & (LTTNG_EVENT_HT_SIZE - 1)]; - lttng_hlist_for_each_entry(event, head, hlist) { + hlist_for_each_entry(event, head, hlist) { WARN_ON_ONCE(!event->desc); if (!strncmp(event->desc->name, event_name, LTTNG_KERNEL_SYM_NAME_LEN - 1) @@ -728,27 +710,6 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, list_add(&event_return->list, &chan->session->events); break; } - case LTTNG_KERNEL_FUNCTION: - /* - * 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_ftrace_register(event_name, - event_param->u.ftrace.symbol_name, - event); - if (ret) { - goto register_error; - } - ret = try_module_get(event->desc->owner); - WARN_ON_ONCE(!ret); - break; case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_SYSCALL: /* @@ -785,6 +746,7 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, ret = try_module_get(event->desc->owner); WARN_ON_ONCE(!ret); break; + case LTTNG_KERNEL_FUNCTION: /* Fall-through */ default: WARN_ON_ONCE(1); ret = -EINVAL; @@ -838,9 +800,9 @@ void register_event(struct lttng_event *event) desc = event->desc; switch (event->instrumentation) { case LTTNG_KERNEL_TRACEPOINT: - ret = lttng_wrapper_tracepoint_probe_register(desc->kname, - desc->probe_callback, - event); + ret = lttng_tracepoint_probe_register(desc->kname, + desc->probe_callback, + event); break; case LTTNG_KERNEL_SYSCALL: ret = lttng_syscall_filter_enable(event->chan, @@ -849,10 +811,10 @@ void register_event(struct lttng_event *event) case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_KRETPROBE: - case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: ret = 0; break; + case LTTNG_KERNEL_FUNCTION: /* Fall-through */ default: WARN_ON_ONCE(1); } @@ -874,7 +836,7 @@ int _lttng_event_unregister(struct lttng_event *event) desc = event->desc; switch (event->instrumentation) { case LTTNG_KERNEL_TRACEPOINT: - ret = lttng_wrapper_tracepoint_probe_unregister(event->desc->kname, + ret = lttng_tracepoint_probe_unregister(event->desc->kname, event->desc->probe_callback, event); break; @@ -886,10 +848,6 @@ int _lttng_event_unregister(struct lttng_event *event) lttng_kretprobes_unregister(event); ret = 0; break; - case LTTNG_KERNEL_FUNCTION: - lttng_ftrace_unregister(event); - ret = 0; - break; case LTTNG_KERNEL_SYSCALL: ret = lttng_syscall_filter_disable(event->chan, desc->name); @@ -901,6 +859,7 @@ int _lttng_event_unregister(struct lttng_event *event) lttng_uprobes_unregister(event); ret = 0; break; + case LTTNG_KERNEL_FUNCTION: /* Fall-through */ default: WARN_ON_ONCE(1); } @@ -927,10 +886,6 @@ void _lttng_event_destroy(struct lttng_event *event) module_put(event->desc->owner); lttng_kretprobes_destroy_private(event); break; - case LTTNG_KERNEL_FUNCTION: - module_put(event->desc->owner); - lttng_ftrace_destroy_private(event); - break; case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_SYSCALL: break; @@ -938,6 +893,7 @@ void _lttng_event_destroy(struct lttng_event *event) module_put(event->desc->owner); lttng_uprobes_destroy_private(event); break; + case LTTNG_KERNEL_FUNCTION: /* Fall-through */ default: WARN_ON_ONCE(1); } @@ -1026,7 +982,7 @@ void *id_list_start(struct seq_file *m, loff_t *pos) for (i = 0; i < LTTNG_ID_TABLE_SIZE; i++) { struct hlist_head *head = &id_tracker_p->id_hash[i]; - lttng_hlist_for_each_entry(e, head, hlist) { + hlist_for_each_entry(e, head, hlist) { if (iter++ >= *pos) return e; } @@ -1056,7 +1012,7 @@ void *id_list_next(struct seq_file *m, void *p, loff_t *ppos) for (i = 0; i < LTTNG_ID_TABLE_SIZE; i++) { struct hlist_head *head = &id_tracker_p->id_hash[i]; - lttng_hlist_for_each_entry(e, head, hlist) { + hlist_for_each_entry(e, head, hlist) { if (iter++ >= *ppos) return e; } @@ -1161,7 +1117,7 @@ int lttng_session_list_tracker_ids(struct lttng_session *session, struct seq_file *m; int file_fd, ret; - file_fd = lttng_get_unused_fd(); + file_fd = get_unused_fd_flags(0); if (file_fd < 0) { ret = file_fd; goto fd_error; @@ -1206,8 +1162,8 @@ static int lttng_match_enabler_star_glob(const char *desc_name, const char *pattern) { - if (!strutils_star_glob_match(pattern, LTTNG_SIZE_MAX, - desc_name, LTTNG_SIZE_MAX)) + if (!strutils_star_glob_match(pattern, SIZE_MAX, + desc_name, SIZE_MAX)) return 0; return 1; } @@ -1323,7 +1279,7 @@ void lttng_create_tracepoint_if_missing(struct lttng_enabler *enabler) */ hash = jhash(event_name, name_len, 0); head = &session->events_ht.table[hash & (LTTNG_EVENT_HT_SIZE - 1)]; - lttng_hlist_for_each_entry(event, head, hlist) { + hlist_for_each_entry(event, head, hlist) { if (event->desc == desc && event->chan == enabler->chan) found = 1; @@ -1779,6 +1735,45 @@ int print_tabs(struct lttng_session *session, size_t nesting) return 0; } +static +int lttng_field_name_statedump(struct lttng_session *session, + const struct lttng_event_field *field, + size_t nesting) +{ + return lttng_metadata_printf(session, " _%s;\n", field->name); +} + +static +int _lttng_integer_type_statedump(struct lttng_session *session, + const struct lttng_type *type, + size_t nesting) +{ + int ret; + + WARN_ON_ONCE(type->atype != atype_integer); + ret = print_tabs(session, nesting); + if (ret) + return ret; + ret = lttng_metadata_printf(session, + "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s }", + type->u.integer.size, + type->u.integer.alignment, + type->u.integer.signedness, + (type->u.integer.encoding == lttng_encode_none) + ? "none" + : (type->u.integer.encoding == lttng_encode_UTF8) + ? "UTF8" + : "ASCII", + type->u.integer.base, +#if __BYTE_ORDER == __BIG_ENDIAN + type->u.integer.reverse_byte_order ? " byte_order = le;" : "" +#else + type->u.integer.reverse_byte_order ? " byte_order = be;" : "" +#endif + ); + return ret; +} + /* * Must be called with sessions_mutex held. */ @@ -1789,6 +1784,9 @@ int _lttng_struct_type_statedump(struct lttng_session *session, { int ret; uint32_t i, nr_fields; + unsigned int alignment; + + WARN_ON_ONCE(type->atype != atype_struct_nestable); ret = print_tabs(session, nesting); if (ret) @@ -1797,11 +1795,11 @@ int _lttng_struct_type_statedump(struct lttng_session *session, "struct {\n"); if (ret) return ret; - nr_fields = type->u._struct.nr_fields; + nr_fields = type->u.struct_nestable.nr_fields; for (i = 0; i < nr_fields; i++) { const struct lttng_event_field *iter_field; - iter_field = &type->u._struct.fields[i]; + iter_field = &type->u.struct_nestable.fields[i]; ret = _lttng_field_statedump(session, iter_field, nesting + 1); if (ret) return ret; @@ -1809,8 +1807,15 @@ int _lttng_struct_type_statedump(struct lttng_session *session, ret = print_tabs(session, nesting); if (ret) return ret; - ret = lttng_metadata_printf(session, - "}"); + alignment = type->u.struct_nestable.alignment; + if (alignment) { + ret = lttng_metadata_printf(session, + "} align(%u)", + alignment); + } else { + ret = lttng_metadata_printf(session, + "}"); + } return ret; } @@ -1818,7 +1823,7 @@ int _lttng_struct_type_statedump(struct lttng_session *session, * Must be called with sessions_mutex held. */ static -int _lttng_struct_statedump(struct lttng_session *session, +int _lttng_struct_field_statedump(struct lttng_session *session, const struct lttng_event_field *field, size_t nesting) { @@ -1828,10 +1833,7 @@ int _lttng_struct_statedump(struct lttng_session *session, &field->type, nesting); if (ret) return ret; - ret = lttng_metadata_printf(session, - "_%s;\n", - field->name); - return ret; + return lttng_field_name_statedump(session, field, nesting); } /* @@ -1845,19 +1847,25 @@ int _lttng_variant_type_statedump(struct lttng_session *session, int ret; uint32_t i, nr_choices; + WARN_ON_ONCE(type->atype != atype_variant_nestable); + /* + * CTF 1.8 does not allow expressing nonzero variant alignment in a nestable way. + */ + if (type->u.variant_nestable.alignment != 0) + return -EINVAL; ret = print_tabs(session, nesting); if (ret) return ret; ret = lttng_metadata_printf(session, "variant <_%s> {\n", - type->u.variant.tag_name); + type->u.variant_nestable.tag_name); if (ret) return ret; - nr_choices = type->u.variant.nr_choices; + nr_choices = type->u.variant_nestable.nr_choices; for (i = 0; i < nr_choices; i++) { const struct lttng_event_field *iter_field; - iter_field = &type->u.variant.choices[i]; + iter_field = &type->u.variant_nestable.choices[i]; ret = _lttng_field_statedump(session, iter_field, nesting + 1); if (ret) return ret; @@ -1874,7 +1882,7 @@ int _lttng_variant_type_statedump(struct lttng_session *session, * Must be called with sessions_mutex held. */ static -int _lttng_variant_statedump(struct lttng_session *session, +int _lttng_variant_field_statedump(struct lttng_session *session, const struct lttng_event_field *field, size_t nesting) { @@ -1884,43 +1892,54 @@ int _lttng_variant_statedump(struct lttng_session *session, &field->type, nesting); if (ret) return ret; - ret = lttng_metadata_printf(session, - "_%s;\n", - field->name); - return ret; + return lttng_field_name_statedump(session, field, nesting); } /* * Must be called with sessions_mutex held. */ static -int _lttng_array_compound_statedump(struct lttng_session *session, +int _lttng_array_field_statedump(struct lttng_session *session, const struct lttng_event_field *field, size_t nesting) { int ret; const struct lttng_type *elem_type; - /* Only array of structures and variants are currently supported. */ - elem_type = field->type.u.array_compound.elem_type; - switch (elem_type->atype) { - case atype_struct: - ret = _lttng_struct_type_statedump(session, elem_type, nesting); + WARN_ON_ONCE(field->type.atype != atype_array_nestable); + + if (field->type.u.array_nestable.alignment) { + ret = print_tabs(session, nesting); if (ret) return ret; - break; - case atype_variant: - ret = _lttng_variant_type_statedump(session, elem_type, nesting); + ret = lttng_metadata_printf(session, + "struct { } align(%u) _%s_padding;\n", + field->type.u.array_nestable.alignment * CHAR_BIT, + field->name); + if (ret) + return ret; + } + /* + * Nested compound types: Only array of structures and variants are + * currently supported. + */ + elem_type = field->type.u.array_nestable.elem_type; + switch (elem_type->atype) { + case atype_integer: + case atype_struct_nestable: + case atype_variant_nestable: + ret = _lttng_type_statedump(session, elem_type, nesting); if (ret) return ret; break; + default: return -EINVAL; } ret = lttng_metadata_printf(session, " _%s[%u];\n", field->name, - field->type.u.array_compound.length); + field->type.u.array_nestable.length); return ret; } @@ -1928,7 +1947,7 @@ int _lttng_array_compound_statedump(struct lttng_session *session, * Must be called with sessions_mutex held. */ static -int _lttng_sequence_compound_statedump(struct lttng_session *session, +int _lttng_sequence_field_statedump(struct lttng_session *session, const struct lttng_event_field *field, size_t nesting) { @@ -1936,28 +1955,43 @@ int _lttng_sequence_compound_statedump(struct lttng_session *session, const char *length_name; const struct lttng_type *elem_type; - length_name = field->type.u.sequence_compound.length_name; + WARN_ON_ONCE(field->type.atype != atype_sequence_nestable); - /* Only array of structures and variants are currently supported. */ - elem_type = field->type.u.sequence_compound.elem_type; - switch (elem_type->atype) { - case atype_struct: - ret = _lttng_struct_type_statedump(session, elem_type, nesting); + length_name = field->type.u.sequence_nestable.length_name; + + if (field->type.u.sequence_nestable.alignment) { + ret = print_tabs(session, nesting); if (ret) return ret; - break; - case atype_variant: - ret = _lttng_variant_type_statedump(session, elem_type, nesting); + ret = lttng_metadata_printf(session, + "struct { } align(%u) _%s_padding;\n", + field->type.u.sequence_nestable.alignment * CHAR_BIT, + field->name); + if (ret) + return ret; + } + + /* + * Nested compound types: Only array of structures and variants are + * currently supported. + */ + elem_type = field->type.u.sequence_nestable.elem_type; + switch (elem_type->atype) { + case atype_integer: + case atype_struct_nestable: + case atype_variant_nestable: + ret = _lttng_type_statedump(session, elem_type, nesting); if (ret) return ret; break; + default: return -EINVAL; } ret = lttng_metadata_printf(session, " _%s[ _%s ];\n", field->name, - length_name); + field->type.u.sequence_nestable.length_name); return ret; } @@ -1965,41 +1999,35 @@ int _lttng_sequence_compound_statedump(struct lttng_session *session, * Must be called with sessions_mutex held. */ static -int _lttng_enum_statedump(struct lttng_session *session, - const struct lttng_event_field *field, +int _lttng_enum_type_statedump(struct lttng_session *session, + const struct lttng_type *type, size_t nesting) { const struct lttng_enum_desc *enum_desc; - const struct lttng_integer_type *container_type; + const struct lttng_type *container_type; int ret; unsigned int i, nr_entries; - enum_desc = field->type.u.basic.enumeration.desc; - container_type = &field->type.u.basic.enumeration.container_type; + container_type = type->u.enum_nestable.container_type; + if (container_type->atype != atype_integer) { + ret = -EINVAL; + goto end; + } + enum_desc = type->u.enum_nestable.desc; nr_entries = enum_desc->nr_entries; ret = print_tabs(session, nesting); if (ret) goto end; - ret = lttng_metadata_printf(session, - "enum : integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } {\n", - container_type->size, - container_type->alignment, - container_type->signedness, - (container_type->encoding == lttng_encode_none) - ? "none" - : (container_type->encoding == lttng_encode_UTF8) - ? "UTF8" - : "ASCII", - container_type->base, -#if __BYTE_ORDER == __BIG_ENDIAN - container_type->reverse_byte_order ? " byte_order = le;" : "" -#else - container_type->reverse_byte_order ? " byte_order = be;" : "" -#endif - ); + ret = lttng_metadata_printf(session, "enum : "); + if (ret) + goto end; + ret = _lttng_integer_type_statedump(session, container_type, 0); + if (ret) + goto end; + ret = lttng_metadata_printf(session, " {\n"); if (ret) - goto end; + goto end; /* Dump all entries */ for (i = 0; i < nr_entries; i++) { const struct lttng_enum_entry *entry = &enum_desc->entries[i]; @@ -2078,8 +2106,7 @@ int _lttng_enum_statedump(struct lttng_session *session, ret = print_tabs(session, nesting); if (ret) goto end; - ret = lttng_metadata_printf(session, "} _%s;\n", - field->name); + ret = lttng_metadata_printf(session, "}"); end: return ret; } @@ -2088,165 +2115,132 @@ end: * Must be called with sessions_mutex held. */ static -int _lttng_field_statedump(struct lttng_session *session, +int _lttng_enum_field_statedump(struct lttng_session *session, + const struct lttng_event_field *field, + size_t nesting) +{ + int ret; + + ret = _lttng_enum_type_statedump(session, &field->type, nesting); + if (ret) + return ret; + return lttng_field_name_statedump(session, field, nesting); +} + +static +int _lttng_integer_field_statedump(struct lttng_session *session, const struct lttng_event_field *field, size_t nesting) +{ + int ret; + + ret = _lttng_integer_type_statedump(session, &field->type, nesting); + if (ret) + return ret; + return lttng_field_name_statedump(session, field, nesting); +} + +static +int _lttng_string_type_statedump(struct lttng_session *session, + const struct lttng_type *type, + size_t nesting) +{ + int ret; + + WARN_ON_ONCE(type->atype != atype_string); + /* Default encoding is UTF8 */ + ret = print_tabs(session, nesting); + if (ret) + return ret; + ret = lttng_metadata_printf(session, + "string%s", + type->u.string.encoding == lttng_encode_ASCII ? + " { encoding = ASCII; }" : ""); + return ret; +} + +static +int _lttng_string_field_statedump(struct lttng_session *session, + const struct lttng_event_field *field, + size_t nesting) +{ + int ret; + + WARN_ON_ONCE(field->type.atype != atype_string); + ret = _lttng_string_type_statedump(session, &field->type, nesting); + if (ret) + return ret; + return lttng_field_name_statedump(session, field, nesting); +} + +/* + * Must be called with sessions_mutex held. + */ +static +int _lttng_type_statedump(struct lttng_session *session, + const struct lttng_type *type, + size_t nesting) { int ret = 0; - switch (field->type.atype) { + switch (type->atype) { case atype_integer: - ret = print_tabs(session, nesting); - if (ret) - return ret; - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n", - field->type.u.basic.integer.size, - field->type.u.basic.integer.alignment, - field->type.u.basic.integer.signedness, - (field->type.u.basic.integer.encoding == lttng_encode_none) - ? "none" - : (field->type.u.basic.integer.encoding == lttng_encode_UTF8) - ? "UTF8" - : "ASCII", - field->type.u.basic.integer.base, -#if __BYTE_ORDER == __BIG_ENDIAN - field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", -#else - field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", -#endif - field->name); + ret = _lttng_integer_type_statedump(session, type, nesting); break; - case atype_enum: - ret = _lttng_enum_statedump(session, field, nesting); + case atype_enum_nestable: + ret = _lttng_enum_type_statedump(session, type, nesting); break; - case atype_array: - case atype_array_bitfield: - { - const struct lttng_basic_type *elem_type; - - elem_type = &field->type.u.array.elem_type; - if (field->type.u.array.elem_alignment) { - ret = print_tabs(session, nesting); - if (ret) - return ret; - ret = lttng_metadata_printf(session, - "struct { } align(%u) _%s_padding;\n", - field->type.u.array.elem_alignment * CHAR_BIT, - field->name); - if (ret) - return ret; - } - ret = print_tabs(session, nesting); - if (ret) - return ret; - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", - elem_type->u.basic.integer.size, - elem_type->u.basic.integer.alignment, - elem_type->u.basic.integer.signedness, - (elem_type->u.basic.integer.encoding == lttng_encode_none) - ? "none" - : (elem_type->u.basic.integer.encoding == lttng_encode_UTF8) - ? "UTF8" - : "ASCII", - elem_type->u.basic.integer.base, -#if __BYTE_ORDER == __BIG_ENDIAN - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", -#else - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", -#endif - field->name, field->type.u.array.length); + case atype_string: + ret = _lttng_string_type_statedump(session, type, nesting); + break; + case atype_struct_nestable: + ret = _lttng_struct_type_statedump(session, type, nesting); + break; + case atype_variant_nestable: + ret = _lttng_variant_type_statedump(session, type, nesting); break; + + /* Nested arrays and sequences are not supported yet. */ + case atype_array_nestable: + case atype_sequence_nestable: + default: + WARN_ON_ONCE(1); + return -EINVAL; } - case atype_sequence: - case atype_sequence_bitfield: - { - const struct lttng_basic_type *elem_type; - const struct lttng_basic_type *length_type; + return ret; +} - elem_type = &field->type.u.sequence.elem_type; - length_type = &field->type.u.sequence.length_type; - ret = print_tabs(session, nesting); - if (ret) - return ret; - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n", - length_type->u.basic.integer.size, - (unsigned int) length_type->u.basic.integer.alignment, - length_type->u.basic.integer.signedness, - (length_type->u.basic.integer.encoding == lttng_encode_none) - ? "none" - : ((length_type->u.basic.integer.encoding == lttng_encode_UTF8) - ? "UTF8" - : "ASCII"), - length_type->u.basic.integer.base, -#if __BYTE_ORDER == __BIG_ENDIAN - length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", -#else - length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", -#endif - field->name); - if (ret) - return ret; +/* + * Must be called with sessions_mutex held. + */ +static +int _lttng_field_statedump(struct lttng_session *session, + const struct lttng_event_field *field, + size_t nesting) +{ + int ret = 0; - if (field->type.u.sequence.elem_alignment) { - ret = print_tabs(session, nesting); - if (ret) - return ret; - ret = lttng_metadata_printf(session, - "struct { } align(%u) _%s_padding;\n", - field->type.u.sequence.elem_alignment * CHAR_BIT, - field->name); - if (ret) - return ret; - } - ret = print_tabs(session, nesting); - if (ret) - return ret; - ret = lttng_metadata_printf(session, - "integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n", - elem_type->u.basic.integer.size, - (unsigned int) elem_type->u.basic.integer.alignment, - elem_type->u.basic.integer.signedness, - (elem_type->u.basic.integer.encoding == lttng_encode_none) - ? "none" - : ((elem_type->u.basic.integer.encoding == lttng_encode_UTF8) - ? "UTF8" - : "ASCII"), - elem_type->u.basic.integer.base, -#if __BYTE_ORDER == __BIG_ENDIAN - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", -#else - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", -#endif - field->name, - field->name); + switch (field->type.atype) { + case atype_integer: + ret = _lttng_integer_field_statedump(session, field, nesting); + break; + case atype_enum_nestable: + ret = _lttng_enum_field_statedump(session, field, nesting); break; - } - case atype_string: - /* Default encoding is UTF8 */ - ret = print_tabs(session, nesting); - if (ret) - return ret; - ret = lttng_metadata_printf(session, - "string%s _%s;\n", - field->type.u.basic.string.encoding == lttng_encode_ASCII ? - " { encoding = ASCII; }" : "", - field->name); + ret = _lttng_string_field_statedump(session, field, nesting); break; - case atype_struct: - ret = _lttng_struct_statedump(session, field, nesting); + case atype_struct_nestable: + ret = _lttng_struct_field_statedump(session, field, nesting); break; - case atype_array_compound: - ret = _lttng_array_compound_statedump(session, field, nesting); + case atype_array_nestable: + ret = _lttng_array_field_statedump(session, field, nesting); break; - case atype_sequence_compound: - ret = _lttng_sequence_compound_statedump(session, field, nesting); + case atype_sequence_nestable: + ret = _lttng_sequence_field_statedump(session, field, nesting); break; - case atype_variant: - ret = _lttng_variant_statedump(session, field, nesting); + case atype_variant_nestable: + ret = _lttng_variant_field_statedump(session, field, nesting); break; default: @@ -2483,6 +2477,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) @@ -2490,13 +2487,13 @@ 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; + struct timespec64 rts = { 0, 0 }; /* Disable interrupts to increase correlation precision. */ local_irq_save(flags); monotonic[0] = trace_clock_read64(); - getnstimeofday(&rts); + ktime_get_real_ts64(&rts); monotonic[1] = trace_clock_read64(); local_irq_restore(flags); @@ -2517,7 +2514,7 @@ int64_t measure_clock_offset(void) static int print_escaped_ctf_string(struct lttng_session *session, const char *string) { - int ret; + int ret = 0; size_t i; char cur; @@ -2577,7 +2574,7 @@ static int _lttng_session_metadata_statedump(struct lttng_session *session) { unsigned char *uuid_c = session->uuid.b; - unsigned char uuid_s[37], clock_uuid_s[BOOT_ID_LEN]; + unsigned char uuid_s[LTTNG_MODULES_UUID_STR_LEN], clock_uuid_s[LTTNG_MODULES_UUID_STR_LEN]; const char *product_uuid; struct lttng_channel *chan; struct lttng_event *event; @@ -2765,22 +2762,10 @@ end: * @transport: transport structure * * Registers a transport which can be used as output to extract the data out of - * LTTng. The module calling this registration function must ensure that no - * trap-inducing code will be executed by the transport functions. E.g. - * vmalloc_sync_all() must be called between a vmalloc and the moment the memory - * is made visible to the transport function. This registration acts as a - * vmalloc_sync_all. Therefore, only if the module allocates virtual memory - * after its registration must it synchronize the TLBs. + * LTTng. */ void lttng_transport_register(struct lttng_transport *transport) { - /* - * Make sure no page fault can be triggered by the module about to be - * registered. We deal with this here so we don't have to call - * vmalloc_sync_all() in each module's init. - */ - wrapper_vmalloc_sync_all(); - mutex_lock(&sessions_mutex); list_add_tail(&transport->node, <tng_transport_list); mutex_unlock(&sessions_mutex); @@ -2799,8 +2784,6 @@ void lttng_transport_unregister(struct lttng_transport *transport) } EXPORT_SYMBOL_GPL(lttng_transport_unregister); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - enum cpuhp_state lttng_hp_prepare; enum cpuhp_state lttng_hp_online; @@ -2915,30 +2898,10 @@ static void __exit lttng_exit_cpu_hotplug(void) cpuhp_remove_multi_state(lttng_hp_prepare); } -#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ -static int lttng_init_cpu_hotplug(void) -{ - return 0; -} -static void lttng_exit_cpu_hotplug(void) -{ -} -#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) */ - - static int __init lttng_events_init(void) { int ret; - ret = wrapper_lttng_fixup_sig(THIS_MODULE); - if (ret) - return ret; - ret = wrapper_get_pfnblock_flags_mask_init(); - if (ret) - return ret; - ret = wrapper_get_pageblock_flags_mask_init(); - if (ret) - return ret; ret = lttng_probes_init(); if (ret) return ret;