Validate channel context mismatch across UST applications
[lttng-tools.git] / src / bin / lttng-sessiond / ust-registry.cpp
1 /*
2 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
9 #include <inttypes.h>
10
11 #include <common/common.h>
12 #include <common/hashtable/utils.h>
13 #include <lttng/lttng.h>
14
15 #include "ust-registry.h"
16 #include "ust-app.h"
17 #include "ust-field-utils.h"
18 #include "utils.h"
19 #include "lttng-sessiond.h"
20 #include "notification-thread-commands.h"
21
22 /*
23 * Hash table match function for event in the registry.
24 */
25 static int ht_match_event(struct cds_lfht_node *node, const void *_key)
26 {
27 const struct ust_registry_event *key;
28 struct ust_registry_event *event;
29
30 LTTNG_ASSERT(node);
31 LTTNG_ASSERT(_key);
32
33 event = caa_container_of(node, struct ust_registry_event, node.node);
34 LTTNG_ASSERT(event);
35 key = (ust_registry_event *) _key;
36
37 /* It has to be a perfect match. First, compare the event names. */
38 if (strncmp(event->name, key->name, sizeof(event->name))) {
39 goto no_match;
40 }
41
42 /* Compare log levels. */
43 if (event->loglevel_value != key->loglevel_value) {
44 goto no_match;
45 }
46
47 /* Compare the arrays of fields. */
48 if (!match_lttng_ust_ctl_field_array(event->fields, event->nr_fields,
49 key->fields, key->nr_fields)) {
50 goto no_match;
51 }
52
53 /* Compare model URI. */
54 if (event->model_emf_uri != NULL && key->model_emf_uri == NULL) {
55 goto no_match;
56 } else if(event->model_emf_uri == NULL && key->model_emf_uri != NULL) {
57 goto no_match;
58 } else if (event->model_emf_uri != NULL && key->model_emf_uri != NULL) {
59 if (strcmp(event->model_emf_uri, key->model_emf_uri)) {
60 goto no_match;
61 }
62 }
63
64 /* Match */
65 return 1;
66
67 no_match:
68 return 0;
69 }
70
71 static unsigned long ht_hash_event(const void *_key, unsigned long seed)
72 {
73 uint64_t hashed_key;
74 const struct ust_registry_event *key = (ust_registry_event *) _key;
75
76 LTTNG_ASSERT(key);
77
78 hashed_key = (uint64_t) hash_key_str(key->name, seed);
79
80 return hash_key_u64(&hashed_key, seed);
81 }
82
83 static int compare_enums(const struct ust_registry_enum *reg_enum_a,
84 const struct ust_registry_enum *reg_enum_b)
85 {
86 int ret = 0;
87 size_t i;
88
89 LTTNG_ASSERT(strcmp(reg_enum_a->name, reg_enum_b->name) == 0);
90 if (reg_enum_a->nr_entries != reg_enum_b->nr_entries) {
91 ret = -1;
92 goto end;
93 }
94 for (i = 0; i < reg_enum_a->nr_entries; i++) {
95 const struct lttng_ust_ctl_enum_entry *entries_a, *entries_b;
96
97 entries_a = &reg_enum_a->entries[i];
98 entries_b = &reg_enum_b->entries[i];
99 if (entries_a->start.value != entries_b->start.value) {
100 ret = -1;
101 goto end;
102 }
103 if (entries_a->end.value != entries_b->end.value) {
104 ret = -1;
105 goto end;
106 }
107 if (entries_a->start.signedness != entries_b->start.signedness) {
108 ret = -1;
109 goto end;
110 }
111 if (entries_a->end.signedness != entries_b->end.signedness) {
112 ret = -1;
113 goto end;
114 }
115
116 if (strcmp(entries_a->string, entries_b->string)) {
117 ret = -1;
118 goto end;
119 }
120 }
121 end:
122 return ret;
123 }
124
125 /*
126 * Hash table match function for enumerations in the session. Match is
127 * performed on enumeration name, and confirmed by comparing the enum
128 * entries.
129 */
130 static int ht_match_enum(struct cds_lfht_node *node, const void *_key)
131 {
132 struct ust_registry_enum *_enum;
133 const struct ust_registry_enum *key;
134
135 LTTNG_ASSERT(node);
136 LTTNG_ASSERT(_key);
137
138 _enum = caa_container_of(node, struct ust_registry_enum,
139 node.node);
140 LTTNG_ASSERT(_enum);
141 key = (ust_registry_enum *) _key;
142
143 if (strncmp(_enum->name, key->name, LTTNG_UST_ABI_SYM_NAME_LEN)) {
144 goto no_match;
145 }
146 if (compare_enums(_enum, key)) {
147 goto no_match;
148 }
149
150 /* Match. */
151 return 1;
152
153 no_match:
154 return 0;
155 }
156
157 /*
158 * Hash table match function for enumerations in the session. Match is
159 * performed by enumeration ID.
160 */
161 static int ht_match_enum_id(struct cds_lfht_node *node, const void *_key)
162 {
163 struct ust_registry_enum *_enum;
164 const struct ust_registry_enum *key = (ust_registry_enum *) _key;
165
166 LTTNG_ASSERT(node);
167 LTTNG_ASSERT(_key);
168
169 _enum = caa_container_of(node, struct ust_registry_enum, node.node);
170 LTTNG_ASSERT(_enum);
171
172 if (_enum->id != key->id) {
173 goto no_match;
174 }
175
176 /* Match. */
177 return 1;
178
179 no_match:
180 return 0;
181 }
182
183 /*
184 * Hash table hash function for enumerations in the session. The
185 * enumeration name is used for hashing.
186 */
187 static unsigned long ht_hash_enum(void *_key, unsigned long seed)
188 {
189 struct ust_registry_enum *key = (ust_registry_enum *) _key;
190
191 LTTNG_ASSERT(key);
192 return hash_key_str(key->name, seed);
193 }
194
195 /*
196 * Return negative value on error, 0 if OK.
197 *
198 * TODO: we could add stricter verification of more types to catch
199 * errors in liblttng-ust implementation earlier than consumption by the
200 * trace reader.
201 */
202 static
203 int validate_event_field(struct lttng_ust_ctl_field *field,
204 const char *event_name,
205 struct ust_app *app)
206 {
207 int ret = 0;
208
209 switch(field->type.atype) {
210 case lttng_ust_ctl_atype_integer:
211 case lttng_ust_ctl_atype_enum:
212 case lttng_ust_ctl_atype_array:
213 case lttng_ust_ctl_atype_sequence:
214 case lttng_ust_ctl_atype_string:
215 case lttng_ust_ctl_atype_variant:
216 case lttng_ust_ctl_atype_array_nestable:
217 case lttng_ust_ctl_atype_sequence_nestable:
218 case lttng_ust_ctl_atype_enum_nestable:
219 case lttng_ust_ctl_atype_variant_nestable:
220 break;
221 case lttng_ust_ctl_atype_struct:
222 if (field->type.u.legacy._struct.nr_fields != 0) {
223 WARN("Unsupported non-empty struct field.");
224 ret = -EINVAL;
225 goto end;
226 }
227 break;
228 case lttng_ust_ctl_atype_struct_nestable:
229 if (field->type.u.struct_nestable.nr_fields != 0) {
230 WARN("Unsupported non-empty struct field.");
231 ret = -EINVAL;
232 goto end;
233 }
234 break;
235
236 case lttng_ust_ctl_atype_float:
237 switch (field->type.u._float.mant_dig) {
238 case 0:
239 WARN("UST application '%s' (pid: %d) has unknown float mantissa '%u' "
240 "in field '%s', rejecting event '%s'",
241 app->name, app->pid,
242 field->type.u._float.mant_dig,
243 field->name,
244 event_name);
245 ret = -EINVAL;
246 goto end;
247 default:
248 break;
249 }
250 break;
251
252 default:
253 ret = -ENOENT;
254 goto end;
255 }
256 end:
257 return ret;
258 }
259
260 static
261 int validate_event_fields(size_t nr_fields, struct lttng_ust_ctl_field *fields,
262 const char *event_name, struct ust_app *app)
263 {
264 unsigned int i;
265
266 for (i = 0; i < nr_fields; i++) {
267 if (validate_event_field(&fields[i], event_name, app) < 0)
268 return -EINVAL;
269 }
270 return 0;
271 }
272
273 /*
274 * Allocate event and initialize it. This does NOT set a valid event id from a
275 * registry.
276 */
277 static struct ust_registry_event *alloc_event(int session_objd,
278 int channel_objd, char *name, char *sig, size_t nr_fields,
279 struct lttng_ust_ctl_field *fields, int loglevel_value,
280 char *model_emf_uri, struct ust_app *app)
281 {
282 struct ust_registry_event *event = NULL;
283
284 /*
285 * Ensure that the field content is valid.
286 */
287 if (validate_event_fields(nr_fields, fields, name, app) < 0) {
288 return NULL;
289 }
290
291 event = (ust_registry_event *) zmalloc(sizeof(*event));
292 if (!event) {
293 PERROR("zmalloc ust registry event");
294 goto error;
295 }
296
297 event->session_objd = session_objd;
298 event->channel_objd = channel_objd;
299 /* Allocated by ustctl. */
300 event->signature = sig;
301 event->nr_fields = nr_fields;
302 event->fields = fields;
303 event->loglevel_value = loglevel_value;
304 event->model_emf_uri = model_emf_uri;
305 if (name) {
306 /* Copy event name and force NULL byte. */
307 strncpy(event->name, name, sizeof(event->name));
308 event->name[sizeof(event->name) - 1] = '\0';
309 }
310 cds_lfht_node_init(&event->node.node);
311
312 error:
313 return event;
314 }
315
316 /*
317 * Free event data structure. This does NOT delete it from any hash table. It's
318 * safe to pass a NULL pointer. This shoudl be called inside a call RCU if the
319 * event is previously deleted from a rcu hash table.
320 */
321 static void destroy_event(struct ust_registry_event *event)
322 {
323 if (!event) {
324 return;
325 }
326
327 free(event->fields);
328 free(event->model_emf_uri);
329 free(event->signature);
330 free(event);
331 }
332
333 /*
334 * Destroy event function call of the call RCU.
335 */
336 static void destroy_event_rcu(struct rcu_head *head)
337 {
338 struct lttng_ht_node_u64 *node =
339 caa_container_of(head, struct lttng_ht_node_u64, head);
340 struct ust_registry_event *event =
341 caa_container_of(node, struct ust_registry_event, node);
342
343 destroy_event(event);
344 }
345
346 /*
347 * Find an event using the name and signature in the given registry. RCU read
348 * side lock MUST be acquired before calling this function and as long as the
349 * event reference is kept by the caller.
350 *
351 * On success, the event pointer is returned else NULL.
352 */
353 struct ust_registry_event *ust_registry_find_event(
354 struct ust_registry_channel *chan, char *name, char *sig)
355 {
356 struct lttng_ht_node_u64 *node;
357 struct lttng_ht_iter iter;
358 struct ust_registry_event *event = NULL;
359 struct ust_registry_event key;
360
361 LTTNG_ASSERT(chan);
362 LTTNG_ASSERT(name);
363 LTTNG_ASSERT(sig);
364
365 /* Setup key for the match function. */
366 strncpy(key.name, name, sizeof(key.name));
367 key.name[sizeof(key.name) - 1] = '\0';
368 key.signature = sig;
369
370 cds_lfht_lookup(chan->ht->ht, chan->ht->hash_fct(&key, lttng_ht_seed),
371 chan->ht->match_fct, &key, &iter.iter);
372 node = lttng_ht_iter_get_node_u64(&iter);
373 if (!node) {
374 goto end;
375 }
376 event = caa_container_of(node, struct ust_registry_event, node);
377
378 end:
379 return event;
380 }
381
382 /*
383 * Create a ust_registry_event from the given parameters and add it to the
384 * registry hash table. If event_id is valid, it is set with the newly created
385 * event id.
386 *
387 * On success, return 0 else a negative value. The created event MUST be unique
388 * so on duplicate entry -EINVAL is returned. On error, event_id is untouched.
389 *
390 * Should be called with session registry mutex held.
391 */
392 int ust_registry_create_event(struct ust_registry_session *session,
393 uint64_t chan_key, int session_objd, int channel_objd, char *name,
394 char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields,
395 int loglevel_value, char *model_emf_uri, int buffer_type,
396 uint32_t *event_id_p, struct ust_app *app)
397 {
398 int ret;
399 uint32_t event_id;
400 struct cds_lfht_node *nptr;
401 struct ust_registry_event *event = NULL;
402 struct ust_registry_channel *chan;
403
404 LTTNG_ASSERT(session);
405 LTTNG_ASSERT(name);
406 LTTNG_ASSERT(sig);
407 LTTNG_ASSERT(event_id_p);
408
409 rcu_read_lock();
410
411 /*
412 * This should not happen but since it comes from the UST tracer, an
413 * external party, don't assert and simply validate values.
414 */
415 if (session_objd < 0 || channel_objd < 0) {
416 ret = -EINVAL;
417 goto error_free;
418 }
419
420 chan = ust_registry_channel_find(session, chan_key);
421 if (!chan) {
422 ret = -EINVAL;
423 goto error_free;
424 }
425
426 /* Check if we've reached the maximum possible id. */
427 if (ust_registry_is_max_id(chan->used_event_id)) {
428 ret = -ENOENT;
429 goto error_free;
430 }
431
432 event = alloc_event(session_objd, channel_objd, name, sig, nr_fields,
433 fields, loglevel_value, model_emf_uri, app);
434 if (!event) {
435 ret = -ENOMEM;
436 goto error_free;
437 }
438
439 DBG3("UST registry creating event with event: %s, sig: %s, id: %u, "
440 "chan_objd: %u, sess_objd: %u, chan_id: %u", event->name,
441 event->signature, event->id, event->channel_objd,
442 event->session_objd, chan->chan_id);
443
444 /*
445 * This is an add unique with a custom match function for event. The node
446 * are matched using the event name and signature.
447 */
448 nptr = cds_lfht_add_unique(chan->ht->ht, chan->ht->hash_fct(event,
449 lttng_ht_seed), chan->ht->match_fct, event, &event->node.node);
450 if (nptr != &event->node.node) {
451 if (buffer_type == LTTNG_BUFFER_PER_UID) {
452 /*
453 * This is normal, we just have to send the event id of the
454 * returned node and make sure we destroy the previously allocated
455 * event object.
456 */
457 destroy_event(event);
458 event = caa_container_of(nptr, struct ust_registry_event,
459 node.node);
460 LTTNG_ASSERT(event);
461 event_id = event->id;
462 } else {
463 ERR("UST registry create event add unique failed for event: %s, "
464 "sig: %s, id: %u, chan_objd: %u, sess_objd: %u",
465 event->name, event->signature, event->id,
466 event->channel_objd, event->session_objd);
467 ret = -EINVAL;
468 goto error_unlock;
469 }
470 } else {
471 /* Request next event id if the node was successfully added. */
472 event_id = event->id = ust_registry_get_next_event_id(chan);
473 }
474
475 *event_id_p = event_id;
476
477 if (!event->metadata_dumped) {
478 /* Append to metadata */
479 ret = ust_metadata_event_statedump(session, chan, event);
480 if (ret) {
481 ERR("Error appending event metadata (errno = %d)", ret);
482 rcu_read_unlock();
483 return ret;
484 }
485 }
486
487 rcu_read_unlock();
488 return 0;
489
490 error_free:
491 free(sig);
492 free(fields);
493 free(model_emf_uri);
494 error_unlock:
495 rcu_read_unlock();
496 destroy_event(event);
497 return ret;
498 }
499
500 /*
501 * For a given event in a registry, delete the entry and destroy the event.
502 * This MUST be called within a RCU read side lock section.
503 */
504 void ust_registry_destroy_event(struct ust_registry_channel *chan,
505 struct ust_registry_event *event)
506 {
507 int ret;
508 struct lttng_ht_iter iter;
509
510 LTTNG_ASSERT(chan);
511 LTTNG_ASSERT(event);
512
513 /* Delete the node first. */
514 iter.iter.node = &event->node.node;
515 ret = lttng_ht_del(chan->ht, &iter);
516 LTTNG_ASSERT(!ret);
517
518 call_rcu(&event->node.head, destroy_event_rcu);
519
520 return;
521 }
522
523 static void destroy_enum(struct ust_registry_enum *reg_enum)
524 {
525 if (!reg_enum) {
526 return;
527 }
528 free(reg_enum->entries);
529 free(reg_enum);
530 }
531
532 static void destroy_enum_rcu(struct rcu_head *head)
533 {
534 struct ust_registry_enum *reg_enum =
535 caa_container_of(head, struct ust_registry_enum, rcu_head);
536
537 destroy_enum(reg_enum);
538 }
539
540 /*
541 * Lookup enumeration by name and comparing enumeration entries.
542 * Needs to be called from RCU read-side critical section.
543 */
544 static struct ust_registry_enum *ust_registry_lookup_enum(
545 struct ust_registry_session *session,
546 const struct ust_registry_enum *reg_enum_lookup)
547 {
548 struct ust_registry_enum *reg_enum = NULL;
549 struct lttng_ht_node_str *node;
550 struct lttng_ht_iter iter;
551
552 cds_lfht_lookup(session->enums->ht,
553 ht_hash_enum((void *) reg_enum_lookup, lttng_ht_seed),
554 ht_match_enum, reg_enum_lookup, &iter.iter);
555 node = lttng_ht_iter_get_node_str(&iter);
556 if (!node) {
557 goto end;
558 }
559 reg_enum = caa_container_of(node, struct ust_registry_enum, node);
560 end:
561 return reg_enum;
562 }
563
564 /*
565 * Lookup enumeration by enum ID.
566 * Needs to be called from RCU read-side critical section.
567 */
568 struct ust_registry_enum *
569 ust_registry_lookup_enum_by_id(struct ust_registry_session *session,
570 const char *enum_name, uint64_t enum_id)
571 {
572 struct ust_registry_enum *reg_enum = NULL;
573 struct lttng_ht_node_str *node;
574 struct lttng_ht_iter iter;
575 struct ust_registry_enum reg_enum_lookup;
576
577 memset(&reg_enum_lookup, 0, sizeof(reg_enum_lookup));
578 strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
579 reg_enum_lookup.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
580 reg_enum_lookup.id = enum_id;
581 cds_lfht_lookup(session->enums->ht,
582 ht_hash_enum((void *) &reg_enum_lookup, lttng_ht_seed),
583 ht_match_enum_id, &reg_enum_lookup, &iter.iter);
584 node = lttng_ht_iter_get_node_str(&iter);
585 if (!node) {
586 goto end;
587 }
588 reg_enum = caa_container_of(node, struct ust_registry_enum, node);
589 end:
590 return reg_enum;
591 }
592
593 /*
594 * Create a ust_registry_enum from the given parameters and add it to the
595 * registry hash table, or find it if already there.
596 *
597 * On success, return 0 else a negative value.
598 *
599 * Should be called with session registry mutex held.
600 *
601 * We receive ownership of entries.
602 */
603 int ust_registry_create_or_find_enum(struct ust_registry_session *session,
604 int session_objd, char *enum_name,
605 struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries,
606 uint64_t *enum_id)
607 {
608 int ret = 0;
609 struct cds_lfht_node *nodep;
610 struct ust_registry_enum *reg_enum = NULL, *old_reg_enum;
611
612 LTTNG_ASSERT(session);
613 LTTNG_ASSERT(enum_name);
614
615 rcu_read_lock();
616
617 /*
618 * This should not happen but since it comes from the UST tracer, an
619 * external party, don't assert and simply validate values.
620 */
621 if (session_objd < 0) {
622 ret = -EINVAL;
623 goto end;
624 }
625
626 /* Check if the enumeration was already dumped */
627 reg_enum = (ust_registry_enum *) zmalloc(sizeof(*reg_enum));
628 if (!reg_enum) {
629 PERROR("zmalloc ust registry enumeration");
630 ret = -ENOMEM;
631 goto end;
632 }
633 strncpy(reg_enum->name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
634 reg_enum->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
635 /* entries will be owned by reg_enum. */
636 reg_enum->entries = entries;
637 reg_enum->nr_entries = nr_entries;
638 entries = NULL;
639
640 old_reg_enum = ust_registry_lookup_enum(session, reg_enum);
641 if (old_reg_enum) {
642 DBG("enum %s already in sess_objd: %u", enum_name, session_objd);
643 /* Fall through. Use prior enum. */
644 destroy_enum(reg_enum);
645 reg_enum = old_reg_enum;
646 } else {
647 DBG("UST registry creating enum: %s, sess_objd: %u",
648 enum_name, session_objd);
649 if (session->next_enum_id == -1ULL) {
650 ret = -EOVERFLOW;
651 destroy_enum(reg_enum);
652 goto end;
653 }
654 reg_enum->id = session->next_enum_id++;
655 cds_lfht_node_init(&reg_enum->node.node);
656 nodep = cds_lfht_add_unique(session->enums->ht,
657 ht_hash_enum(reg_enum, lttng_ht_seed),
658 ht_match_enum_id, reg_enum,
659 &reg_enum->node.node);
660 LTTNG_ASSERT(nodep == &reg_enum->node.node);
661 }
662 DBG("UST registry reply with enum %s with id %" PRIu64 " in sess_objd: %u",
663 enum_name, reg_enum->id, session_objd);
664 *enum_id = reg_enum->id;
665 end:
666 free(entries);
667 rcu_read_unlock();
668 return ret;
669 }
670
671 /*
672 * For a given enumeration in a registry, delete the entry and destroy
673 * the enumeration.
674 * This MUST be called within a RCU read side lock section.
675 */
676 static void ust_registry_destroy_enum(struct ust_registry_session *reg_session,
677 struct ust_registry_enum *reg_enum)
678 {
679 int ret;
680 struct lttng_ht_iter iter;
681
682 LTTNG_ASSERT(reg_session);
683 LTTNG_ASSERT(reg_enum);
684
685 /* Delete the node first. */
686 iter.iter.node = &reg_enum->node.node;
687 ret = lttng_ht_del(reg_session->enums, &iter);
688 LTTNG_ASSERT(!ret);
689 call_rcu(&reg_enum->rcu_head, destroy_enum_rcu);
690 }
691
692 /*
693 * We need to execute ht_destroy outside of RCU read-side critical
694 * section and outside of call_rcu thread, so we postpone its execution
695 * using ht_cleanup_push. It is simpler than to change the semantic of
696 * the many callers of delete_ust_app_session().
697 */
698 static
699 void destroy_channel_rcu(struct rcu_head *head)
700 {
701 struct ust_registry_channel *chan =
702 caa_container_of(head, struct ust_registry_channel, rcu_head);
703
704 if (chan->ht) {
705 ht_cleanup_push(chan->ht);
706 }
707 free(chan->ctx_fields);
708 free(chan);
709 }
710
711 /*
712 * Destroy every element of the registry and free the memory. This does NOT
713 * free the registry pointer since it might not have been allocated before so
714 * it's the caller responsability.
715 */
716 static void destroy_channel(struct ust_registry_channel *chan, bool notif)
717 {
718 struct lttng_ht_iter iter;
719 struct ust_registry_event *event;
720 enum lttng_error_code cmd_ret;
721
722 LTTNG_ASSERT(chan);
723
724 if (notif) {
725 cmd_ret = notification_thread_command_remove_channel(
726 the_notification_thread_handle,
727 chan->consumer_key, LTTNG_DOMAIN_UST);
728 if (cmd_ret != LTTNG_OK) {
729 ERR("Failed to remove channel from notification thread");
730 }
731 }
732
733 if (chan->ht) {
734 rcu_read_lock();
735 /* Destroy all event associated with this registry. */
736 cds_lfht_for_each_entry(
737 chan->ht->ht, &iter.iter, event, node.node) {
738 /* Delete the node from the ht and free it. */
739 ust_registry_destroy_event(chan, event);
740 }
741 rcu_read_unlock();
742 }
743 call_rcu(&chan->rcu_head, destroy_channel_rcu);
744 }
745
746 /*
747 * Initialize registry with default values.
748 */
749 int ust_registry_channel_add(struct ust_registry_session *session,
750 uint64_t key)
751 {
752 int ret = 0;
753 struct ust_registry_channel *chan;
754
755 LTTNG_ASSERT(session);
756
757 chan = (ust_registry_channel *) zmalloc(sizeof(*chan));
758 if (!chan) {
759 PERROR("zmalloc ust registry channel");
760 ret = -ENOMEM;
761 goto error_alloc;
762 }
763
764 chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
765 if (!chan->ht) {
766 ret = -ENOMEM;
767 goto error;
768 }
769
770 /* Set custom match function. */
771 chan->ht->match_fct = ht_match_event;
772 chan->ht->hash_fct = ht_hash_event;
773
774 /*
775 * Assign a channel ID right now since the event notification comes
776 * *before* the channel notify so the ID needs to be set at this point so
777 * the metadata can be dumped for that event.
778 */
779 if (ust_registry_is_max_id(session->used_channel_id)) {
780 ret = -1;
781 goto error;
782 }
783 chan->chan_id = ust_registry_get_next_chan_id(session);
784
785 rcu_read_lock();
786 lttng_ht_node_init_u64(&chan->node, key);
787 lttng_ht_add_unique_u64(session->channels, &chan->node);
788 rcu_read_unlock();
789
790 return 0;
791
792 error:
793 destroy_channel(chan, false);
794 error_alloc:
795 return ret;
796 }
797
798 /*
799 * Find a channel in the given registry. RCU read side lock MUST be acquired
800 * before calling this function and as long as the event reference is kept by
801 * the caller.
802 *
803 * On success, the pointer is returned else NULL.
804 */
805 struct ust_registry_channel *ust_registry_channel_find(
806 struct ust_registry_session *session, uint64_t key)
807 {
808 struct lttng_ht_node_u64 *node;
809 struct lttng_ht_iter iter;
810 struct ust_registry_channel *chan = NULL;
811
812 LTTNG_ASSERT(session);
813 LTTNG_ASSERT(session->channels);
814
815 DBG3("UST registry channel finding key %" PRIu64, key);
816
817 lttng_ht_lookup(session->channels, &key, &iter);
818 node = lttng_ht_iter_get_node_u64(&iter);
819 if (!node) {
820 goto end;
821 }
822 chan = caa_container_of(node, struct ust_registry_channel, node);
823
824 end:
825 return chan;
826 }
827
828 /*
829 * Remove channel using key from registry and free memory.
830 */
831 void ust_registry_channel_del_free(struct ust_registry_session *session,
832 uint64_t key, bool notif)
833 {
834 struct lttng_ht_iter iter;
835 struct ust_registry_channel *chan;
836 int ret;
837
838 LTTNG_ASSERT(session);
839
840 rcu_read_lock();
841 chan = ust_registry_channel_find(session, key);
842 if (!chan) {
843 rcu_read_unlock();
844 goto end;
845 }
846
847 iter.iter.node = &chan->node.node;
848 ret = lttng_ht_del(session->channels, &iter);
849 LTTNG_ASSERT(!ret);
850 rcu_read_unlock();
851 destroy_channel(chan, notif);
852
853 end:
854 return;
855 }
856
857 /*
858 * Initialize registry with default values and set the newly allocated session
859 * pointer to sessionp.
860 *
861 * Return 0 on success and sessionp is set or else return -1 and sessionp is
862 * kept untouched.
863 */
864 int ust_registry_session_init(struct ust_registry_session **sessionp,
865 struct ust_app *app,
866 uint32_t bits_per_long,
867 uint32_t uint8_t_alignment,
868 uint32_t uint16_t_alignment,
869 uint32_t uint32_t_alignment,
870 uint32_t uint64_t_alignment,
871 uint32_t long_alignment,
872 int byte_order,
873 uint32_t major,
874 uint32_t minor,
875 const char *root_shm_path,
876 const char *shm_path,
877 uid_t euid,
878 gid_t egid,
879 uint64_t tracing_id,
880 uid_t tracing_uid)
881 {
882 int ret;
883 struct ust_registry_session *session;
884
885 LTTNG_ASSERT(sessionp);
886
887 session = (ust_registry_session *) zmalloc(sizeof(*session));
888 if (!session) {
889 PERROR("zmalloc ust registry session");
890 goto error_alloc;
891 }
892
893 pthread_mutex_init(&session->lock, NULL);
894 session->bits_per_long = bits_per_long;
895 session->uint8_t_alignment = uint8_t_alignment;
896 session->uint16_t_alignment = uint16_t_alignment;
897 session->uint32_t_alignment = uint32_t_alignment;
898 session->uint64_t_alignment = uint64_t_alignment;
899 session->long_alignment = long_alignment;
900 session->byte_order = byte_order;
901 session->metadata_fd = -1;
902 session->uid = euid;
903 session->gid = egid;
904 session->next_enum_id = 0;
905 session->major = major;
906 session->minor = minor;
907 strncpy(session->root_shm_path, root_shm_path,
908 sizeof(session->root_shm_path));
909 session->root_shm_path[sizeof(session->root_shm_path) - 1] = '\0';
910 if (shm_path[0]) {
911 strncpy(session->shm_path, shm_path,
912 sizeof(session->shm_path));
913 session->shm_path[sizeof(session->shm_path) - 1] = '\0';
914 strncpy(session->metadata_path, shm_path,
915 sizeof(session->metadata_path));
916 session->metadata_path[sizeof(session->metadata_path) - 1] = '\0';
917 strncat(session->metadata_path, "/metadata",
918 sizeof(session->metadata_path)
919 - strlen(session->metadata_path) - 1);
920 }
921 if (session->shm_path[0]) {
922 ret = run_as_mkdir_recursive(session->shm_path,
923 S_IRWXU | S_IRWXG,
924 euid, egid);
925 if (ret) {
926 PERROR("run_as_mkdir_recursive");
927 goto error;
928 }
929 }
930 if (session->metadata_path[0]) {
931 /* Create metadata file */
932 ret = run_as_open(session->metadata_path,
933 O_WRONLY | O_CREAT | O_EXCL,
934 S_IRUSR | S_IWUSR, euid, egid);
935 if (ret < 0) {
936 PERROR("Opening metadata file");
937 goto error;
938 }
939 session->metadata_fd = ret;
940 }
941
942 session->enums = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
943 if (!session->enums) {
944 ERR("Failed to create enums hash table");
945 goto error;
946 }
947 /* hash/match functions are specified at call site. */
948 session->enums->match_fct = NULL;
949 session->enums->hash_fct = NULL;
950
951 session->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
952 if (!session->channels) {
953 goto error;
954 }
955
956 ret = lttng_uuid_generate(session->uuid);
957 if (ret) {
958 ERR("Failed to generate UST uuid (errno = %d)", ret);
959 goto error;
960 }
961
962 session->tracing_id = tracing_id;
963 session->tracing_uid = tracing_uid;
964
965 pthread_mutex_lock(&session->lock);
966 ret = ust_metadata_session_statedump(session, app, major, minor);
967 pthread_mutex_unlock(&session->lock);
968 if (ret) {
969 ERR("Failed to generate session metadata (errno = %d)", ret);
970 goto error;
971 }
972
973 *sessionp = session;
974
975 return 0;
976
977 error:
978 ust_registry_session_destroy(session);
979 free(session);
980 error_alloc:
981 return -1;
982 }
983
984 /*
985 * Destroy session registry. This does NOT free the given pointer since it
986 * might get passed as a reference. The registry lock should NOT be acquired.
987 */
988 void ust_registry_session_destroy(struct ust_registry_session *reg)
989 {
990 int ret;
991 struct lttng_ht_iter iter;
992 struct ust_registry_channel *chan;
993 struct ust_registry_enum *reg_enum;
994
995 if (!reg) {
996 return;
997 }
998
999 /* On error, EBUSY can be returned if lock. Code flow error. */
1000 ret = pthread_mutex_destroy(&reg->lock);
1001 LTTNG_ASSERT(!ret);
1002
1003 if (reg->channels) {
1004 rcu_read_lock();
1005 /* Destroy all event associated with this registry. */
1006 cds_lfht_for_each_entry(reg->channels->ht, &iter.iter, chan,
1007 node.node) {
1008 /* Delete the node from the ht and free it. */
1009 ret = lttng_ht_del(reg->channels, &iter);
1010 LTTNG_ASSERT(!ret);
1011 destroy_channel(chan, true);
1012 }
1013 rcu_read_unlock();
1014 ht_cleanup_push(reg->channels);
1015 }
1016
1017 free(reg->metadata);
1018 if (reg->metadata_fd >= 0) {
1019 ret = close(reg->metadata_fd);
1020 if (ret) {
1021 PERROR("close");
1022 }
1023 ret = run_as_unlink(reg->metadata_path,
1024 reg->uid, reg->gid);
1025 if (ret) {
1026 PERROR("unlink");
1027 }
1028 }
1029 if (reg->root_shm_path[0]) {
1030 /*
1031 * Try deleting the directory hierarchy.
1032 */
1033 (void) run_as_rmdir_recursive(reg->root_shm_path,
1034 reg->uid, reg->gid,
1035 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
1036 }
1037 /* Destroy the enum hash table */
1038 if (reg->enums) {
1039 rcu_read_lock();
1040 /* Destroy all enum entries associated with this registry. */
1041 cds_lfht_for_each_entry(reg->enums->ht, &iter.iter, reg_enum,
1042 node.node) {
1043 ust_registry_destroy_enum(reg, reg_enum);
1044 }
1045 rcu_read_unlock();
1046 ht_cleanup_push(reg->enums);
1047 }
1048 }
This page took 0.088537 seconds and 4 git commands to generate.