Fix: syscall event rule: emission sites not compared in is_equal
[lttng-tools.git] / src / bin / lttng-relayd / session.cpp
1 /*
2 * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
3 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
4 * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-only
7 *
8 */
9
10 #define _LGPL_SOURCE
11 #include "ctf-trace.hpp"
12 #include "lttng-relayd.hpp"
13 #include "session.hpp"
14 #include "sessiond-trace-chunks.hpp"
15 #include "stream.hpp"
16 #include "utils.hpp"
17
18 #include <common/common.hpp>
19 #include <common/compat/path.hpp>
20 #include <common/defaults.hpp>
21 #include <common/fd-tracker/utils.hpp>
22 #include <common/time.hpp>
23 #include <common/urcu.hpp>
24 #include <common/utils.hpp>
25 #include <common/uuid.hpp>
26
27 #include <sys/stat.h>
28 #include <urcu/rculist.h>
29
30 /* Global session id used in the session creation. */
31 static uint64_t last_relay_session_id;
32 static pthread_mutex_t last_relay_session_id_lock = PTHREAD_MUTEX_INITIALIZER;
33
34 static int init_session_output_path_group_by_host(struct relay_session *session)
35 {
36 /*
37 * session_directory:
38 *
39 * if base_path is \0'
40 * hostname/session_name
41 * else
42 * hostname/base_path
43 */
44 char *session_directory = nullptr;
45 int ret = 0;
46
47 if (session->output_path[0] != '\0') {
48 goto end;
49 }
50 /*
51 * If base path is set, it overrides the session name for the
52 * session relative base path. No timestamp is appended if the
53 * base path is overridden.
54 *
55 * If the session name already contains the creation time (e.g.
56 * auto-<timestamp>, don't append yet another timestamp after
57 * the session name in the generated path.
58 *
59 * Otherwise, generate the path with session_name-<timestamp>.
60 */
61 if (session->base_path[0] != '\0') {
62 ret = asprintf(&session_directory, "%s/%s", session->hostname, session->base_path);
63 } else if (session->session_name_contains_creation_time) {
64 ret = asprintf(
65 &session_directory, "%s/%s", session->hostname, session->session_name);
66 } else {
67 char session_creation_datetime[DATETIME_STR_LEN];
68
69 ret = time_to_datetime_str(LTTNG_OPTIONAL_GET(session->creation_time),
70 session_creation_datetime,
71 sizeof(session_creation_datetime));
72 if (ret) {
73 ERR("Failed to format session creation timestamp while initializing session output directory handle");
74 ret = -1;
75 goto end;
76 }
77
78 ret = asprintf(&session_directory,
79 "%s/%s-%s",
80 session->hostname,
81 session->session_name,
82 session_creation_datetime);
83 }
84 if (ret < 0) {
85 PERROR("Failed to format session directory name");
86 goto end;
87 }
88
89 if (strlen(session_directory) >= LTTNG_PATH_MAX) {
90 ERR("Session output directory exceeds maximal length");
91 ret = -1;
92 goto end;
93 }
94 strcpy(session->output_path, session_directory);
95 ret = 0;
96
97 end:
98 free(session_directory);
99 return ret;
100 }
101
102 static int init_session_output_path_group_by_session(struct relay_session *session)
103 {
104 /*
105 * session_directory:
106 *
107 * session_name/hostname-creation_time/base_path
108 *
109 * For session name including the datetime, use it as the complete name
110 * since. Do not perform modification on it since the datetime is an
111 * integral part of the name and how a user identify a session.
112 */
113 int ret = 0;
114 char *session_directory = nullptr;
115 char creation_datetime[DATETIME_STR_LEN];
116
117 if (session->output_path[0] != '\0') {
118 /* output_path as been generated already */
119 goto end;
120 }
121
122 ret = time_to_datetime_str(LTTNG_OPTIONAL_GET(session->creation_time),
123 creation_datetime,
124 sizeof(creation_datetime));
125 if (ret) {
126 ERR("Failed to format session creation timestamp while initializing session output directory handle");
127 ret = -1;
128 goto end;
129 }
130
131 ret = asprintf(&session_directory,
132 "%s/%s-%s%s%s",
133 session->session_name,
134 session->hostname,
135 creation_datetime,
136 session->base_path[0] != '\0' ? "/" : "",
137 session->base_path);
138 if (ret < 0) {
139 PERROR("Failed to format session directory name");
140 goto end;
141 }
142
143 if (strlen(session_directory) >= LTTNG_PATH_MAX) {
144 ERR("Session output directory exceeds maximal length");
145 ret = -1;
146 goto end;
147 }
148
149 strcpy(session->output_path, session_directory);
150 ret = 0;
151
152 end:
153 free(session_directory);
154 return ret;
155 }
156
157 static int init_session_output_path(struct relay_session *session)
158 {
159 int ret;
160
161 switch (opt_group_output_by) {
162 case RELAYD_GROUP_OUTPUT_BY_HOST:
163 ret = init_session_output_path_group_by_host(session);
164 break;
165 case RELAYD_GROUP_OUTPUT_BY_SESSION:
166 ret = init_session_output_path_group_by_session(session);
167 break;
168 case RELAYD_GROUP_OUTPUT_BY_UNKNOWN:
169 default:
170 abort();
171 break;
172 }
173
174 return ret;
175 }
176
177 static struct lttng_directory_handle *
178 session_create_output_directory_handle(struct relay_session *session)
179 {
180 int ret;
181 /*
182 * relayd_output_path/session_directory
183 * e.g. /home/user/lttng-traces/hostname/session_name
184 */
185 char *full_session_path = nullptr;
186 struct lttng_directory_handle *handle = nullptr;
187
188 pthread_mutex_lock(&session->lock);
189 full_session_path = create_output_path(session->output_path);
190 if (!full_session_path) {
191 goto end;
192 }
193
194 ret = utils_mkdir_recursive(full_session_path, S_IRWXU | S_IRWXG, -1, -1);
195 if (ret) {
196 ERR("Failed to create session output path \"%s\"", full_session_path);
197 goto end;
198 }
199
200 handle = fd_tracker_create_directory_handle(the_fd_tracker, full_session_path);
201 end:
202 pthread_mutex_unlock(&session->lock);
203 free(full_session_path);
204 return handle;
205 }
206
207 static int session_set_anonymous_chunk(struct relay_session *session)
208 {
209 int ret = 0;
210 struct lttng_trace_chunk *chunk = nullptr;
211 enum lttng_trace_chunk_status status;
212 struct lttng_directory_handle *output_directory;
213
214 output_directory = session_create_output_directory_handle(session);
215 if (!output_directory) {
216 goto end;
217 }
218
219 chunk = lttng_trace_chunk_create_anonymous();
220 if (!chunk) {
221 goto end;
222 }
223
224 lttng_trace_chunk_set_fd_tracker(chunk, the_fd_tracker);
225 status = lttng_trace_chunk_set_credentials_current_user(chunk);
226 if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
227 ret = -1;
228 goto end;
229 }
230
231 status = lttng_trace_chunk_set_as_owner(chunk, output_directory);
232 if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
233 ret = -1;
234 goto end;
235 }
236
237 session->current_trace_chunk = chunk;
238 chunk = nullptr;
239 end:
240 lttng_trace_chunk_put(chunk);
241 lttng_directory_handle_put(output_directory);
242 return ret;
243 }
244
245 /*
246 * Check if a name is safe to use in a path.
247 *
248 * A name that is deemed "path-safe":
249 * - Does not contains a path separator (/ or \, platform dependant),
250 * - Does not start with a '.' (hidden file/folder),
251 * - Is not empty.
252 */
253 static bool is_name_path_safe(const char *name)
254 {
255 const size_t name_len = strlen(name);
256
257 /* Not empty. */
258 if (name_len == 0) {
259 WARN("An empty name is not allowed to be used in a path");
260 return false;
261 }
262 /* Does not start with '.'. */
263 if (name[0] == '.') {
264 WARN("Name \"%s\" is not allowed to be used in a path since it starts with '.'",
265 name);
266 return false;
267 }
268 /* Does not contain a path-separator. */
269 if (strchr(name, LTTNG_PATH_SEPARATOR)) {
270 WARN("Name \"%s\" is not allowed to be used in a path since it contains a path separator",
271 name);
272 return false;
273 }
274
275 return true;
276 }
277
278 /*
279 * Create a new session by assigning a new session ID.
280 *
281 * Return allocated session or else NULL.
282 */
283 struct relay_session *session_create(const char *session_name,
284 const char *hostname,
285 const char *base_path,
286 uint32_t live_timer,
287 bool snapshot,
288 const lttng_uuid& sessiond_uuid,
289 const uint64_t *id_sessiond,
290 const uint64_t *current_chunk_id,
291 const time_t *creation_time,
292 uint32_t major,
293 uint32_t minor,
294 bool session_name_contains_creation_time)
295 {
296 int ret;
297 struct relay_session *session = nullptr;
298
299 LTTNG_ASSERT(session_name);
300 LTTNG_ASSERT(hostname);
301 LTTNG_ASSERT(base_path);
302
303 if (!is_name_path_safe(session_name)) {
304 ERR("Refusing to create session as the provided session name is not path-safe");
305 goto error;
306 }
307 if (!is_name_path_safe(hostname)) {
308 ERR("Refusing to create session as the provided hostname is not path-safe");
309 goto error;
310 }
311 if (strstr(base_path, "../")) {
312 ERR("Invalid session base path walks up the path hierarchy: \"%s\"", base_path);
313 goto error;
314 }
315
316 session = zmalloc<relay_session>();
317 if (!session) {
318 PERROR("Failed to allocate session");
319 goto error;
320 }
321
322 pthread_mutex_lock(&last_relay_session_id_lock);
323 session->id = ++last_relay_session_id;
324 pthread_mutex_unlock(&last_relay_session_id_lock);
325
326 lttng_ht_node_init_u64(&session->session_n, session->id);
327 urcu_ref_init(&session->ref);
328 CDS_INIT_LIST_HEAD(&session->recv_list);
329 pthread_mutex_init(&session->lock, nullptr);
330 pthread_mutex_init(&session->recv_list_lock, nullptr);
331
332 if (lttng_strncpy(session->session_name, session_name, sizeof(session->session_name))) {
333 WARN("Session name exceeds maximal allowed length");
334 goto error;
335 }
336 if (lttng_strncpy(session->hostname, hostname, sizeof(session->hostname))) {
337 WARN("Hostname exceeds maximal allowed length");
338 goto error;
339 }
340 if (lttng_strncpy(session->base_path, base_path, sizeof(session->base_path))) {
341 WARN("Base path exceeds maximal allowed length");
342 goto error;
343 }
344 if (creation_time) {
345 LTTNG_OPTIONAL_SET(&session->creation_time, *creation_time);
346 } else {
347 LTTNG_OPTIONAL_SET(&session->creation_time, time(nullptr));
348 if (session->creation_time.value == (time_t) -1) {
349 PERROR("Failed to sample session creation time");
350 goto error;
351 }
352 }
353 session->session_name_contains_creation_time = session_name_contains_creation_time;
354
355 session->ctf_traces_ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
356 if (!session->ctf_traces_ht) {
357 goto error;
358 }
359
360 session->major = major;
361 session->minor = minor;
362
363 session->live_timer = live_timer;
364 session->snapshot = snapshot;
365 session->sessiond_uuid = sessiond_uuid;
366
367 if (id_sessiond) {
368 LTTNG_OPTIONAL_SET(&session->id_sessiond, *id_sessiond);
369 }
370
371 if (major == 2 && minor >= 11) {
372 /* Only applies for 2.11+ peers using trace chunks. */
373 ret = init_session_output_path(session);
374 if (ret) {
375 goto error;
376 }
377 }
378
379 ret = sessiond_trace_chunk_registry_session_created(sessiond_trace_chunk_registry,
380 sessiond_uuid);
381 if (ret) {
382 goto error;
383 }
384
385 if (id_sessiond && current_chunk_id) {
386 enum lttng_trace_chunk_status chunk_status;
387 struct lttng_directory_handle *session_output_directory;
388
389 session->current_trace_chunk =
390 sessiond_trace_chunk_registry_get_chunk(sessiond_trace_chunk_registry,
391 session->sessiond_uuid,
392 session->id_sessiond.value,
393 *current_chunk_id);
394 if (!session->current_trace_chunk) {
395 char uuid_str[LTTNG_UUID_STR_LEN];
396
397 lttng_uuid_to_str(sessiond_uuid, uuid_str);
398 ERR("Could not find trace chunk: sessiond = {%s}, sessiond session id = %" PRIu64
399 ", trace chunk id = %" PRIu64,
400 uuid_str,
401 *id_sessiond,
402 *current_chunk_id);
403 goto error;
404 }
405
406 chunk_status = lttng_trace_chunk_get_session_output_directory_handle(
407 session->current_trace_chunk, &session_output_directory);
408 if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
409 goto error;
410 }
411
412 LTTNG_ASSERT(session_output_directory);
413 session->output_directory = session_output_directory;
414 } else if (!id_sessiond) {
415 /*
416 * Pre-2.11 peers will not announce trace chunks. An
417 * anonymous trace chunk which will remain set for the
418 * duration of the session is created.
419 */
420 ret = session_set_anonymous_chunk(session);
421 if (ret) {
422 goto error;
423 }
424 } else {
425 session->output_directory = session_create_output_directory_handle(session);
426 if (!session->output_directory) {
427 goto error;
428 }
429 }
430
431 lttng_ht_add_unique_u64(sessions_ht, &session->session_n);
432 return session;
433
434 error:
435 session_put(session);
436 return nullptr;
437 }
438
439 /* Should be called with RCU read-side lock held. */
440 bool session_get(struct relay_session *session)
441 {
442 return urcu_ref_get_unless_zero(&session->ref);
443 }
444
445 /*
446 * Lookup a session within the session hash table using the session id
447 * as key. A session reference is taken when a session is returned.
448 * session_put() must be called on that session.
449 *
450 * Return session or NULL if not found.
451 */
452 struct relay_session *session_get_by_id(uint64_t id)
453 {
454 struct relay_session *session = nullptr;
455 struct lttng_ht_node_u64 *node;
456 struct lttng_ht_iter iter;
457
458 lttng::urcu::read_lock_guard read_lock;
459 lttng_ht_lookup(sessions_ht, &id, &iter);
460 node = lttng_ht_iter_get_node_u64(&iter);
461 if (!node) {
462 DBG("Session find by ID %" PRIu64 " id NOT found", id);
463 goto end;
464 }
465 session = lttng::utils::container_of(node, &relay_session::session_n);
466 DBG("Session find by ID %" PRIu64 " id found", id);
467 if (!session_get(session)) {
468 session = nullptr;
469 }
470 end:
471 return session;
472 }
473
474 /*
475 * Check if any of the relay sessions originating from the same
476 * session daemon session have the 'ongoing_rotation' state set.
477 *
478 * The caller must hold the lock of session.
479 */
480 bool session_has_ongoing_rotation(const struct relay_session *session)
481 {
482 bool ongoing_rotation = false;
483 struct lttng_ht_iter iter;
484 struct relay_session *iterated_session;
485
486 ASSERT_LOCKED(session->lock);
487
488 if (!session->id_sessiond.is_set) {
489 /*
490 * The peer that created this session is too old to
491 * support rotations; we can assume no rotations are ongoing.
492 */
493 goto end;
494 }
495
496 if (session->ongoing_rotation) {
497 ongoing_rotation = true;
498 goto end;
499 }
500
501 /*
502 * Sample the 'ongoing_rotation' status of all relay sessions that
503 * originate from the same session daemon session.
504 */
505 {
506 lttng::urcu::read_lock_guard read_lock;
507
508 cds_lfht_for_each_entry (
509 sessions_ht->ht, &iter.iter, iterated_session, session_n.node) {
510 if (!session_get(iterated_session)) {
511 continue;
512 }
513
514 if (session == iterated_session) {
515 /* Skip this session. */
516 goto next_session_no_unlock;
517 }
518
519 pthread_mutex_lock(&iterated_session->lock);
520
521 if (!iterated_session->id_sessiond.is_set) {
522 /*
523 * Session belongs to a peer that doesn't support
524 * rotations.
525 */
526 goto next_session;
527 }
528
529 if (session->sessiond_uuid != iterated_session->sessiond_uuid) {
530 /* Sessions do not originate from the same sessiond. */
531 goto next_session;
532 }
533
534 if (LTTNG_OPTIONAL_GET(session->id_sessiond) !=
535 LTTNG_OPTIONAL_GET(iterated_session->id_sessiond)) {
536 /*
537 * Sessions do not originate from the same sessiond
538 * session.
539 */
540 goto next_session;
541 }
542
543 ongoing_rotation = iterated_session->ongoing_rotation;
544
545 next_session:
546 pthread_mutex_unlock(&iterated_session->lock);
547 next_session_no_unlock:
548 session_put(iterated_session);
549
550 if (ongoing_rotation) {
551 break;
552 }
553 }
554 }
555
556 end:
557 return ongoing_rotation;
558 }
559
560 static void rcu_destroy_session(struct rcu_head *rcu_head)
561 {
562 struct relay_session *session = caa_container_of(rcu_head, struct relay_session, rcu_node);
563 /*
564 * Since each trace has a reference on the session, it means
565 * that if we are at the point where we teardown the session, no
566 * trace belonging to that session exist at this point.
567 * Calling lttng_ht_destroy in call_rcu worker thread so we
568 * don't hold the RCU read-side lock while calling it.
569 */
570 lttng_ht_destroy(session->ctf_traces_ht);
571 free(session);
572 }
573
574 /*
575 * Delete session from the given hash table.
576 *
577 * Return lttng ht del error code being 0 on success and 1 on failure.
578 */
579 static int session_delete(struct relay_session *session)
580 {
581 struct lttng_ht_iter iter;
582
583 iter.iter.node = &session->session_n.node;
584 return lttng_ht_del(sessions_ht, &iter);
585 }
586
587 static void destroy_session(struct relay_session *session)
588 {
589 int ret;
590
591 ret = session_delete(session);
592 LTTNG_ASSERT(!ret);
593 lttng_trace_chunk_put(session->current_trace_chunk);
594 session->current_trace_chunk = nullptr;
595 lttng_trace_chunk_put(session->pending_closure_trace_chunk);
596 session->pending_closure_trace_chunk = nullptr;
597 ret = sessiond_trace_chunk_registry_session_destroyed(sessiond_trace_chunk_registry,
598 session->sessiond_uuid);
599 LTTNG_ASSERT(!ret);
600 lttng_directory_handle_put(session->output_directory);
601 session->output_directory = nullptr;
602 call_rcu(&session->rcu_node, rcu_destroy_session);
603 }
604
605 static void session_release(struct urcu_ref *ref)
606 {
607 struct relay_session *session = lttng::utils::container_of(ref, &relay_session::ref);
608
609 destroy_session(session);
610 }
611
612 void session_put(struct relay_session *session)
613 {
614 if (!session) {
615 return;
616 }
617 lttng::urcu::read_lock_guard read_lock;
618 urcu_ref_put(&session->ref, session_release);
619 }
620
621 int session_close(struct relay_session *session)
622 {
623 int ret = 0;
624 struct ctf_trace *trace;
625 struct lttng_ht_iter iter;
626 struct relay_stream *stream;
627
628 pthread_mutex_lock(&session->lock);
629 DBG("closing session %" PRIu64 ": is conn already closed %d",
630 session->id,
631 session->connection_closed);
632 session->connection_closed = true;
633 pthread_mutex_unlock(&session->lock);
634
635 {
636 lttng::urcu::read_lock_guard read_lock;
637
638 cds_lfht_for_each_entry (session->ctf_traces_ht->ht, &iter.iter, trace, node.node) {
639 ret = ctf_trace_close(trace);
640 if (ret) {
641 goto end;
642 }
643 }
644
645 cds_list_for_each_entry_rcu(stream, &session->recv_list, recv_node)
646 {
647 /* Close streams which have not been published yet. */
648 try_stream_close(stream);
649 }
650 }
651
652 end:
653 if (ret) {
654 return ret;
655 }
656
657 /* Put self-reference from create. */
658 session_put(session);
659 return ret;
660 }
661
662 int session_abort(struct relay_session *session)
663 {
664 int ret = 0;
665
666 if (!session) {
667 return 0;
668 }
669
670 pthread_mutex_lock(&session->lock);
671 DBG("aborting session %" PRIu64, session->id);
672 session->aborted = true;
673 pthread_mutex_unlock(&session->lock);
674 return ret;
675 }
676
677 void print_sessions()
678 {
679 struct lttng_ht_iter iter;
680 struct relay_session *session;
681
682 if (!sessions_ht) {
683 return;
684 }
685
686 {
687 lttng::urcu::read_lock_guard read_lock;
688
689 cds_lfht_for_each_entry (sessions_ht->ht, &iter.iter, session, session_n.node) {
690 if (!session_get(session)) {
691 continue;
692 }
693 DBG("session %p refcount %ld session %" PRIu64,
694 session,
695 session->ref.refcount,
696 session->id);
697 session_put(session);
698 }
699 }
700 }
This page took 0.042128 seconds and 5 git commands to generate.