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