Commit | Line | Data |
---|---|---|
aeeb48c6 JG |
1 | /* |
2 | * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0-only | |
5 | * | |
6 | */ | |
7 | ||
8 | #include "ust-registry.hpp" | |
9 | ||
10 | #include <common/compat/directory-handle.hpp> | |
11 | #include <common/error.hpp> | |
12 | #include <common/exception.hpp> | |
13 | #include <common/runas.hpp> | |
14 | ||
15 | #include <fcntl.h> | |
16 | #include <sstream> | |
17 | #include <string> | |
18 | ||
19 | ust_registry_session::ust_registry_session(uint32_t bits_per_long, | |
20 | uint32_t uint8_t_alignment, | |
21 | uint32_t uint16_t_alignment, | |
22 | uint32_t uint32_t_alignment, | |
23 | uint32_t uint64_t_alignment, | |
24 | uint32_t long_alignment, | |
25 | int byte_order, | |
26 | uint32_t major, | |
27 | uint32_t minor, | |
28 | const char *root_shm_path, | |
29 | const char *shm_path, | |
30 | uid_t euid, | |
31 | gid_t egid, | |
32 | uint64_t tracing_id) : | |
33 | _bits_per_long{bits_per_long}, | |
34 | _uint8_t_alignment{uint8_t_alignment}, | |
35 | _uint16_t_alignment{uint16_t_alignment}, | |
36 | _uint32_t_alignment{uint32_t_alignment}, | |
37 | _uint64_t_alignment{uint64_t_alignment}, | |
38 | _long_alignment{long_alignment}, | |
39 | _byte_order{byte_order}, | |
40 | _uid{euid}, | |
41 | _gid{egid}, | |
42 | _app_tracer_version_major{major}, | |
43 | _app_tracer_version_minor{minor}, | |
44 | _tracing_id{tracing_id} | |
45 | { | |
46 | pthread_mutex_init(&_lock, NULL); | |
47 | strncpy(_root_shm_path, root_shm_path, sizeof(_root_shm_path)); | |
48 | _root_shm_path[sizeof(_root_shm_path) - 1] = '\0'; | |
49 | if (shm_path[0]) { | |
50 | strncpy(_shm_path, shm_path, sizeof(_shm_path)); | |
51 | _shm_path[sizeof(_shm_path) - 1] = '\0'; | |
52 | strncpy(_metadata_path, shm_path, sizeof(_metadata_path)); | |
53 | _metadata_path[sizeof(_metadata_path) - 1] = '\0'; | |
54 | strncat(_metadata_path, "/metadata", | |
55 | sizeof(_metadata_path) - strlen(_metadata_path) - 1); | |
56 | } | |
57 | ||
58 | if (_shm_path[0]) { | |
59 | if (run_as_mkdir_recursive(_shm_path, S_IRWXU | S_IRWXG, euid, egid)) { | |
60 | LTTNG_THROW_POSIX("run_as_mkdir_recursive", errno); | |
61 | } | |
62 | } | |
63 | ||
64 | if (_metadata_path[0]) { | |
65 | /* Create metadata file. */ | |
66 | const int ret = run_as_open(_metadata_path, O_WRONLY | O_CREAT | O_EXCL, | |
67 | S_IRUSR | S_IWUSR, euid, egid); | |
68 | ||
69 | if (ret < 0) { | |
70 | std::stringstream ss; | |
71 | ||
72 | ss << "Opening metadata file '" << _metadata_path << "'"; | |
73 | LTTNG_THROW_POSIX(ss.str(), errno); | |
74 | } | |
75 | ||
76 | _metadata_fd = ret; | |
77 | } | |
78 | ||
79 | _enums.reset(lttng_ht_new(0, LTTNG_HT_TYPE_STRING)); | |
80 | if (!_enums) { | |
81 | LTTNG_THROW_POSIX("Failed to create enums hash table", ENOMEM); | |
82 | } | |
83 | ||
84 | /* hash/match functions are specified at call site. */ | |
85 | _enums->match_fct = NULL; | |
86 | _enums->hash_fct = NULL; | |
87 | ||
88 | _channels.reset(lttng_ht_new(0, LTTNG_HT_TYPE_U64)); | |
89 | if (!_channels) { | |
90 | LTTNG_THROW_POSIX("Failed to create channels hash table", ENOMEM); | |
91 | } | |
92 | ||
93 | if (lttng_uuid_generate(_uuid)) { | |
94 | LTTNG_THROW_POSIX("Failed to generate UST uuid", errno); | |
95 | } | |
96 | } | |
97 | ||
98 | ust_registry_session::~ust_registry_session() | |
99 | { | |
100 | int ret; | |
101 | struct lttng_ht_iter iter; | |
102 | struct ust_registry_channel *chan; | |
103 | struct ust_registry_enum *reg_enum; | |
104 | ||
105 | /* On error, EBUSY can be returned if lock. Code flow error. */ | |
106 | ret = pthread_mutex_destroy(&_lock); | |
107 | LTTNG_ASSERT(!ret); | |
108 | ||
109 | if (_channels) { | |
110 | rcu_read_lock(); | |
111 | /* Destroy all event associated with this registry. */ | |
112 | cds_lfht_for_each_entry (_channels->ht, &iter.iter, chan, node.node) { | |
113 | /* Delete the node from the ht and free it. */ | |
114 | ret = lttng_ht_del(_channels.get(), &iter); | |
115 | LTTNG_ASSERT(!ret); | |
116 | ust_registry_channel_destroy(chan, true); | |
117 | } | |
118 | ||
119 | rcu_read_unlock(); | |
120 | } | |
121 | ||
122 | free(_metadata); | |
123 | if (_metadata_fd >= 0) { | |
124 | ret = close(_metadata_fd); | |
125 | if (ret) { | |
126 | PERROR("close"); | |
127 | } | |
128 | ||
129 | ret = run_as_unlink(_metadata_path, _uid, _gid); | |
130 | if (ret) { | |
131 | PERROR("unlink"); | |
132 | } | |
133 | } | |
134 | ||
135 | if (_root_shm_path[0]) { | |
136 | /* Try to delete the directory hierarchy. */ | |
137 | (void) run_as_rmdir_recursive(_root_shm_path, _uid, _gid, | |
138 | LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG); | |
139 | } | |
140 | ||
141 | /* Destroy the enum hash table */ | |
142 | if (_enums) { | |
143 | rcu_read_lock(); | |
144 | /* Destroy all enum entries associated with this registry. */ | |
145 | cds_lfht_for_each_entry (_enums->ht, &iter.iter, reg_enum, node.node) { | |
146 | ust_registry_destroy_enum(this, reg_enum); | |
147 | } | |
148 | ||
149 | rcu_read_unlock(); | |
150 | } | |
151 | } | |
152 | ||
153 | void ust_registry_session::statedump() | |
154 | { | |
155 | pthread_mutex_lock(&_lock); | |
156 | const int ret = ust_metadata_session_statedump(this); | |
157 | pthread_mutex_unlock(&_lock); | |
158 | if (ret) { | |
159 | LTTNG_THROW_ERROR( | |
160 | "Failed to generate session metadata during registry session creation"); | |
161 | } | |
162 | } |