fix: relayd: unaligned access in trace_chunk_registry_ht_key_hash
[lttng-tools.git] / src / lib / lttng-ctl / lttng-ctl-health.cpp
1 /*
2 * lttng-ctl-health.c
3 *
4 * Linux Trace Toolkit Health Control Library
5 *
6 * Copyright (C) 2011 EfficiOS Inc.
7 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 *
9 * SPDX-License-Identifier: LGPL-2.1-only
10 *
11 */
12
13 #define _LGPL_SOURCE
14 #include "lttng-ctl-helper.hpp"
15
16 #include <common/compat/errno.hpp>
17 #include <common/compiler.hpp>
18 #include <common/defaults.hpp>
19 #include <common/utils.hpp>
20
21 #include <lttng/health-internal.hpp>
22
23 #include <bin/lttng-consumerd/health-consumerd.hpp>
24 #include <bin/lttng-relayd/health-relayd.hpp>
25 #include <bin/lttng-sessiond/health-sessiond.hpp>
26 #include <limits.h>
27 #include <stdint.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31
32 enum health_component {
33 HEALTH_COMPONENT_SESSIOND,
34 HEALTH_COMPONENT_CONSUMERD,
35 HEALTH_COMPONENT_RELAYD,
36
37 NR_HEALTH_COMPONENT,
38 };
39
40 struct lttng_health_thread {
41 struct lttng_health *p;
42 int state;
43 };
44
45 struct lttng_health {
46 enum health_component component;
47 uint64_t state;
48 unsigned int nr_threads;
49 char health_sock_path[PATH_MAX];
50 /* For consumer health only */
51 enum lttng_health_consumerd consumerd_type;
52 struct lttng_health_thread thread[LTTNG_FLEXIBLE_ARRAY_MEMBER_LENGTH];
53 };
54
55 static const char *get_sessiond_thread_name(health_type_sessiond type)
56 {
57 switch (type) {
58 case HEALTH_SESSIOND_TYPE_CMD:
59 return "Session daemon command";
60 case HEALTH_SESSIOND_TYPE_APP_MANAGE:
61 return "Session daemon application manager";
62 case HEALTH_SESSIOND_TYPE_APP_REG:
63 return "Session daemon application registration";
64 case HEALTH_SESSIOND_TYPE_KERNEL:
65 return "Session daemon kernel";
66 case HEALTH_SESSIOND_TYPE_CONSUMER:
67 return "Session daemon consumer manager";
68 case HEALTH_SESSIOND_TYPE_APP_MANAGE_NOTIFY:
69 return "Session daemon application notification manager";
70 case HEALTH_SESSIOND_TYPE_APP_REG_DISPATCH:
71 return "Session daemon application registration dispatcher";
72 case HEALTH_SESSIOND_TYPE_NOTIFICATION:
73 return "Session daemon notification";
74 case HEALTH_SESSIOND_TYPE_ROTATION:
75 return "Session daemon rotation manager";
76 case HEALTH_SESSIOND_TYPE_TIMER:
77 return "Session daemon timer manager";
78 case HEALTH_SESSIOND_TYPE_ACTION_EXECUTOR:
79 return "Session daemon trigger action executor";
80 case NR_HEALTH_SESSIOND_TYPES:
81 abort();
82 }
83
84 abort();
85 };
86
87 static const char *get_consumerd_thread_name(health_type_consumerd type)
88 {
89 switch (type) {
90 case HEALTH_CONSUMERD_TYPE_CHANNEL:
91 return "Consumer daemon channel";
92 case HEALTH_CONSUMERD_TYPE_METADATA:
93 return "Consumer daemon metadata";
94 case HEALTH_CONSUMERD_TYPE_DATA:
95 return "Consumer daemon data";
96 case HEALTH_CONSUMERD_TYPE_SESSIOND:
97 return "Consumer daemon session daemon command manager";
98 case HEALTH_CONSUMERD_TYPE_METADATA_TIMER:
99 return "Consumer daemon metadata timer";
100 case NR_HEALTH_CONSUMERD_TYPES:
101 abort();
102 }
103
104 abort();
105 };
106
107 static const char *get_relayd_thread_name(health_type_relayd type)
108 {
109 switch (type) {
110 case HEALTH_RELAYD_TYPE_DISPATCHER:
111 return "Relay daemon dispatcher";
112 case HEALTH_RELAYD_TYPE_WORKER:
113 return "Relay daemon worker";
114 case HEALTH_RELAYD_TYPE_LISTENER:
115 return "Relay daemon listener";
116 case HEALTH_RELAYD_TYPE_LIVE_DISPATCHER:
117 return "Relay daemon live dispatcher";
118 case HEALTH_RELAYD_TYPE_LIVE_WORKER:
119 return "Relay daemon live worker";
120 case HEALTH_RELAYD_TYPE_LIVE_LISTENER:
121 return "Relay daemon live listener";
122 case NR_HEALTH_RELAYD_TYPES:
123 abort();
124 }
125
126 abort();
127 }
128
129 static const char *get_thread_name(int comp, int nr)
130 {
131 switch (comp) {
132 case HEALTH_COMPONENT_SESSIOND:
133 return get_sessiond_thread_name((health_type_sessiond) nr);
134 case HEALTH_COMPONENT_CONSUMERD:
135 return get_consumerd_thread_name((health_type_consumerd) nr);
136 case HEALTH_COMPONENT_RELAYD:
137 return get_relayd_thread_name((health_type_relayd) nr);
138 case NR_HEALTH_COMPONENT:
139 abort();
140 }
141
142 abort();
143 }
144
145 /*
146 * Set health socket path.
147 *
148 * Returns 0 on success or a negative errno.
149 */
150 static int set_health_socket_path(struct lttng_health *lh, int tracing_group)
151 {
152 uid_t uid;
153 const char *home;
154 int ret;
155 /* Global and home format strings */
156 const char *global_str, *home_str;
157
158 switch (lh->component) {
159 case HEALTH_COMPONENT_SESSIOND:
160 global_str = DEFAULT_GLOBAL_HEALTH_UNIX_SOCK;
161 home_str = DEFAULT_HOME_HEALTH_UNIX_SOCK;
162 break;
163 case HEALTH_COMPONENT_CONSUMERD:
164 switch (lh->consumerd_type) {
165 case LTTNG_HEALTH_CONSUMERD_UST_32:
166 global_str = DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK;
167 home_str = DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK;
168 break;
169 case LTTNG_HEALTH_CONSUMERD_UST_64:
170 global_str = DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK;
171 home_str = DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK;
172 break;
173 case LTTNG_HEALTH_CONSUMERD_KERNEL:
174 global_str = DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK;
175 home_str = DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK;
176 break;
177 default:
178 return -EINVAL;
179 }
180 break;
181 case HEALTH_COMPONENT_RELAYD:
182 if (lh->health_sock_path[0] == '\0') {
183 return -EINVAL;
184 } else {
185 return 0;
186 }
187 break; /* Unreached */
188 default:
189 return -EINVAL;
190 }
191
192 uid = getuid();
193
194 if (uid == 0 || tracing_group) {
195 ret = lttng_strncpy(lh->health_sock_path, global_str, sizeof(lh->health_sock_path));
196 return ret == 0 ? 0 : -EINVAL;
197 }
198
199 /*
200 * With GNU C < 2.1, snprintf returns -1 if the target buffer
201 * is too small; With GNU C >= 2.1, snprintf returns the
202 * required size (excluding closing null).
203 */
204 home = utils_get_home_dir();
205 if (home == nullptr) {
206 /* Fallback in /tmp */
207 home = "/tmp";
208 }
209
210 DIAGNOSTIC_PUSH
211 DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
212 ret = snprintf(lh->health_sock_path, sizeof(lh->health_sock_path), home_str, home);
213 DIAGNOSTIC_POP
214 if ((ret < 0) || (ret >= sizeof(lh->health_sock_path))) {
215 return -ENOMEM;
216 }
217
218 return 0;
219 }
220
221 static struct lttng_health *lttng_health_create(enum health_component hc, unsigned int nr_threads)
222 {
223 struct lttng_health *lh;
224 int i;
225
226 lh = zmalloc<lttng_health>(sizeof(*lh) + sizeof(lh->thread[0]) * nr_threads);
227 if (!lh) {
228 return nullptr;
229 }
230
231 lh->component = hc;
232 lh->state = UINT64_MAX; /* All bits in error initially */
233 lh->nr_threads = nr_threads;
234 for (i = 0; i < nr_threads; i++) {
235 lh->thread[i].p = lh;
236 }
237 return lh;
238 }
239
240 struct lttng_health *lttng_health_create_sessiond(void)
241 {
242 struct lttng_health *lh;
243
244 lh = lttng_health_create(HEALTH_COMPONENT_SESSIOND, NR_HEALTH_SESSIOND_TYPES);
245 if (!lh) {
246 return nullptr;
247 }
248 return lh;
249 }
250
251 struct lttng_health *lttng_health_create_consumerd(enum lttng_health_consumerd consumerd)
252 {
253 struct lttng_health *lh;
254
255 lh = lttng_health_create(HEALTH_COMPONENT_CONSUMERD, NR_HEALTH_CONSUMERD_TYPES);
256 if (!lh) {
257 return nullptr;
258 }
259 lh->consumerd_type = consumerd;
260 return lh;
261 }
262
263 struct lttng_health *lttng_health_create_relayd(const char *path)
264 {
265 int ret;
266 struct lttng_health *lh = nullptr;
267
268 if (!path) {
269 goto error;
270 }
271
272 lh = lttng_health_create(HEALTH_COMPONENT_RELAYD, NR_HEALTH_RELAYD_TYPES);
273 if (!lh) {
274 goto error;
275 }
276
277 ret = lttng_strncpy(lh->health_sock_path, path, sizeof(lh->health_sock_path));
278 if (ret) {
279 goto error;
280 }
281
282 return lh;
283
284 error:
285 free(lh);
286 return nullptr;
287 }
288
289 void lttng_health_destroy(struct lttng_health *lh)
290 {
291 free(lh);
292 }
293
294 int lttng_health_query(struct lttng_health *health)
295 {
296 int sock, ret, i, tracing_group;
297 struct health_comm_msg msg;
298 struct health_comm_reply reply;
299
300 if (!health) {
301 return -EINVAL;
302 }
303
304 tracing_group = lttng_check_tracing_group();
305 retry:
306 ret = set_health_socket_path(health, tracing_group);
307 if (ret) {
308 goto error;
309 }
310 /* Connect to component */
311 sock = lttcomm_connect_unix_sock(health->health_sock_path);
312 if (sock < 0) {
313 if (tracing_group) {
314 /* For tracing group, fallback to per-user */
315 tracing_group = 0;
316 goto retry;
317 }
318 ret = -1;
319 goto error;
320 }
321
322 memset(&msg, 0, sizeof(msg));
323 msg.cmd = HEALTH_CMD_CHECK;
324
325 ret = lttcomm_send_unix_sock(sock, (void *) &msg, sizeof(msg));
326 if (ret < 0) {
327 ret = -1;
328 goto close_error;
329 }
330
331 ret = lttcomm_recv_unix_sock(sock, (void *) &reply, sizeof(reply));
332 if (ret < 0) {
333 ret = -1;
334 goto close_error;
335 }
336
337 health->state = reply.ret_code;
338 for (i = 0; i < health->nr_threads; i++) {
339 if (health->state & (1ULL << i)) {
340 health->thread[i].state = -1;
341 } else {
342 health->thread[i].state = 0;
343 }
344 }
345
346 close_error:
347 {
348 int closeret;
349
350 closeret = close(sock);
351 LTTNG_ASSERT(!closeret);
352 }
353
354 error:
355 if (ret >= 0)
356 ret = 0;
357 return ret;
358 }
359
360 int lttng_health_state(const struct lttng_health *health)
361 {
362 if (!health) {
363 return -EINVAL;
364 }
365
366 if (health->state == 0) {
367 return 0;
368 } else {
369 return -1;
370 }
371 }
372
373 int lttng_health_get_nr_threads(const struct lttng_health *health)
374 {
375 if (!health) {
376 return -EINVAL;
377 }
378 return health->nr_threads;
379 }
380
381 const struct lttng_health_thread *lttng_health_get_thread(const struct lttng_health *health,
382 unsigned int nth_thread)
383 {
384 if (!health || nth_thread >= health->nr_threads) {
385 return nullptr;
386 }
387 return &health->thread[nth_thread];
388 }
389
390 int lttng_health_thread_state(const struct lttng_health_thread *thread)
391 {
392 if (!thread) {
393 return -EINVAL;
394 }
395 return thread->state;
396 }
397
398 const char *lttng_health_thread_name(const struct lttng_health_thread *thread)
399 {
400 unsigned int nr;
401
402 if (!thread) {
403 return nullptr;
404 }
405 nr = thread - &thread->p->thread[0];
406 return get_thread_name(thread->p->component, nr);
407 }
This page took 0.036542 seconds and 4 git commands to generate.