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