From 97f630d42cd12a475293af66e75a71ab7b490633 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Wed, 8 Jun 2022 15:50:07 -0400 Subject: [PATCH] Clean-up: sessiond: move registry_session free functions under class MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Move a number of registry_session methods implemented as c-style free functions under the `registry_session` class. This makes it possible to make a large number of attributes private. This leaves only the metadata storage and locking facilities publicly accessible. Making them private requires a bit more refactoring. Signed-off-by: Jérémie Galarneau Change-Id: I6bdd4cc8918e5d7025fc3d735fadbf1ce2e9b7c8 --- src/bin/lttng-sessiond/ust-app.cpp | 52 ++- src/bin/lttng-sessiond/ust-field-convert.cpp | 2 +- .../lttng-sessiond/ust-registry-session.cpp | 309 ++++++++++++++++-- .../lttng-sessiond/ust-registry-session.hpp | 139 ++++---- src/bin/lttng-sessiond/ust-registry.cpp | 257 --------------- src/bin/lttng-sessiond/ust-registry.hpp | 40 +-- 6 files changed, 385 insertions(+), 414 deletions(-) diff --git a/src/bin/lttng-sessiond/ust-app.cpp b/src/bin/lttng-sessiond/ust-app.cpp index 3ca4279a9..16848191d 100644 --- a/src/bin/lttng-sessiond/ust-app.cpp +++ b/src/bin/lttng-sessiond/ust-app.cpp @@ -6613,16 +6613,16 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, const char *na * * On success 0 is returned else a negative value. */ -static int add_enum_ust_registry(int sock, int sobjd, char *name, - struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries) +static int add_enum_ust_registry(int sock, int sobjd, const char *name, + struct lttng_ust_ctl_enum_entry *raw_entries, size_t nr_entries) { - int ret = 0, ret_code; + int ret = 0; struct ust_app *app; struct ust_app_session *ua_sess; - lsu::registry_session *registry; uint64_t enum_id = -1ULL; - - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock_guard; + auto entries = lttng::make_unique_wrapper( + raw_entries); /* Lookup application. If not found, there is a code flow error. */ app = find_app_by_notify_sock(sock); @@ -6630,9 +6630,7 @@ static int add_enum_ust_registry(int sock, int sobjd, char *name, /* Return an error since this is not an error */ DBG("Application socket %d is being torn down. Aborting enum registration", sock); - free(entries); - ret = -1; - goto error_rcu_unlock; + return -1; } /* Lookup session by UST object descriptor. */ @@ -6640,34 +6638,37 @@ static int add_enum_ust_registry(int sock, int sobjd, char *name, if (!ua_sess) { /* Return an error since this is not an error */ DBG("Application session is being torn down (session not found). Aborting enum registration."); - free(entries); - goto error_rcu_unlock; + return 0; } - registry = get_session_registry(ua_sess); - if (!registry) { + auto locked_registry = get_locked_session_registry(ua_sess); + if (!locked_registry) { DBG("Application session is being torn down (registry not found). Aborting enum registration."); - free(entries); - goto error_rcu_unlock; + return 0; } - pthread_mutex_lock(®istry->_lock); - /* * From this point on, the callee acquires the ownership of * entries. The variable entries MUST NOT be read/written after * call. */ - ret_code = ust_registry_create_or_find_enum(registry, sobjd, name, - entries, nr_entries, &enum_id); - entries = NULL; + int application_reply_code; + try { + locked_registry->create_or_find_enum( + sobjd, name, entries.release(), nr_entries, &enum_id); + application_reply_code = 0; + } catch (const std::exception& ex) { + ERR("%s: %s", fmt::format("Failed to create or find enumeration provided by application: app = {}, enumeration name = {}", + *app, name).c_str(), ex.what()); + application_reply_code = -1; + } /* * The return value is returned to ustctl so in case of an error, the * application can be notified. In case of an error, it's important not to * return a negative error or else the application will get closed. */ - ret = lttng_ust_ctl_reply_register_enum(sock, enum_id, ret_code); + ret = lttng_ust_ctl_reply_register_enum(sock, enum_id, application_reply_code); if (ret < 0) { if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { DBG3("UST app reply enum failed. Application died: pid = %d, sock = %d", @@ -6683,16 +6684,11 @@ static int add_enum_ust_registry(int sock, int sobjd, char *name, * No need to wipe the create enum since the application socket will * get close on error hence cleaning up everything by itself. */ - goto error; + return ret; } DBG3("UST registry enum %s added successfully or already found", name); - -error: - pthread_mutex_unlock(®istry->_lock); -error_rcu_unlock: - rcu_read_unlock(); - return ret; + return 0; } /* diff --git a/src/bin/lttng-sessiond/ust-field-convert.cpp b/src/bin/lttng-sessiond/ust-field-convert.cpp index ae402ccb8..89f000128 100644 --- a/src/bin/lttng-sessiond/ust-field-convert.cpp +++ b/src/bin/lttng-sessiond/ust-field-convert.cpp @@ -650,7 +650,7 @@ std::vector create_fields_from_ust_ctl_fields( const auto trace_native_byte_order = session.abi.byte_order; const session_attributes session_attributes{ [&session](const char *enum_name, uint64_t enum_id) { - return ust_registry_lookup_enum_by_id(&session, enum_name, enum_id); + return session.get_enumeration(enum_name, enum_id); }, trace_native_byte_order}; diff --git a/src/bin/lttng-sessiond/ust-registry-session.cpp b/src/bin/lttng-sessiond/ust-registry-session.cpp index bb678fe4d..255a5ec81 100644 --- a/src/bin/lttng-sessiond/ust-registry-session.cpp +++ b/src/bin/lttng-sessiond/ust-registry-session.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -131,6 +132,94 @@ void destroy_channel(lsu::registry_channel *chan, bool notify) call_rcu(&chan->_rcu_head, destroy_channel_rcu); } + +void destroy_enum(lsu::registry_enum *reg_enum) +{ + if (!reg_enum) { + return; + } + + delete reg_enum; +} + +void destroy_enum_rcu(struct rcu_head *head) +{ + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_INVALID_OFFSETOF + lsu::registry_enum *reg_enum = + caa_container_of(head, lsu::registry_enum, rcu_head); + DIAGNOSTIC_POP + + destroy_enum(reg_enum); +} + +/* + * Hash table match function for enumerations in the session. Match is + * performed on enumeration name, and confirmed by comparing the enum + * entries. + */ +int ht_match_enum(struct cds_lfht_node *node, const void *_key) +{ + lsu::registry_enum *_enum; + const lsu::registry_enum *key; + + LTTNG_ASSERT(node); + LTTNG_ASSERT(_key); + + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_INVALID_OFFSETOF + _enum = caa_container_of(node, lsu::registry_enum, + node.node); + DIAGNOSTIC_POP + + LTTNG_ASSERT(_enum); + key = (lsu::registry_enum *) _key; + + return *_enum == *key; +} + +/* + * Hash table match function for enumerations in the session. Match is + * performed by enumeration ID. + */ +int ht_match_enum_id(struct cds_lfht_node *node, const void *_key) +{ + lsu::registry_enum *_enum; + const lsu::registry_enum *key = (lsu::registry_enum *) _key; + + LTTNG_ASSERT(node); + LTTNG_ASSERT(_key); + + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_INVALID_OFFSETOF + _enum = caa_container_of(node, lsu::registry_enum, node.node); + DIAGNOSTIC_POP + + LTTNG_ASSERT(_enum); + + if (_enum->id != key->id) { + goto no_match; + } + + /* Match. */ + return 1; + +no_match: + return 0; +} + +/* + * Hash table hash function for enumerations in the session. The + * enumeration name is used for hashing. + */ +unsigned long ht_hash_enum(void *_key, unsigned long seed) +{ + lsu::registry_enum *key = (lsu::registry_enum *) _key; + + LTTNG_ASSERT(key); + return hash_key_str(key->name.c_str(), seed); +} + } /* namespace */ void lsu::details::locked_registry_session_release(lsu::registry_session *session) @@ -147,44 +236,33 @@ lsu::registry_session::registry_session(const struct lst::abi& in_abi, gid_t egid, uint64_t tracing_id) : lst::trace_class(in_abi, generate_uuid_or_throw()), + _root_shm_path{root_shm_path ? root_shm_path : ""}, + _shm_path{shm_path ? shm_path : ""}, + _metadata_path{_shm_path.size() > 0 ? + fmt::format("{}/metadata", _shm_path) : std::string("")}, _uid{euid}, _gid{egid}, - _app_tracer_version_major{major}, - _app_tracer_version_minor{minor}, + _app_tracer_version{.major = major, .minor = minor}, _tracing_id{tracing_id}, - _metadata_generating_visitor{lttng::make_unique( - abi, [this](const std::string& fragment) { + _metadata_generating_visitor{lttng::make_unique(abi, + [this](const std::string& fragment) { _append_metadata_fragment(fragment); })} { pthread_mutex_init(&_lock, NULL); - strncpy(_root_shm_path, root_shm_path, sizeof(_root_shm_path)); - _root_shm_path[sizeof(_root_shm_path) - 1] = '\0'; - if (shm_path[0]) { - strncpy(_shm_path, shm_path, sizeof(_shm_path)); - _shm_path[sizeof(_shm_path) - 1] = '\0'; - strncpy(_metadata_path, shm_path, sizeof(_metadata_path)); - _metadata_path[sizeof(_metadata_path) - 1] = '\0'; - strncat(_metadata_path, "/metadata", - sizeof(_metadata_path) - strlen(_metadata_path) - 1); - } - - if (_shm_path[0]) { - if (run_as_mkdir_recursive(_shm_path, S_IRWXU | S_IRWXG, euid, egid)) { + if (_shm_path.size() > 0) { + if (run_as_mkdir_recursive(_shm_path.c_str(), S_IRWXU | S_IRWXG, euid, egid)) { LTTNG_THROW_POSIX("run_as_mkdir_recursive", errno); } } - if (_metadata_path[0]) { + if (_metadata_path.size() > 0) { /* Create metadata file. */ - const int ret = run_as_open(_metadata_path, O_WRONLY | O_CREAT | O_EXCL, + const int ret = run_as_open(_metadata_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, euid, egid); - if (ret < 0) { - std::stringstream ss; - - ss << "Opening metadata file '" << _metadata_path << "'"; - LTTNG_THROW_POSIX(ss.str(), errno); + LTTNG_THROW_POSIX(fmt::format("Failed to open metadata file during registry session creation: path = {}", + _metadata_path), errno); } _metadata_fd = ret; @@ -205,6 +283,26 @@ lsu::registry_session::registry_session(const struct lst::abi& in_abi, } } +/* + * For a given enumeration in a registry, delete the entry and destroy + * the enumeration. + */ +void lsu::registry_session::_destroy_enum(lsu::registry_enum *reg_enum) +{ + int ret; + lttng::urcu::read_lock_guard read_lock_guard; + + LTTNG_ASSERT(reg_enum); + ASSERT_RCU_READ_LOCKED(); + + /* Delete the node first. */ + struct lttng_ht_iter iter; + iter.iter.node = ®_enum->node.node; + ret = lttng_ht_del(_enums.get(), &iter); + LTTNG_ASSERT(!ret); + call_rcu(®_enum->rcu_head, destroy_enum_rcu); +} + lsu::registry_session::~registry_session() { int ret; @@ -238,7 +336,7 @@ lsu::registry_session::~registry_session() PERROR("close"); } - ret = run_as_unlink(_metadata_path, _uid, _gid); + ret = run_as_unlink(_metadata_path.c_str(), _uid, _gid); if (ret) { PERROR("unlink"); } @@ -246,26 +344,25 @@ lsu::registry_session::~registry_session() if (_root_shm_path[0]) { /* Try to delete the directory hierarchy. */ - (void) run_as_rmdir_recursive(_root_shm_path, _uid, _gid, + (void) run_as_rmdir_recursive(_root_shm_path.c_str(), _uid, _gid, LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG); } /* Destroy the enum hash table */ if (_enums) { - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock_guard; + /* Destroy all enum entries associated with this registry. */ DIAGNOSTIC_PUSH DIAGNOSTIC_IGNORE_INVALID_OFFSETOF cds_lfht_for_each_entry (_enums->ht, &iter.iter, reg_enum, node.node) { - ust_registry_destroy_enum(this, reg_enum); + _destroy_enum(reg_enum); } DIAGNOSTIC_POP - - rcu_read_unlock(); } } -lsu::registry_session::locked_ptr lsu::registry_session::lock() +lsu::registry_session::locked_ptr lsu::registry_session::lock() noexcept { pthread_mutex_lock(&_lock); return locked_ptr(this); @@ -360,8 +457,8 @@ void lsu::registry_session::_visit_environment( visitor.visit(lst::environment_field("domain", "ust")); visitor.visit(lst::environment_field("tracer_name", "lttng-ust")); - visitor.visit(lst::environment_field("tracer_major", _app_tracer_version_major)); - visitor.visit(lst::environment_field("tracer_minor", _app_tracer_version_minor)); + visitor.visit(lst::environment_field("tracer_major", _app_tracer_version.major)); + visitor.visit(lst::environment_field("tracer_minor", _app_tracer_version.minor)); visitor.visit(lst::environment_field("tracer_buffering_scheme", get_buffering_scheme() == LTTNG_BUFFER_PER_PID ? "pid" : "uid")); visitor.visit(lst::environment_field("architecture_bit_width", abi.bits_per_long)); @@ -516,3 +613,149 @@ void lsu::registry_session::regenerate_metadata() _reset_metadata(); _generate_metadata(); } + +/* + * Lookup enumeration by enum ID. + * + * Note that there is no need to lock the registry session as this only + * performs an RCU-protected look-up. The function also return an rcu-protected + * reference, which ensures that the caller keeps the RCU read lock until it + * disposes of the object. + */ +lsu::registry_enum::const_rcu_protected_reference +lsu::registry_session::get_enumeration(const char *enum_name, uint64_t enum_id) const +{ + lsu::registry_enum *reg_enum = NULL; + struct lttng_ht_node_str *node; + struct lttng_ht_iter iter; + lttng::urcu::unique_read_lock rcu_lock; + /* + * Hack: only the name is used for hashing; the rest of the attributes + * can be fudged. + */ + lsu::registry_signed_enum reg_enum_lookup(enum_name, nullptr, 0); + + ASSERT_RCU_READ_LOCKED(); + + reg_enum_lookup.id = enum_id; + cds_lfht_lookup(_enums->ht, + ht_hash_enum((void *) ®_enum_lookup, lttng_ht_seed), + ht_match_enum_id, ®_enum_lookup, &iter.iter); + node = lttng_ht_iter_get_node_str(&iter); + if (!node) { + LTTNG_THROW_PROTOCOL_ERROR(fmt::format( + "Unknown enumeration referenced by application event field: enum name = `{}`, enum id = {}", + enum_name, enum_id)); + } + + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_INVALID_OFFSETOF + reg_enum = caa_container_of(node, lsu::registry_enum, node); + DIAGNOSTIC_POP + + return lsu::registry_enum::const_rcu_protected_reference{*reg_enum, std::move(rcu_lock)}; +} + +/* + * Lookup enumeration by name and comparing enumeration entries. + * Needs to be called from RCU read-side critical section. + */ +lsu::registry_enum *lsu::registry_session::_lookup_enum( + const lsu::registry_enum *reg_enum_lookup) const +{ + lsu::registry_enum *reg_enum = NULL; + struct lttng_ht_node_str *node; + struct lttng_ht_iter iter; + + ASSERT_RCU_READ_LOCKED(); + + cds_lfht_lookup(_enums->ht, 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; + } + + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_INVALID_OFFSETOF + reg_enum = caa_container_of(node, lsu::registry_enum, node); + DIAGNOSTIC_POP + +end: + return reg_enum; +} + +/* + * Create a lsu::registry_enum from the given parameters and add it to the + * registry hash table, or find it if already there. + * + * Should be called with session registry mutex held. + * + * We receive ownership of entries. + */ +void lsu::registry_session::create_or_find_enum( + int session_objd, const char *enum_name, + struct lttng_ust_ctl_enum_entry *raw_entries, size_t nr_entries, + uint64_t *enum_id) +{ + struct cds_lfht_node *nodep; + lsu::registry_enum *reg_enum = NULL, *old_reg_enum; + lttng::urcu::read_lock_guard read_lock_guard; + auto entries = lttng::make_unique_wrapper(raw_entries); + + LTTNG_ASSERT(enum_name); + + /* + * This should not happen but since it comes from the UST tracer, an + * external party, don't assert and simply validate values. + */ + if (session_objd < 0) { + LTTNG_THROW_INVALID_ARGUMENT_ERROR(fmt::format( + "Invalid parameters used to create or look-up enumeration from registry session: session_objd = {}", + session_objd)); + } + if (nr_entries == 0) { + LTTNG_THROW_INVALID_ARGUMENT_ERROR(fmt::format( + "Invalid parameters used to create or look-up enumeration from registry session: nr_entries = {}", + nr_entries)); + } + if (lttng_strnlen(enum_name, LTTNG_UST_ABI_SYM_NAME_LEN) == + LTTNG_UST_ABI_SYM_NAME_LEN) { + LTTNG_THROW_INVALID_ARGUMENT_ERROR( + "Invalid parameters used to create or look-up enumeration from registry session: enumeration name is not null terminated"); + } + + if (entries->start.signedness) { + reg_enum = new lsu::registry_signed_enum( + enum_name, entries.get(), nr_entries); + } else { + reg_enum = new lsu::registry_unsigned_enum( + enum_name, entries.get(), nr_entries); + } + + old_reg_enum = _lookup_enum(reg_enum); + if (old_reg_enum) { + DBG("enum %s already in sess_objd: %u", enum_name, session_objd); + /* Fall through. Use prior enum. */ + destroy_enum(reg_enum); + reg_enum = old_reg_enum; + } else { + DBG("UST registry creating enum: %s, sess_objd: %u", + enum_name, session_objd); + if (_next_enum_id == -1ULL) { + destroy_enum(reg_enum); + LTTNG_THROW_ERROR("Failed to allocate unique enumeration ID as it would overflow"); + } + + reg_enum->id = _next_enum_id++; + nodep = cds_lfht_add_unique(_enums->ht, + ht_hash_enum(reg_enum, lttng_ht_seed), + ht_match_enum_id, reg_enum, + ®_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); + *enum_id = reg_enum->id; +} \ No newline at end of file diff --git a/src/bin/lttng-sessiond/ust-registry-session.hpp b/src/bin/lttng-sessiond/ust-registry-session.hpp index c95097e4f..0bd023d70 100644 --- a/src/bin/lttng-sessiond/ust-registry-session.hpp +++ b/src/bin/lttng-sessiond/ust-registry-session.hpp @@ -13,6 +13,7 @@ #include "trace-class.hpp" #include "ust-clock-class.hpp" #include "ust-registry-channel.hpp" +#include "ust-registry.hpp" #include @@ -26,6 +27,7 @@ namespace lttng { namespace sessiond { namespace ust { +class registry_enum; class registry_session; namespace details { @@ -40,12 +42,23 @@ public: deleter>; virtual lttng_buffer_type get_buffering_scheme() const noexcept = 0; - locked_ptr lock(); + locked_ptr lock() noexcept; void add_channel(uint64_t channel_key); + + /* A channel is protected by its parent registry session's lock. */ lttng::sessiond::ust::registry_channel& get_channel(uint64_t channel_key) const; + void remove_channel(uint64_t channel_key, bool notify); + void create_or_find_enum(int session_objd, + const char *enum_name, + struct lttng_ust_ctl_enum_entry *raw_entries, + size_t nr_entries, + uint64_t *enum_id); + registry_enum::const_rcu_protected_reference get_enumeration( + const char *enum_name, uint64_t enum_id) const; + void regenerate_metadata(); virtual ~registry_session(); @@ -55,23 +68,70 @@ public: * Also acts as a registry serialization lock. Used by registry * readers to serialize the registry information sent from the * sessiond to the consumerd. + * * The consumer socket lock nests within this lock. */ mutable pthread_mutex_t _lock; + + /* Generated metadata, not null-terminated. */ + char *_metadata = nullptr; /* */ + size_t _metadata_len = 0; + /* Length of bytes sent to the consumer. */ + size_t _metadata_len_sent = 0; + /* Current version of the metadata. */ + uint64_t _metadata_version = 0; + + /* + * Unique key to identify the metadata on the consumer side. + */ + uint64_t _metadata_key = 0; + /* + * Indicates if the metadata is closed on the consumer side. This is to + * avoid double close of metadata when an application unregisters AND + * deletes its sessions. + */ + bool _metadata_closed = false; + +protected: + /* Prevent instanciation of this base class. */ + registry_session(const struct lttng::sessiond::trace::abi& abi, + unsigned int app_tracer_version_major, + unsigned int app_tracer_version_minor, + const char *root_shm_path, + const char *shm_path, + uid_t euid, + gid_t egid, + uint64_t tracing_id); + virtual void _visit_environment( + lttng::sessiond::trace::trace_class_visitor& trace_class_visitor) + const override; + void _generate_metadata(); + +private: + uint32_t _get_next_channel_id(); + void _increase_metadata_size(size_t reservation_length); + void _append_metadata_fragment(const std::string& fragment); + void _reset_metadata(); + void _destroy_enum(registry_enum *reg_enum); + registry_enum *_lookup_enum(const registry_enum *target_enum) const; + + virtual void _accept_on_clock_classes( + lttng::sessiond::trace::trace_class_visitor& trace_class_visitor) + const override final; + virtual void _accept_on_stream_classes( + lttng::sessiond::trace::trace_class_visitor& trace_class_visitor) + const override final; + /* Next channel ID available for a newly registered channel. */ uint32_t _next_channel_id = 0; + /* Once this value reaches UINT32_MAX, no more id can be allocated. */ uint32_t _used_channel_id = 0; + /* Next enumeration ID available. */ uint64_t _next_enum_id = 0; - /* Generated metadata. */ - char *_metadata = nullptr; /* NOT null-terminated ! Use memcpy. */ - size_t _metadata_len = 0, _metadata_alloc_len = 0; - /* Length of bytes sent to the consumer. */ - size_t _metadata_len_sent = 0; - /* Current version of the metadata. */ - uint64_t _metadata_version = 0; + size_t _metadata_alloc_len = 0; /* * Those fields are only used when a session is created with @@ -100,9 +160,10 @@ public: * metadata_fd is a file descriptor that points to the file at * 'metadata_path'. */ - char _root_shm_path[PATH_MAX] = {}; - char _shm_path[PATH_MAX] = {}; - char _metadata_path[PATH_MAX] = {}; + const std::string _root_shm_path; + const std::string _shm_path; + const std::string _metadata_path; + /* File-backed metadata FD */ int _metadata_fd = -1; @@ -112,61 +173,23 @@ public: */ lttng_ht::uptr _channels; - /* - * Unique key to identify the metadata on the consumer side. - */ - uint64_t _metadata_key = 0; - /* - * Indicates if the metadata is closed on the consumer side. This is to - * avoid double close of metadata when an application unregisters AND - * deletes its sessions. - */ - bool _metadata_closed = false; - - /* User and group owning the session. */ - uid_t _uid = -1; - gid_t _gid = -1; - /* Enumerations table. */ lttng_ht::uptr _enums; + /* User and group owning the session. */ + const uid_t _uid; + const gid_t _gid; + /* * Copy of the tracer version when the first app is registered. * It is used if we need to regenerate the metadata. */ - uint32_t _app_tracer_version_major = 0; - uint32_t _app_tracer_version_minor = 0; - - /* The id of the parent session */ - ltt_session::id_t _tracing_id = -1ULL; + const struct { + uint32_t major, minor; + } _app_tracer_version; -protected: - /* Prevent instanciation of this base class. */ - registry_session(const struct lttng::sessiond::trace::abi& abi, - unsigned int app_tracer_version_major, - unsigned int app_tracer_version_minor, - const char *root_shm_path, - const char *shm_path, - uid_t euid, - gid_t egid, - uint64_t tracing_id); - virtual void _visit_environment( - lttng::sessiond::trace::trace_class_visitor& trace_class_visitor) - const override; - void _generate_metadata(); - -private: - uint32_t _get_next_channel_id(); - void _increase_metadata_size(size_t reservation_length); - void _append_metadata_fragment(const std::string& fragment); - void _reset_metadata(); - - virtual void _accept_on_clock_classes( - lttng::sessiond::trace::trace_class_visitor& trace_class_visitor) - const override final; - virtual void _accept_on_stream_classes( - lttng::sessiond::trace::trace_class_visitor& trace_class_visitor) - const override final; + /* The id of the parent session. */ + const ltt_session::id_t _tracing_id; lttng::sessiond::ust::clock_class _clock; const lttng::sessiond::trace::trace_class_visitor::cuptr _metadata_generating_visitor; diff --git a/src/bin/lttng-sessiond/ust-registry.cpp b/src/bin/lttng-sessiond/ust-registry.cpp index ce76e403f..323fdd6a7 100644 --- a/src/bin/lttng-sessiond/ust-registry.cpp +++ b/src/bin/lttng-sessiond/ust-registry.cpp @@ -28,73 +28,6 @@ namespace ls = lttng::sessiond; namespace lst = lttng::sessiond::trace; namespace lsu = lttng::sessiond::ust; -/* - * Hash table match function for enumerations in the session. Match is - * performed on enumeration name, and confirmed by comparing the enum - * entries. - */ -static int ht_match_enum(struct cds_lfht_node *node, const void *_key) -{ - lsu::registry_enum *_enum; - const lsu::registry_enum *key; - - LTTNG_ASSERT(node); - LTTNG_ASSERT(_key); - - DIAGNOSTIC_PUSH - DIAGNOSTIC_IGNORE_INVALID_OFFSETOF - _enum = caa_container_of(node, lsu::registry_enum, - node.node); - DIAGNOSTIC_POP - - LTTNG_ASSERT(_enum); - key = (lsu::registry_enum *) _key; - - return *_enum == *key; -} - -/* - * Hash table match function for enumerations in the session. Match is - * performed by enumeration ID. - */ -static int ht_match_enum_id(struct cds_lfht_node *node, const void *_key) -{ - lsu::registry_enum *_enum; - const lsu::registry_enum *key = (lsu::registry_enum *) _key; - - LTTNG_ASSERT(node); - LTTNG_ASSERT(_key); - - DIAGNOSTIC_PUSH - DIAGNOSTIC_IGNORE_INVALID_OFFSETOF - _enum = caa_container_of(node, lsu::registry_enum, node.node); - DIAGNOSTIC_POP - - LTTNG_ASSERT(_enum); - - if (_enum->id != key->id) { - goto no_match; - } - - /* Match. */ - return 1; - -no_match: - return 0; -} - -/* - * Hash table hash function for enumerations in the session. The - * enumeration name is used for hashing. - */ -static unsigned long ht_hash_enum(void *_key, unsigned long seed) -{ - lsu::registry_enum *key = (lsu::registry_enum *) _key; - - LTTNG_ASSERT(key); - return hash_key_str(key->name.c_str(), seed); -} - /* * Destroy event function call of the call RCU. */ @@ -134,196 +67,6 @@ void ust_registry_channel_destroy_event(lsu::registry_channel *chan, return; } -static void destroy_enum(lsu::registry_enum *reg_enum) -{ - if (!reg_enum) { - return; - } - - delete reg_enum; -} - -static void destroy_enum_rcu(struct rcu_head *head) -{ - DIAGNOSTIC_PUSH - DIAGNOSTIC_IGNORE_INVALID_OFFSETOF - lsu::registry_enum *reg_enum = - caa_container_of(head, lsu::registry_enum, rcu_head); - DIAGNOSTIC_POP - - destroy_enum(reg_enum); -} - -/* - * Lookup enumeration by name and comparing enumeration entries. - * Needs to be called from RCU read-side critical section. - */ -static lsu::registry_enum *ust_registry_lookup_enum( - lsu::registry_session *session, - const lsu::registry_enum *reg_enum_lookup) -{ - lsu::registry_enum *reg_enum = NULL; - struct lttng_ht_node_str *node; - struct lttng_ht_iter iter; - - ASSERT_RCU_READ_LOCKED(); - - cds_lfht_lookup(session->_enums->ht, - 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; - } - - DIAGNOSTIC_PUSH - DIAGNOSTIC_IGNORE_INVALID_OFFSETOF - reg_enum = caa_container_of(node, lsu::registry_enum, node); - DIAGNOSTIC_POP - -end: - return reg_enum; -} - -/* - * Lookup enumeration by enum ID. - */ -lsu::registry_enum::const_rcu_protected_reference -ust_registry_lookup_enum_by_id(const lsu::registry_session *session, - const char *enum_name, uint64_t enum_id) -{ - lsu::registry_enum *reg_enum = NULL; - struct lttng_ht_node_str *node; - struct lttng_ht_iter iter; - lttng::urcu::unique_read_lock rcu_lock; - /* - * Hack: only the name is used for hashing; the rest of the attributes - * can be fudged. - */ - lsu::registry_signed_enum reg_enum_lookup(enum_name, nullptr, 0); - - ASSERT_RCU_READ_LOCKED(); - - reg_enum_lookup.id = enum_id; - cds_lfht_lookup(session->_enums->ht, - ht_hash_enum((void *) ®_enum_lookup, lttng_ht_seed), - ht_match_enum_id, ®_enum_lookup, &iter.iter); - node = lttng_ht_iter_get_node_str(&iter); - if (!node) { - LTTNG_THROW_PROTOCOL_ERROR(fmt::format( - "Unknown enumeration referenced by application event field: enum name = `{}`, enum id = {}", - enum_name, enum_id)); - } - - DIAGNOSTIC_PUSH - DIAGNOSTIC_IGNORE_INVALID_OFFSETOF - reg_enum = caa_container_of(node, lsu::registry_enum, node); - DIAGNOSTIC_POP - - return lsu::registry_enum::const_rcu_protected_reference{*reg_enum, std::move(rcu_lock)}; -} - -/* - * Create a lsu::registry_enum from the given parameters and add it to the - * registry hash table, or find it if already there. - * - * On success, return 0 else a negative value. - * - * Should be called with session registry mutex held. - * - * We receive ownership of entries. - */ -int ust_registry_create_or_find_enum(lsu::registry_session *session, - int session_objd, char *enum_name, - struct lttng_ust_ctl_enum_entry *raw_entries, size_t nr_entries, - uint64_t *enum_id) -{ - int ret = 0; - struct cds_lfht_node *nodep; - lsu::registry_enum *reg_enum = NULL, *old_reg_enum; - auto entries = lttng::make_unique_wrapper(raw_entries); - - LTTNG_ASSERT(session); - LTTNG_ASSERT(enum_name); - - rcu_read_lock(); - - /* - * This should not happen but since it comes from the UST tracer, an - * external party, don't assert and simply validate values. - */ - if (session_objd < 0 || nr_entries == 0 || - lttng_strnlen(enum_name, LTTNG_UST_ABI_SYM_NAME_LEN) == - LTTNG_UST_ABI_SYM_NAME_LEN) { - ret = -EINVAL; - goto end; - } - - try { - if (entries->start.signedness) { - reg_enum = new lsu::registry_signed_enum( - enum_name, entries.get(), nr_entries); - } else { - reg_enum = new lsu::registry_unsigned_enum( - enum_name, entries.get(), nr_entries); - } - } catch (const std::exception& ex) { - ERR("Failed to create ust registry enumeration: %s", ex.what()); - ret = -ENOMEM; - goto end; - } - - old_reg_enum = ust_registry_lookup_enum(session, reg_enum); - if (old_reg_enum) { - DBG("enum %s already in sess_objd: %u", enum_name, session_objd); - /* Fall through. Use prior enum. */ - destroy_enum(reg_enum); - reg_enum = old_reg_enum; - } else { - DBG("UST registry creating enum: %s, sess_objd: %u", - enum_name, session_objd); - if (session->_next_enum_id == -1ULL) { - ret = -EOVERFLOW; - destroy_enum(reg_enum); - goto end; - } - reg_enum->id = session->_next_enum_id++; - nodep = cds_lfht_add_unique(session->_enums->ht, - ht_hash_enum(reg_enum, lttng_ht_seed), - ht_match_enum_id, reg_enum, - ®_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); - *enum_id = reg_enum->id; -end: - rcu_read_unlock(); - return ret; -} - -/* - * For a given enumeration in a registry, delete the entry and destroy - * the enumeration. - * This MUST be called within a RCU read side lock section. - */ -void ust_registry_destroy_enum(lsu::registry_session *reg_session, - lsu::registry_enum *reg_enum) -{ - int ret; - struct lttng_ht_iter iter; - - LTTNG_ASSERT(reg_session); - LTTNG_ASSERT(reg_enum); - ASSERT_RCU_READ_LOCKED(); - - /* Delete the node first. */ - iter.iter.node = ®_enum->node.node; - ret = lttng_ht_del(reg_session->_enums.get(), &iter); - LTTNG_ASSERT(!ret); - call_rcu(®_enum->rcu_head, destroy_enum_rcu); -} - lsu::registry_session *ust_registry_session_per_uid_create(const lttng::sessiond::trace::abi& abi, uint32_t major, uint32_t minor, diff --git a/src/bin/lttng-sessiond/ust-registry.hpp b/src/bin/lttng-sessiond/ust-registry.hpp index 627ae06c0..c43821100 100644 --- a/src/bin/lttng-sessiond/ust-registry.hpp +++ b/src/bin/lttng-sessiond/ust-registry.hpp @@ -18,7 +18,6 @@ #include "ust-clock-class.hpp" #include "ust-registry-channel.hpp" #include "ust-registry-event.hpp" -#include "ust-registry-session.hpp" #include #include @@ -43,6 +42,9 @@ struct ust_app; namespace lttng { namespace sessiond { namespace ust { + +class registry_session; + namespace details { template @@ -173,15 +175,6 @@ void ust_registry_session_destroy(lttng::sessiond::ust::registry_session *sessio void ust_registry_channel_destroy_event(lttng::sessiond::ust::registry_channel *chan, lttng::sessiond::ust::registry_event *event); -int ust_registry_create_or_find_enum(lttng::sessiond::ust::registry_session *session, - int session_objd, char *name, - struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries, - uint64_t *enum_id); -lttng::sessiond::ust::registry_enum::const_rcu_protected_reference -ust_registry_lookup_enum_by_id(const lttng::sessiond::ust::registry_session *session, - const char *name, uint64_t id); -void ust_registry_destroy_enum(lttng::sessiond::ust::registry_session *reg_session, - lttng::sessiond::ust::registry_enum *reg_enum); #else /* HAVE_LIBLTTNG_UST_CTL */ static inline @@ -262,33 +255,6 @@ int ust_metadata_event_statedump( return 0; } -static inline -int ust_registry_create_or_find_enum( - lttng::sessiond::ust::registry_session *session __attribute__((unused)), - int session_objd __attribute__((unused)), - char *name __attribute__((unused)), - struct lttng_ust_ctl_enum_entry *entries __attribute__((unused)), - size_t nr_entries __attribute__((unused)), - uint64_t *enum_id __attribute__((unused))) -{ - return 0; -} - -static inline -struct ust_registry_enum * - ust_registry_lookup_enum_by_id( - const lttng::sessiond::ust::registry_session *session __attribute__((unused)), - const char *name __attribute__((unused)), - uint64_t id __attribute__((unused))) -{ - return NULL; -} - -static inline -void ust_registry_destroy_enum(lttng::sessiond::ust::registry_session *reg_session __attribute__((unused)), - struct ust_registry_enum *reg_enum __attribute__((unused))) -{} - #endif /* HAVE_LIBLTTNG_UST_CTL */ #endif /* LTTNG_UST_REGISTRY_H */ -- 2.34.1