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