X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=lttng-events.c;h=21c41133b859623e6a5ea63c65927021cb646171;hb=1b25fe5879436a90fd22a731e9d3371807e78ba1;hp=b748cce62c8f464f8743f5794d50ee927fa0c57e;hpb=f513b2bf88afa9a36a725fbf8e91e3a3f3efebc9;p=lttng-modules.git diff --git a/lttng-events.c b/lttng-events.c index b748cce6..21c41133 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -46,12 +46,16 @@ #include #include #include +#include #include #include #include #include #include +#include #include +#include +#include #define METADATA_CACHE_DEFAULT_SIZE 4096 @@ -128,7 +132,7 @@ struct lttng_session *lttng_session_create(void) int i; mutex_lock(&sessions_mutex); - session = kzalloc(sizeof(struct lttng_session), GFP_KERNEL); + session = lttng_kvzalloc(sizeof(struct lttng_session), GFP_KERNEL); if (!session) goto err; INIT_LIST_HEAD(&session->chan); @@ -159,7 +163,7 @@ struct lttng_session *lttng_session_create(void) err_free_cache: kfree(metadata_cache); err_free_session: - kfree(session); + lttng_kvfree(session); err: mutex_unlock(&sessions_mutex); return NULL; @@ -208,7 +212,17 @@ 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); - kfree(session); + lttng_kvfree(session); +} + +int lttng_session_statedump(struct lttng_session *session) +{ + int ret; + + mutex_lock(&sessions_mutex); + ret = lttng_statedump_start(session); + mutex_unlock(&sessions_mutex); + return ret; } int lttng_session_enable(struct lttng_session *session) @@ -241,6 +255,12 @@ int lttng_session_enable(struct lttng_session *session) /* We need to sync enablers with session before activation. */ lttng_session_sync_enablers(session); + /* Clear each stream's quiescent state. */ + list_for_each_entry(chan, &session->chan, list) { + if (chan->channel_type != METADATA_CHANNEL) + lib_ring_buffer_clear_quiescent_channel(chan->chan); + } + ACCESS_ONCE(session->active) = 1; ACCESS_ONCE(session->been_active) = 1; ret = _lttng_session_metadata_statedump(session); @@ -259,6 +279,7 @@ end: int lttng_session_disable(struct lttng_session *session) { int ret = 0; + struct lttng_channel *chan; mutex_lock(&sessions_mutex); if (!session->active) { @@ -270,6 +291,12 @@ int lttng_session_disable(struct lttng_session *session) /* Set transient enabler state to "disabled" */ session->tstate = 0; lttng_session_sync_enablers(session); + + /* Set each stream's quiescent state. */ + list_for_each_entry(chan, &session->chan, list) { + if (chan->channel_type != METADATA_CHANNEL) + lib_ring_buffer_set_quiescent_channel(chan->chan); + } end: mutex_unlock(&sessions_mutex); return ret; @@ -1117,11 +1144,11 @@ fd_error: * Enabler management. */ static -int lttng_match_enabler_wildcard(const char *desc_name, - const char *name) +int lttng_match_enabler_star_glob(const char *desc_name, + const char *pattern) { - /* Compare excluding final '*' */ - if (strncmp(desc_name, name, strlen(name) - 1)) + if (!strutils_star_glob_match(pattern, LTTNG_SIZE_MAX, + desc_name, LTTNG_SIZE_MAX)) return 0; return 1; } @@ -1166,8 +1193,8 @@ int lttng_desc_match_enabler(const struct lttng_event_desc *desc, return -EINVAL; } switch (enabler->type) { - case LTTNG_ENABLER_WILDCARD: - return lttng_match_enabler_wildcard(desc_name, enabler_name); + case LTTNG_ENABLER_STAR_GLOB: + return lttng_match_enabler_star_glob(desc_name, enabler_name); case LTTNG_ENABLER_NAME: return lttng_match_enabler_name(desc_name, enabler_name); default: @@ -1736,6 +1763,62 @@ int _lttng_struct_statedump(struct lttng_session *session, return ret; } +/* + * Must be called with sessions_mutex held. + */ +static +int _lttng_variant_type_statedump(struct lttng_session *session, + const struct lttng_type *type, + size_t nesting) +{ + int ret; + uint32_t i, nr_choices; + + ret = print_tabs(session, nesting); + if (ret) + return ret; + ret = lttng_metadata_printf(session, + "variant <_%s> {\n", + type->u.variant.tag_name); + if (ret) + return ret; + nr_choices = type->u.variant.nr_choices; + for (i = 0; i < nr_choices; i++) { + const struct lttng_event_field *iter_field; + + iter_field = &type->u.variant.choices[i]; + ret = _lttng_field_statedump(session, iter_field, nesting + 1); + if (ret) + return ret; + } + ret = print_tabs(session, nesting); + if (ret) + return ret; + ret = lttng_metadata_printf(session, + "}"); + return ret; +} + +/* + * Must be called with sessions_mutex held. + */ +static +int _lttng_variant_statedump(struct lttng_session *session, + const struct lttng_event_field *field, + size_t nesting) +{ + int ret; + + ret = _lttng_variant_type_statedump(session, + &field->type, nesting); + if (ret) + return ret; + ret = lttng_metadata_printf(session, + "_%s;\n", + field->name); + return ret; +} + /* * Must be called with sessions_mutex held. */ @@ -1747,7 +1830,7 @@ int _lttng_array_compound_statedump(struct lttng_session *session, int ret; const struct lttng_type *elem_type; - /* Only array of structures are currently supported. */ + /* 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: @@ -1755,6 +1838,11 @@ int _lttng_array_compound_statedump(struct lttng_session *session, if (ret) return ret; break; + case atype_variant: + ret = _lttng_variant_type_statedump(session, elem_type, nesting); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -1779,7 +1867,7 @@ int _lttng_sequence_compound_statedump(struct lttng_session *session, length_name = field->type.u.sequence_compound.length_name; - /* Only array of structures are currently supported. */ + /* 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: @@ -1787,6 +1875,11 @@ int _lttng_sequence_compound_statedump(struct lttng_session *session, if (ret) return ret; break; + case atype_variant: + ret = _lttng_variant_type_statedump(session, elem_type, nesting); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -1797,6 +1890,129 @@ int _lttng_sequence_compound_statedump(struct lttng_session *session, return ret; } +/* + * Must be called with sessions_mutex held. + */ +static +int _lttng_enum_statedump(struct lttng_session *session, + const struct lttng_event_field *field, + size_t nesting) +{ + const struct lttng_enum_desc *enum_desc; + const struct lttng_integer_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; + 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 + ); + if (ret) + goto end; + /* Dump all entries */ + for (i = 0; i < nr_entries; i++) { + const struct lttng_enum_entry *entry = &enum_desc->entries[i]; + int j, len; + + ret = print_tabs(session, nesting + 1); + if (ret) + goto end; + ret = lttng_metadata_printf(session, + "\""); + if (ret) + goto end; + len = strlen(entry->string); + /* Escape the character '"' */ + for (j = 0; j < len; j++) { + char c = entry->string[j]; + + switch (c) { + case '"': + ret = lttng_metadata_printf(session, + "\\\""); + break; + case '\\': + ret = lttng_metadata_printf(session, + "\\\\"); + break; + default: + ret = lttng_metadata_printf(session, + "%c", c); + break; + } + if (ret) + goto end; + } + ret = lttng_metadata_printf(session, "\""); + if (ret) + goto end; + + if (entry->options.is_auto) { + ret = lttng_metadata_printf(session, ",\n"); + if (ret) + goto end; + } else { + ret = lttng_metadata_printf(session, + " = "); + if (ret) + goto end; + if (entry->start.signedness) + ret = lttng_metadata_printf(session, + "%lld", (long long) entry->start.value); + else + ret = lttng_metadata_printf(session, + "%llu", entry->start.value); + if (ret) + goto end; + if (entry->start.signedness == entry->end.signedness && + entry->start.value + == entry->end.value) { + ret = lttng_metadata_printf(session, + ",\n"); + } else { + if (entry->end.signedness) { + ret = lttng_metadata_printf(session, + " ... %lld,\n", + (long long) entry->end.value); + } else { + ret = lttng_metadata_printf(session, + " ... %llu,\n", + entry->end.value); + } + } + if (ret) + goto end; + } + } + ret = print_tabs(session, nesting); + if (ret) + goto end; + ret = lttng_metadata_printf(session, "} _%s;\n", + field->name); +end: + return ret; +} + /* * Must be called with sessions_mutex held. */ @@ -1831,13 +2047,7 @@ int _lttng_field_statedump(struct lttng_session *session, field->name); break; case atype_enum: - ret = print_tabs(session, nesting); - if (ret) - return ret; - ret = lttng_metadata_printf(session, - "%s _%s;\n", - field->type.u.basic.enumeration.name, - field->name); + ret = _lttng_enum_statedump(session, field, nesting); break; case atype_array: { @@ -1962,6 +2172,9 @@ int _lttng_field_statedump(struct lttng_session *session, case atype_sequence_compound: ret = _lttng_sequence_compound_statedump(session, field, nesting); break; + case atype_variant: + ret = _lttng_variant_statedump(session, field, nesting); + break; default: WARN_ON_ONCE(1); @@ -2210,7 +2423,7 @@ int64_t measure_clock_offset(void) /* Disable interrupts to increase correlation precision. */ local_irq_save(flags); monotonic[0] = trace_clock_read64(); - getnstimeofday(&rts); + getnstimeofday(&rts); monotonic[1] = trace_clock_read64(); local_irq_restore(flags); @@ -2433,6 +2646,133 @@ void lttng_transport_unregister(struct lttng_transport *transport) } EXPORT_SYMBOL_GPL(lttng_transport_unregister); +#if (defined(CONFIG_HOTPLUG_CPU) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0))) + +enum cpuhp_state lttng_hp_prepare; +enum cpuhp_state lttng_hp_online; + +static int lttng_hotplug_prepare(unsigned int cpu, struct hlist_node *node) +{ + struct lttng_cpuhp_node *lttng_node; + + lttng_node = container_of(node, struct lttng_cpuhp_node, node); + switch (lttng_node->component) { + case LTTNG_RING_BUFFER_FRONTEND: + return 0; + case LTTNG_RING_BUFFER_BACKEND: + return lttng_cpuhp_rb_backend_prepare(cpu, lttng_node); + case LTTNG_RING_BUFFER_ITER: + return 0; + case LTTNG_CONTEXT_PERF_COUNTERS: + return 0; + default: + return -EINVAL; + } +} + +static int lttng_hotplug_dead(unsigned int cpu, struct hlist_node *node) +{ + struct lttng_cpuhp_node *lttng_node; + + lttng_node = container_of(node, struct lttng_cpuhp_node, node); + switch (lttng_node->component) { + case LTTNG_RING_BUFFER_FRONTEND: + return lttng_cpuhp_rb_frontend_dead(cpu, lttng_node); + case LTTNG_RING_BUFFER_BACKEND: + return 0; + case LTTNG_RING_BUFFER_ITER: + return 0; + case LTTNG_CONTEXT_PERF_COUNTERS: + return lttng_cpuhp_perf_counter_dead(cpu, lttng_node); + default: + return -EINVAL; + } +} + +static int lttng_hotplug_online(unsigned int cpu, struct hlist_node *node) +{ + struct lttng_cpuhp_node *lttng_node; + + lttng_node = container_of(node, struct lttng_cpuhp_node, node); + switch (lttng_node->component) { + case LTTNG_RING_BUFFER_FRONTEND: + return lttng_cpuhp_rb_frontend_online(cpu, lttng_node); + case LTTNG_RING_BUFFER_BACKEND: + return 0; + case LTTNG_RING_BUFFER_ITER: + return lttng_cpuhp_rb_iter_online(cpu, lttng_node); + case LTTNG_CONTEXT_PERF_COUNTERS: + return lttng_cpuhp_perf_counter_online(cpu, lttng_node); + default: + return -EINVAL; + } +} + +static int lttng_hotplug_offline(unsigned int cpu, struct hlist_node *node) +{ + struct lttng_cpuhp_node *lttng_node; + + lttng_node = container_of(node, struct lttng_cpuhp_node, node); + switch (lttng_node->component) { + case LTTNG_RING_BUFFER_FRONTEND: + return lttng_cpuhp_rb_frontend_offline(cpu, lttng_node); + case LTTNG_RING_BUFFER_BACKEND: + return 0; + case LTTNG_RING_BUFFER_ITER: + return 0; + case LTTNG_CONTEXT_PERF_COUNTERS: + return 0; + default: + return -EINVAL; + } +} + +static int __init lttng_init_cpu_hotplug(void) +{ + int ret; + + ret = cpuhp_setup_state_multi(CPUHP_BP_PREPARE_DYN, "lttng:prepare", + lttng_hotplug_prepare, + lttng_hotplug_dead); + if (ret < 0) { + return ret; + } + lttng_hp_prepare = ret; + lttng_rb_set_hp_prepare(ret); + + ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "lttng:online", + lttng_hotplug_online, + lttng_hotplug_offline); + if (ret < 0) { + cpuhp_remove_multi_state(lttng_hp_prepare); + lttng_hp_prepare = 0; + return ret; + } + lttng_hp_online = ret; + lttng_rb_set_hp_online(ret); + + return 0; +} + +static void __exit lttng_exit_cpu_hotplug(void) +{ + lttng_rb_set_hp_online(0); + cpuhp_remove_multi_state(lttng_hp_online); + lttng_rb_set_hp_prepare(0); + cpuhp_remove_multi_state(lttng_hp_prepare); +} + +#else /* #if (CONFIG_HOTPLUG_CPU && (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 (CONFIG_HOTPLUG_CPU && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0))) */ + + static int __init lttng_events_init(void) { int ret; @@ -2444,6 +2784,9 @@ static int __init lttng_events_init(void) if (ret) return ret; ret = wrapper_get_pageblock_flags_mask_init(); + if (ret) + return ret; + ret = lttng_probes_init(); if (ret) return ret; ret = lttng_context_init(); @@ -2463,8 +2806,19 @@ static int __init lttng_events_init(void) ret = lttng_logger_init(); if (ret) goto error_logger; + ret = lttng_init_cpu_hotplug(); + if (ret) + goto error_hotplug; + printk(KERN_NOTICE "LTTng: Loaded modules v%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); return 0; +error_hotplug: + lttng_logger_exit(); error_logger: lttng_abi_exit(); error_abi: @@ -2473,6 +2827,12 @@ 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", + __stringify(LTTNG_MODULES_MAJOR_VERSION), + __stringify(LTTNG_MODULES_MINOR_VERSION), + __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION), + LTTNG_MODULES_EXTRAVERSION, + LTTNG_VERSION_NAME); return ret; } @@ -2482,6 +2842,7 @@ static void __exit lttng_events_exit(void) { struct lttng_session *session, *tmpsession; + lttng_exit_cpu_hotplug(); lttng_logger_exit(); lttng_abi_exit(); list_for_each_entry_safe(session, tmpsession, &sessions, list) @@ -2489,6 +2850,12 @@ 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", + __stringify(LTTNG_MODULES_MAJOR_VERSION), + __stringify(LTTNG_MODULES_MINOR_VERSION), + __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION), + LTTNG_MODULES_EXTRAVERSION, + LTTNG_VERSION_NAME); } module_exit(lttng_events_exit);