X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-registry.c;h=93131abaae1b8a1474591441b662a590111cf8d0;hp=3c3aa91f02ce1b0a4719bdc982af80e22bc3fd8c;hb=a0377dfefe40662ba7d68617bce6ff467114136c;hpb=602766ecff63f7ea4267336ba85fe969283bb212 diff --git a/src/bin/lttng-sessiond/ust-registry.c b/src/bin/lttng-sessiond/ust-registry.c index 3c3aa91f0..93131abaa 100644 --- a/src/bin/lttng-sessiond/ust-registry.c +++ b/src/bin/lttng-sessiond/ust-registry.c @@ -1,22 +1,11 @@ /* - * Copyright (C) 2013 - David Goulet + * Copyright (C) 2013 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 -#include #include #include @@ -25,34 +14,61 @@ #include "ust-registry.h" #include "ust-app.h" +#include "ust-field-utils.h" #include "utils.h" +#include "lttng-sessiond.h" +#include "notification-thread-commands.h" + /* * Hash table match function for event in the registry. */ static int ht_match_event(struct cds_lfht_node *node, const void *_key) { - struct ust_registry_event *event; const struct ust_registry_event *key; + struct ust_registry_event *event; + int i; - assert(node); - assert(_key); + LTTNG_ASSERT(node); + LTTNG_ASSERT(_key); event = caa_container_of(node, struct ust_registry_event, node.node); - assert(event); + LTTNG_ASSERT(event); key = _key; - /* It has to be a perfect match. */ + /* It has to be a perfect match. First, compare the event names. */ if (strncmp(event->name, key->name, sizeof(event->name))) { goto no_match; } - /* It has to be a perfect match. */ - if (strncmp(event->signature, key->signature, - strlen(event->signature))) { + /* Compare log levels. */ + if (event->loglevel_value != key->loglevel_value) { + goto no_match; + } + + /* Compare the number of fields. */ + if (event->nr_fields != key->nr_fields) { goto no_match; } + /* Compare each field individually. */ + for (i = 0; i < event->nr_fields; i++) { + if (!match_lttng_ust_ctl_field(&event->fields[i], &key->fields[i])) { + goto no_match; + } + } + + /* Compare model URI. */ + if (event->model_emf_uri != NULL && key->model_emf_uri == NULL) { + goto no_match; + } else if(event->model_emf_uri == NULL && key->model_emf_uri != NULL) { + goto no_match; + } else if (event->model_emf_uri != NULL && key->model_emf_uri != NULL) { + if (strcmp(event->model_emf_uri, key->model_emf_uri)) { + goto no_match; + } + } + /* Match */ return 1; @@ -60,17 +76,16 @@ no_match: return 0; } -static unsigned long ht_hash_event(void *_key, unsigned long seed) +static unsigned long ht_hash_event(const void *_key, unsigned long seed) { - uint64_t xored_key; - struct ust_registry_event *key = _key; + uint64_t hashed_key; + const struct ust_registry_event *key = _key; - assert(key); + LTTNG_ASSERT(key); - xored_key = (uint64_t) (hash_key_str(key->name, seed) ^ - hash_key_str(key->signature, seed)); + hashed_key = (uint64_t) hash_key_str(key->name, seed); - return hash_key_u64(&xored_key, seed); + return hash_key_u64(&hashed_key, seed); } static int compare_enums(const struct ust_registry_enum *reg_enum_a, @@ -79,13 +94,13 @@ static int compare_enums(const struct ust_registry_enum *reg_enum_a, int ret = 0; size_t i; - assert(strcmp(reg_enum_a->name, reg_enum_b->name) == 0); + LTTNG_ASSERT(strcmp(reg_enum_a->name, reg_enum_b->name) == 0); if (reg_enum_a->nr_entries != reg_enum_b->nr_entries) { ret = -1; goto end; } for (i = 0; i < reg_enum_a->nr_entries; i++) { - const struct ustctl_enum_entry *entries_a, *entries_b; + const struct lttng_ust_ctl_enum_entry *entries_a, *entries_b; entries_a = ®_enum_a->entries[i]; entries_b = ®_enum_b->entries[i]; @@ -125,15 +140,15 @@ static int ht_match_enum(struct cds_lfht_node *node, const void *_key) struct ust_registry_enum *_enum; const struct ust_registry_enum *key; - assert(node); - assert(_key); + LTTNG_ASSERT(node); + LTTNG_ASSERT(_key); _enum = caa_container_of(node, struct ust_registry_enum, node.node); - assert(_enum); + LTTNG_ASSERT(_enum); key = _key; - if (strncmp(_enum->name, key->name, LTTNG_UST_SYM_NAME_LEN)) { + if (strncmp(_enum->name, key->name, LTTNG_UST_ABI_SYM_NAME_LEN)) { goto no_match; } if (compare_enums(_enum, key)) { @@ -156,11 +171,11 @@ static int ht_match_enum_id(struct cds_lfht_node *node, const void *_key) struct ust_registry_enum *_enum; const struct ust_registry_enum *key = _key; - assert(node); - assert(_key); + LTTNG_ASSERT(node); + LTTNG_ASSERT(_key); _enum = caa_container_of(node, struct ust_registry_enum, node.node); - assert(_enum); + LTTNG_ASSERT(_enum); if (_enum->id != key->id) { goto no_match; @@ -181,7 +196,7 @@ static unsigned long ht_hash_enum(void *_key, unsigned long seed) { struct ust_registry_enum *key = _key; - assert(key); + LTTNG_ASSERT(key); return hash_key_str(key->name, seed); } @@ -193,35 +208,46 @@ static unsigned long ht_hash_enum(void *_key, unsigned long seed) * trace reader. */ static -int validate_event_field(struct ustctl_field *field, +int validate_event_field(struct lttng_ust_ctl_field *field, const char *event_name, struct ust_app *app) { int ret = 0; switch(field->type.atype) { - case ustctl_atype_integer: - case ustctl_atype_enum: - case ustctl_atype_array: - case ustctl_atype_sequence: - case ustctl_atype_string: - case ustctl_atype_variant: + case lttng_ust_ctl_atype_integer: + case lttng_ust_ctl_atype_enum: + case lttng_ust_ctl_atype_array: + case lttng_ust_ctl_atype_sequence: + case lttng_ust_ctl_atype_string: + case lttng_ust_ctl_atype_variant: + case lttng_ust_ctl_atype_array_nestable: + case lttng_ust_ctl_atype_sequence_nestable: + case lttng_ust_ctl_atype_enum_nestable: + case lttng_ust_ctl_atype_variant_nestable: break; - case ustctl_atype_struct: - if (field->type.u._struct.nr_fields != 0) { + case lttng_ust_ctl_atype_struct: + if (field->type.u.legacy._struct.nr_fields != 0) { + WARN("Unsupported non-empty struct field."); + ret = -EINVAL; + goto end; + } + break; + case lttng_ust_ctl_atype_struct_nestable: + if (field->type.u.struct_nestable.nr_fields != 0) { WARN("Unsupported non-empty struct field."); ret = -EINVAL; goto end; } break; - case ustctl_atype_float: - switch (field->type.u.basic._float.mant_dig) { + case lttng_ust_ctl_atype_float: + switch (field->type.u._float.mant_dig) { case 0: WARN("UST application '%s' (pid: %d) has unknown float mantissa '%u' " "in field '%s', rejecting event '%s'", app->name, app->pid, - field->type.u.basic._float.mant_dig, + field->type.u._float.mant_dig, field->name, event_name); ret = -EINVAL; @@ -240,7 +266,7 @@ end: } static -int validate_event_fields(size_t nr_fields, struct ustctl_field *fields, +int validate_event_fields(size_t nr_fields, struct lttng_ust_ctl_field *fields, const char *event_name, struct ust_app *app) { unsigned int i; @@ -258,7 +284,7 @@ int validate_event_fields(size_t nr_fields, struct ustctl_field *fields, */ static struct ust_registry_event *alloc_event(int session_objd, int channel_objd, char *name, char *sig, size_t nr_fields, - struct ustctl_field *fields, int loglevel_value, + struct lttng_ust_ctl_field *fields, int loglevel_value, char *model_emf_uri, struct ust_app *app) { struct ust_registry_event *event = NULL; @@ -340,9 +366,9 @@ struct ust_registry_event *ust_registry_find_event( struct ust_registry_event *event = NULL; struct ust_registry_event key; - assert(chan); - assert(name); - assert(sig); + LTTNG_ASSERT(chan); + LTTNG_ASSERT(name); + LTTNG_ASSERT(sig); /* Setup key for the match function. */ strncpy(key.name, name, sizeof(key.name)); @@ -373,7 +399,7 @@ end: */ int ust_registry_create_event(struct ust_registry_session *session, uint64_t chan_key, int session_objd, int channel_objd, char *name, - char *sig, size_t nr_fields, struct ustctl_field *fields, + char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields, int loglevel_value, char *model_emf_uri, int buffer_type, uint32_t *event_id_p, struct ust_app *app) { @@ -383,10 +409,10 @@ int ust_registry_create_event(struct ust_registry_session *session, struct ust_registry_event *event = NULL; struct ust_registry_channel *chan; - assert(session); - assert(name); - assert(sig); - assert(event_id_p); + LTTNG_ASSERT(session); + LTTNG_ASSERT(name); + LTTNG_ASSERT(sig); + LTTNG_ASSERT(event_id_p); rcu_read_lock(); @@ -439,7 +465,7 @@ int ust_registry_create_event(struct ust_registry_session *session, destroy_event(event); event = caa_container_of(nptr, struct ust_registry_event, node.node); - assert(event); + LTTNG_ASSERT(event); event_id = event->id; } else { ERR("UST registry create event add unique failed for event: %s, " @@ -489,13 +515,13 @@ void ust_registry_destroy_event(struct ust_registry_channel *chan, int ret; struct lttng_ht_iter iter; - assert(chan); - assert(event); + LTTNG_ASSERT(chan); + LTTNG_ASSERT(event); /* Delete the node first. */ iter.iter.node = &event->node.node; ret = lttng_ht_del(chan->ht, &iter); - assert(!ret); + LTTNG_ASSERT(!ret); call_rcu(&event->node.head, destroy_event_rcu); @@ -523,8 +549,8 @@ static void destroy_enum_rcu(struct rcu_head *head) * Lookup enumeration by name and comparing enumeration entries. * Needs to be called from RCU read-side critical section. */ -struct ust_registry_enum * - ust_registry_lookup_enum(struct ust_registry_session *session, +static struct ust_registry_enum *ust_registry_lookup_enum( + struct ust_registry_session *session, const struct ust_registry_enum *reg_enum_lookup) { struct ust_registry_enum *reg_enum = NULL; @@ -532,8 +558,8 @@ struct ust_registry_enum * struct lttng_ht_iter iter; cds_lfht_lookup(session->enums->ht, - ht_hash_enum((void *) ®_enum_lookup, lttng_ht_seed), - ht_match_enum, ®_enum_lookup, &iter.iter); + ht_hash_enum((void *) reg_enum_lookup, lttng_ht_seed), + ht_match_enum, reg_enum_lookup, &iter.iter); node = lttng_ht_iter_get_node_str(&iter); if (!node) { goto end; @@ -557,8 +583,8 @@ struct ust_registry_enum * struct ust_registry_enum reg_enum_lookup; memset(®_enum_lookup, 0, sizeof(reg_enum_lookup)); - strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_SYM_NAME_LEN); - reg_enum_lookup.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN); + reg_enum_lookup.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0'; reg_enum_lookup.id = enum_id; cds_lfht_lookup(session->enums->ht, ht_hash_enum((void *) ®_enum_lookup, lttng_ht_seed), @@ -584,15 +610,15 @@ end: */ int ust_registry_create_or_find_enum(struct ust_registry_session *session, int session_objd, char *enum_name, - struct ustctl_enum_entry *entries, size_t nr_entries, + struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries, uint64_t *enum_id) { int ret = 0; struct cds_lfht_node *nodep; struct ust_registry_enum *reg_enum = NULL, *old_reg_enum; - assert(session); - assert(enum_name); + LTTNG_ASSERT(session); + LTTNG_ASSERT(enum_name); rcu_read_lock(); @@ -612,8 +638,8 @@ int ust_registry_create_or_find_enum(struct ust_registry_session *session, ret = -ENOMEM; goto end; } - strncpy(reg_enum->name, enum_name, LTTNG_UST_SYM_NAME_LEN); - reg_enum->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + strncpy(reg_enum->name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN); + reg_enum->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0'; /* entries will be owned by reg_enum. */ reg_enum->entries = entries; reg_enum->nr_entries = nr_entries; @@ -639,7 +665,7 @@ int ust_registry_create_or_find_enum(struct ust_registry_session *session, ht_hash_enum(reg_enum, lttng_ht_seed), ht_match_enum_id, reg_enum, ®_enum->node.node); - assert(nodep == ®_enum->node.node); + LTTNG_ASSERT(nodep == ®_enum->node.node); } DBG("UST registry reply with enum %s with id %" PRIu64 " in sess_objd: %u", enum_name, reg_enum->id, session_objd); @@ -655,19 +681,19 @@ end: * the enumeration. * This MUST be called within a RCU read side lock section. */ -void ust_registry_destroy_enum(struct ust_registry_session *reg_session, +static void ust_registry_destroy_enum(struct ust_registry_session *reg_session, struct ust_registry_enum *reg_enum) { int ret; struct lttng_ht_iter iter; - assert(reg_session); - assert(reg_enum); + LTTNG_ASSERT(reg_session); + LTTNG_ASSERT(reg_enum); /* Delete the node first. */ iter.iter.node = ®_enum->node.node; ret = lttng_ht_del(reg_session->enums, &iter); - assert(!ret); + LTTNG_ASSERT(!ret); call_rcu(®_enum->rcu_head, destroy_enum_rcu); } @@ -695,20 +721,33 @@ void destroy_channel_rcu(struct rcu_head *head) * free the registry pointer since it might not have been allocated before so * it's the caller responsability. */ -static void destroy_channel(struct ust_registry_channel *chan) +static void destroy_channel(struct ust_registry_channel *chan, bool notif) { struct lttng_ht_iter iter; struct ust_registry_event *event; + enum lttng_error_code cmd_ret; - assert(chan); + LTTNG_ASSERT(chan); - rcu_read_lock(); - /* Destroy all event associated with this registry. */ - cds_lfht_for_each_entry(chan->ht->ht, &iter.iter, event, node.node) { - /* Delete the node from the ht and free it. */ - ust_registry_destroy_event(chan, event); + if (notif) { + cmd_ret = notification_thread_command_remove_channel( + the_notification_thread_handle, + chan->consumer_key, LTTNG_DOMAIN_UST); + if (cmd_ret != LTTNG_OK) { + ERR("Failed to remove channel from notification thread"); + } + } + + if (chan->ht) { + rcu_read_lock(); + /* Destroy all event associated with this registry. */ + cds_lfht_for_each_entry( + chan->ht->ht, &iter.iter, event, node.node) { + /* Delete the node from the ht and free it. */ + ust_registry_destroy_event(chan, event); + } + rcu_read_unlock(); } - rcu_read_unlock(); call_rcu(&chan->rcu_head, destroy_channel_rcu); } @@ -721,7 +760,7 @@ int ust_registry_channel_add(struct ust_registry_session *session, int ret = 0; struct ust_registry_channel *chan; - assert(session); + LTTNG_ASSERT(session); chan = zmalloc(sizeof(*chan)); if (!chan) { @@ -759,7 +798,7 @@ int ust_registry_channel_add(struct ust_registry_session *session, return 0; error: - destroy_channel(chan); + destroy_channel(chan, false); error_alloc: return ret; } @@ -778,8 +817,8 @@ struct ust_registry_channel *ust_registry_channel_find( struct lttng_ht_iter iter; struct ust_registry_channel *chan = NULL; - assert(session); - assert(session->channels); + LTTNG_ASSERT(session); + LTTNG_ASSERT(session->channels); DBG3("UST registry channel finding key %" PRIu64, key); @@ -798,13 +837,13 @@ end: * Remove channel using key from registry and free memory. */ void ust_registry_channel_del_free(struct ust_registry_session *session, - uint64_t key) + uint64_t key, bool notif) { struct lttng_ht_iter iter; struct ust_registry_channel *chan; int ret; - assert(session); + LTTNG_ASSERT(session); rcu_read_lock(); chan = ust_registry_channel_find(session, key); @@ -815,9 +854,9 @@ void ust_registry_channel_del_free(struct ust_registry_session *session, iter.iter.node = &chan->node.node; ret = lttng_ht_del(session->channels, &iter); - assert(!ret); + LTTNG_ASSERT(!ret); rcu_read_unlock(); - destroy_channel(chan); + destroy_channel(chan, notif); end: return; @@ -844,12 +883,14 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, const char *root_shm_path, const char *shm_path, uid_t euid, - gid_t egid) + gid_t egid, + uint64_t tracing_id, + uid_t tracing_uid) { int ret; struct ust_registry_session *session; - assert(sessionp); + LTTNG_ASSERT(sessionp); session = zmalloc(sizeof(*session)); if (!session) { @@ -908,7 +949,7 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, session->enums = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); if (!session->enums) { - ret = -ENOMEM; + ERR("Failed to create enums hash table"); goto error; } /* hash/match functions are specified at call site. */ @@ -926,6 +967,9 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, goto error; } + session->tracing_id = tracing_id; + session->tracing_uid = tracing_uid; + pthread_mutex_lock(&session->lock); ret = ust_metadata_session_statedump(session, app, major, minor); pthread_mutex_unlock(&session->lock); @@ -962,7 +1006,7 @@ void ust_registry_session_destroy(struct ust_registry_session *reg) /* On error, EBUSY can be returned if lock. Code flow error. */ ret = pthread_mutex_destroy(®->lock); - assert(!ret); + LTTNG_ASSERT(!ret); if (reg->channels) { rcu_read_lock(); @@ -971,8 +1015,8 @@ void ust_registry_session_destroy(struct ust_registry_session *reg) node.node) { /* Delete the node from the ht and free it. */ ret = lttng_ht_del(reg->channels, &iter); - assert(!ret); - destroy_channel(chan); + LTTNG_ASSERT(!ret); + destroy_channel(chan, true); } rcu_read_unlock(); ht_cleanup_push(reg->channels); @@ -995,7 +1039,8 @@ void ust_registry_session_destroy(struct ust_registry_session *reg) * Try deleting the directory hierarchy. */ (void) run_as_rmdir_recursive(reg->root_shm_path, - reg->uid, reg->gid); + reg->uid, reg->gid, + LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG); } /* Destroy the enum hash table */ if (reg->enums) {