2013902e9effa52b6e3c38c1d95ef03b3f68221b
[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 break;
226 case ustctl_atype_struct:
227 if (field->type.u._struct.nr_fields != 0) {
228 WARN("Unsupported non-empty struct field.");
229 ret = -EINVAL;
230 goto end;
231 }
232 break;
233
234 case ustctl_atype_float:
235 switch (field->type.u.basic._float.mant_dig) {
236 case 0:
237 WARN("UST application '%s' (pid: %d) has unknown float mantissa '%u' "
238 "in field '%s', rejecting event '%s'",
239 app->name, app->pid,
240 field->type.u.basic._float.mant_dig,
241 field->name,
242 event_name);
243 ret = -EINVAL;
244 goto end;
245 default:
246 break;
247 }
248 break;
249
250 default:
251 ret = -ENOENT;
252 goto end;
253 }
254 end:
255 return ret;
256 }
257
258 static
259 int validate_event_fields(size_t nr_fields, struct ustctl_field *fields,
260 const char *event_name, struct ust_app *app)
261 {
262 unsigned int i;
263
264 for (i = 0; i < nr_fields; i++) {
265 if (validate_event_field(&fields[i], event_name, app) < 0)
266 return -EINVAL;
267 }
268 return 0;
269 }
270
271 /*
272 * Allocate event and initialize it. This does NOT set a valid event id from a
273 * registry.
274 */
275 static struct ust_registry_event *alloc_event(int session_objd,
276 int channel_objd, char *name, char *sig, size_t nr_fields,
277 struct ustctl_field *fields, int loglevel_value,
278 char *model_emf_uri, struct ust_app *app)
279 {
280 struct ust_registry_event *event = NULL;
281
282 /*
283 * Ensure that the field content is valid.
284 */
285 if (validate_event_fields(nr_fields, fields, name, app) < 0) {
286 return NULL;
287 }
288
289 event = zmalloc(sizeof(*event));
290 if (!event) {
291 PERROR("zmalloc ust registry event");
292 goto error;
293 }
294
295 event->session_objd = session_objd;
296 event->channel_objd = channel_objd;
297 /* Allocated by ustctl. */
298 event->signature = sig;
299 event->nr_fields = nr_fields;
300 event->fields = fields;
301 event->loglevel_value = loglevel_value;
302 event->model_emf_uri = model_emf_uri;
303 if (name) {
304 /* Copy event name and force NULL byte. */
305 strncpy(event->name, name, sizeof(event->name));
306 event->name[sizeof(event->name) - 1] = '\0';
307 }
308 cds_lfht_node_init(&event->node.node);
309
310 error:
311 return event;
312 }
313
314 /*
315 * Free event data structure. This does NOT delete it from any hash table. It's
316 * safe to pass a NULL pointer. This shoudl be called inside a call RCU if the
317 * event is previously deleted from a rcu hash table.
318 */
319 static void destroy_event(struct ust_registry_event *event)
320 {
321 if (!event) {
322 return;
323 }
324
325 free(event->fields);
326 free(event->model_emf_uri);
327 free(event->signature);
328 free(event);
329 }
330
331 /*
332 * Destroy event function call of the call RCU.
333 */
334 static void destroy_event_rcu(struct rcu_head *head)
335 {
336 struct lttng_ht_node_u64 *node =
337 caa_container_of(head, struct lttng_ht_node_u64, head);
338 struct ust_registry_event *event =
339 caa_container_of(node, struct ust_registry_event, node);
340
341 destroy_event(event);
342 }
343
344 /*
345 * Find an event using the name and signature in the given registry. RCU read
346 * side lock MUST be acquired before calling this function and as long as the
347 * event reference is kept by the caller.
348 *
349 * On success, the event pointer is returned else NULL.
350 */
351 struct ust_registry_event *ust_registry_find_event(
352 struct ust_registry_channel *chan, char *name, char *sig)
353 {
354 struct lttng_ht_node_u64 *node;
355 struct lttng_ht_iter iter;
356 struct ust_registry_event *event = NULL;
357 struct ust_registry_event key;
358
359 assert(chan);
360 assert(name);
361 assert(sig);
362
363 /* Setup key for the match function. */
364 strncpy(key.name, name, sizeof(key.name));
365 key.name[sizeof(key.name) - 1] = '\0';
366 key.signature = sig;
367
368 cds_lfht_lookup(chan->ht->ht, chan->ht->hash_fct(&key, lttng_ht_seed),
369 chan->ht->match_fct, &key, &iter.iter);
370 node = lttng_ht_iter_get_node_u64(&iter);
371 if (!node) {
372 goto end;
373 }
374 event = caa_container_of(node, struct ust_registry_event, node);
375
376 end:
377 return event;
378 }
379
380 /*
381 * Create a ust_registry_event from the given parameters and add it to the
382 * registry hash table. If event_id is valid, it is set with the newly created
383 * event id.
384 *
385 * On success, return 0 else a negative value. The created event MUST be unique
386 * so on duplicate entry -EINVAL is returned. On error, event_id is untouched.
387 *
388 * Should be called with session registry mutex held.
389 */
390 int ust_registry_create_event(struct ust_registry_session *session,
391 uint64_t chan_key, int session_objd, int channel_objd, char *name,
392 char *sig, size_t nr_fields, struct ustctl_field *fields,
393 int loglevel_value, char *model_emf_uri, int buffer_type,
394 uint32_t *event_id_p, struct ust_app *app)
395 {
396 int ret;
397 uint32_t event_id;
398 struct cds_lfht_node *nptr;
399 struct ust_registry_event *event = NULL;
400 struct ust_registry_channel *chan;
401
402 assert(session);
403 assert(name);
404 assert(sig);
405 assert(event_id_p);
406
407 rcu_read_lock();
408
409 /*
410 * This should not happen but since it comes from the UST tracer, an
411 * external party, don't assert and simply validate values.
412 */
413 if (session_objd < 0 || channel_objd < 0) {
414 ret = -EINVAL;
415 goto error_free;
416 }
417
418 chan = ust_registry_channel_find(session, chan_key);
419 if (!chan) {
420 ret = -EINVAL;
421 goto error_free;
422 }
423
424 /* Check if we've reached the maximum possible id. */
425 if (ust_registry_is_max_id(chan->used_event_id)) {
426 ret = -ENOENT;
427 goto error_free;
428 }
429
430 event = alloc_event(session_objd, channel_objd, name, sig, nr_fields,
431 fields, loglevel_value, model_emf_uri, app);
432 if (!event) {
433 ret = -ENOMEM;
434 goto error_free;
435 }
436
437 DBG3("UST registry creating event with event: %s, sig: %s, id: %u, "
438 "chan_objd: %u, sess_objd: %u, chan_id: %u", event->name,
439 event->signature, event->id, event->channel_objd,
440 event->session_objd, chan->chan_id);
441
442 /*
443 * This is an add unique with a custom match function for event. The node
444 * are matched using the event name and signature.
445 */
446 nptr = cds_lfht_add_unique(chan->ht->ht, chan->ht->hash_fct(event,
447 lttng_ht_seed), chan->ht->match_fct, event, &event->node.node);
448 if (nptr != &event->node.node) {
449 if (buffer_type == LTTNG_BUFFER_PER_UID) {
450 /*
451 * This is normal, we just have to send the event id of the
452 * returned node and make sure we destroy the previously allocated
453 * event object.
454 */
455 destroy_event(event);
456 event = caa_container_of(nptr, struct ust_registry_event,
457 node.node);
458 assert(event);
459 event_id = event->id;
460 } else {
461 ERR("UST registry create event add unique failed for event: %s, "
462 "sig: %s, id: %u, chan_objd: %u, sess_objd: %u",
463 event->name, event->signature, event->id,
464 event->channel_objd, event->session_objd);
465 ret = -EINVAL;
466 goto error_unlock;
467 }
468 } else {
469 /* Request next event id if the node was successfully added. */
470 event_id = event->id = ust_registry_get_next_event_id(chan);
471 }
472
473 *event_id_p = event_id;
474
475 if (!event->metadata_dumped) {
476 /* Append to metadata */
477 ret = ust_metadata_event_statedump(session, chan, event);
478 if (ret) {
479 ERR("Error appending event metadata (errno = %d)", ret);
480 rcu_read_unlock();
481 return ret;
482 }
483 }
484
485 rcu_read_unlock();
486 return 0;
487
488 error_free:
489 free(sig);
490 free(fields);
491 free(model_emf_uri);
492 error_unlock:
493 rcu_read_unlock();
494 destroy_event(event);
495 return ret;
496 }
497
498 /*
499 * For a given event in a registry, delete the entry and destroy the event.
500 * This MUST be called within a RCU read side lock section.
501 */
502 void ust_registry_destroy_event(struct ust_registry_channel *chan,
503 struct ust_registry_event *event)
504 {
505 int ret;
506 struct lttng_ht_iter iter;
507
508 assert(chan);
509 assert(event);
510
511 /* Delete the node first. */
512 iter.iter.node = &event->node.node;
513 ret = lttng_ht_del(chan->ht, &iter);
514 assert(!ret);
515
516 call_rcu(&event->node.head, destroy_event_rcu);
517
518 return;
519 }
520
521 static void destroy_enum(struct ust_registry_enum *reg_enum)
522 {
523 if (!reg_enum) {
524 return;
525 }
526 free(reg_enum->entries);
527 free(reg_enum);
528 }
529
530 static void destroy_enum_rcu(struct rcu_head *head)
531 {
532 struct ust_registry_enum *reg_enum =
533 caa_container_of(head, struct ust_registry_enum, rcu_head);
534
535 destroy_enum(reg_enum);
536 }
537
538 /*
539 * Lookup enumeration by name and comparing enumeration entries.
540 * Needs to be called from RCU read-side critical section.
541 */
542 static struct ust_registry_enum *ust_registry_lookup_enum(
543 struct ust_registry_session *session,
544 const struct ust_registry_enum *reg_enum_lookup)
545 {
546 struct ust_registry_enum *reg_enum = NULL;
547 struct lttng_ht_node_str *node;
548 struct lttng_ht_iter iter;
549
550 cds_lfht_lookup(session->enums->ht,
551 ht_hash_enum((void *) reg_enum_lookup, lttng_ht_seed),
552 ht_match_enum, reg_enum_lookup, &iter.iter);
553 node = lttng_ht_iter_get_node_str(&iter);
554 if (!node) {
555 goto end;
556 }
557 reg_enum = caa_container_of(node, struct ust_registry_enum, node);
558 end:
559 return reg_enum;
560 }
561
562 /*
563 * Lookup enumeration by enum ID.
564 * Needs to be called from RCU read-side critical section.
565 */
566 struct ust_registry_enum *
567 ust_registry_lookup_enum_by_id(struct ust_registry_session *session,
568 const char *enum_name, uint64_t enum_id)
569 {
570 struct ust_registry_enum *reg_enum = NULL;
571 struct lttng_ht_node_str *node;
572 struct lttng_ht_iter iter;
573 struct ust_registry_enum reg_enum_lookup;
574
575 memset(&reg_enum_lookup, 0, sizeof(reg_enum_lookup));
576 strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_SYM_NAME_LEN);
577 reg_enum_lookup.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
578 reg_enum_lookup.id = enum_id;
579 cds_lfht_lookup(session->enums->ht,
580 ht_hash_enum((void *) &reg_enum_lookup, lttng_ht_seed),
581 ht_match_enum_id, &reg_enum_lookup, &iter.iter);
582 node = lttng_ht_iter_get_node_str(&iter);
583 if (!node) {
584 goto end;
585 }
586 reg_enum = caa_container_of(node, struct ust_registry_enum, node);
587 end:
588 return reg_enum;
589 }
590
591 /*
592 * Create a ust_registry_enum from the given parameters and add it to the
593 * registry hash table, or find it if already there.
594 *
595 * On success, return 0 else a negative value.
596 *
597 * Should be called with session registry mutex held.
598 *
599 * We receive ownership of entries.
600 */
601 int ust_registry_create_or_find_enum(struct ust_registry_session *session,
602 int session_objd, char *enum_name,
603 struct ustctl_enum_entry *entries, size_t nr_entries,
604 uint64_t *enum_id)
605 {
606 int ret = 0;
607 struct cds_lfht_node *nodep;
608 struct ust_registry_enum *reg_enum = NULL, *old_reg_enum;
609
610 assert(session);
611 assert(enum_name);
612
613 rcu_read_lock();
614
615 /*
616 * This should not happen but since it comes from the UST tracer, an
617 * external party, don't assert and simply validate values.
618 */
619 if (session_objd < 0) {
620 ret = -EINVAL;
621 goto end;
622 }
623
624 /* Check if the enumeration was already dumped */
625 reg_enum = zmalloc(sizeof(*reg_enum));
626 if (!reg_enum) {
627 PERROR("zmalloc ust registry enumeration");
628 ret = -ENOMEM;
629 goto end;
630 }
631 strncpy(reg_enum->name, enum_name, LTTNG_UST_SYM_NAME_LEN);
632 reg_enum->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
633 /* entries will be owned by reg_enum. */
634 reg_enum->entries = entries;
635 reg_enum->nr_entries = nr_entries;
636 entries = NULL;
637
638 old_reg_enum = ust_registry_lookup_enum(session, reg_enum);
639 if (old_reg_enum) {
640 DBG("enum %s already in sess_objd: %u", enum_name, session_objd);
641 /* Fall through. Use prior enum. */
642 destroy_enum(reg_enum);
643 reg_enum = old_reg_enum;
644 } else {
645 DBG("UST registry creating enum: %s, sess_objd: %u",
646 enum_name, session_objd);
647 if (session->next_enum_id == -1ULL) {
648 ret = -EOVERFLOW;
649 destroy_enum(reg_enum);
650 goto end;
651 }
652 reg_enum->id = session->next_enum_id++;
653 cds_lfht_node_init(&reg_enum->node.node);
654 nodep = cds_lfht_add_unique(session->enums->ht,
655 ht_hash_enum(reg_enum, lttng_ht_seed),
656 ht_match_enum_id, reg_enum,
657 &reg_enum->node.node);
658 assert(nodep == &reg_enum->node.node);
659 }
660 DBG("UST registry reply with enum %s with id %" PRIu64 " in sess_objd: %u",
661 enum_name, reg_enum->id, session_objd);
662 *enum_id = reg_enum->id;
663 end:
664 free(entries);
665 rcu_read_unlock();
666 return ret;
667 }
668
669 /*
670 * For a given enumeration in a registry, delete the entry and destroy
671 * the enumeration.
672 * This MUST be called within a RCU read side lock section.
673 */
674 static void ust_registry_destroy_enum(struct ust_registry_session *reg_session,
675 struct ust_registry_enum *reg_enum)
676 {
677 int ret;
678 struct lttng_ht_iter iter;
679
680 assert(reg_session);
681 assert(reg_enum);
682
683 /* Delete the node first. */
684 iter.iter.node = &reg_enum->node.node;
685 ret = lttng_ht_del(reg_session->enums, &iter);
686 assert(!ret);
687 call_rcu(&reg_enum->rcu_head, destroy_enum_rcu);
688 }
689
690 /*
691 * We need to execute ht_destroy outside of RCU read-side critical
692 * section and outside of call_rcu thread, so we postpone its execution
693 * using ht_cleanup_push. It is simpler than to change the semantic of
694 * the many callers of delete_ust_app_session().
695 */
696 static
697 void destroy_channel_rcu(struct rcu_head *head)
698 {
699 struct ust_registry_channel *chan =
700 caa_container_of(head, struct ust_registry_channel, rcu_head);
701
702 if (chan->ht) {
703 ht_cleanup_push(chan->ht);
704 }
705 free(chan->ctx_fields);
706 free(chan);
707 }
708
709 /*
710 * Destroy every element of the registry and free the memory. This does NOT
711 * free the registry pointer since it might not have been allocated before so
712 * it's the caller responsability.
713 */
714 static void destroy_channel(struct ust_registry_channel *chan, bool notif)
715 {
716 struct lttng_ht_iter iter;
717 struct ust_registry_event *event;
718 enum lttng_error_code cmd_ret;
719
720 assert(chan);
721
722 if (notif) {
723 cmd_ret = notification_thread_command_remove_channel(
724 notification_thread_handle, chan->consumer_key,
725 LTTNG_DOMAIN_UST);
726 if (cmd_ret != LTTNG_OK) {
727 ERR("Failed to remove channel from notification thread");
728 }
729 }
730
731 rcu_read_lock();
732 /* Destroy all event associated with this registry. */
733 cds_lfht_for_each_entry(chan->ht->ht, &iter.iter, event, node.node) {
734 /* Delete the node from the ht and free it. */
735 ust_registry_destroy_event(chan, event);
736 }
737 rcu_read_unlock();
738 call_rcu(&chan->rcu_head, destroy_channel_rcu);
739 }
740
741 /*
742 * Initialize registry with default values.
743 */
744 int ust_registry_channel_add(struct ust_registry_session *session,
745 uint64_t key)
746 {
747 int ret = 0;
748 struct ust_registry_channel *chan;
749
750 assert(session);
751
752 chan = zmalloc(sizeof(*chan));
753 if (!chan) {
754 PERROR("zmalloc ust registry channel");
755 ret = -ENOMEM;
756 goto error_alloc;
757 }
758
759 chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
760 if (!chan->ht) {
761 ret = -ENOMEM;
762 goto error;
763 }
764
765 /* Set custom match function. */
766 chan->ht->match_fct = ht_match_event;
767 chan->ht->hash_fct = ht_hash_event;
768
769 /*
770 * Assign a channel ID right now since the event notification comes
771 * *before* the channel notify so the ID needs to be set at this point so
772 * the metadata can be dumped for that event.
773 */
774 if (ust_registry_is_max_id(session->used_channel_id)) {
775 ret = -1;
776 goto error;
777 }
778 chan->chan_id = ust_registry_get_next_chan_id(session);
779
780 rcu_read_lock();
781 lttng_ht_node_init_u64(&chan->node, key);
782 lttng_ht_add_unique_u64(session->channels, &chan->node);
783 rcu_read_unlock();
784
785 return 0;
786
787 error:
788 destroy_channel(chan, false);
789 error_alloc:
790 return ret;
791 }
792
793 /*
794 * Find a channel in the given registry. RCU read side lock MUST be acquired
795 * before calling this function and as long as the event reference is kept by
796 * the caller.
797 *
798 * On success, the pointer is returned else NULL.
799 */
800 struct ust_registry_channel *ust_registry_channel_find(
801 struct ust_registry_session *session, uint64_t key)
802 {
803 struct lttng_ht_node_u64 *node;
804 struct lttng_ht_iter iter;
805 struct ust_registry_channel *chan = NULL;
806
807 assert(session);
808 assert(session->channels);
809
810 DBG3("UST registry channel finding key %" PRIu64, key);
811
812 lttng_ht_lookup(session->channels, &key, &iter);
813 node = lttng_ht_iter_get_node_u64(&iter);
814 if (!node) {
815 goto end;
816 }
817 chan = caa_container_of(node, struct ust_registry_channel, node);
818
819 end:
820 return chan;
821 }
822
823 /*
824 * Remove channel using key from registry and free memory.
825 */
826 void ust_registry_channel_del_free(struct ust_registry_session *session,
827 uint64_t key, bool notif)
828 {
829 struct lttng_ht_iter iter;
830 struct ust_registry_channel *chan;
831 int ret;
832
833 assert(session);
834
835 rcu_read_lock();
836 chan = ust_registry_channel_find(session, key);
837 if (!chan) {
838 rcu_read_unlock();
839 goto end;
840 }
841
842 iter.iter.node = &chan->node.node;
843 ret = lttng_ht_del(session->channels, &iter);
844 assert(!ret);
845 rcu_read_unlock();
846 destroy_channel(chan, notif);
847
848 end:
849 return;
850 }
851
852 /*
853 * Initialize registry with default values and set the newly allocated session
854 * pointer to sessionp.
855 *
856 * Return 0 on success and sessionp is set or else return -1 and sessionp is
857 * kept untouched.
858 */
859 int ust_registry_session_init(struct ust_registry_session **sessionp,
860 struct ust_app *app,
861 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 int ret;
878 struct ust_registry_session *session;
879
880 assert(sessionp);
881
882 session = zmalloc(sizeof(*session));
883 if (!session) {
884 PERROR("zmalloc ust registry session");
885 goto error_alloc;
886 }
887
888 pthread_mutex_init(&session->lock, NULL);
889 session->bits_per_long = bits_per_long;
890 session->uint8_t_alignment = uint8_t_alignment;
891 session->uint16_t_alignment = uint16_t_alignment;
892 session->uint32_t_alignment = uint32_t_alignment;
893 session->uint64_t_alignment = uint64_t_alignment;
894 session->long_alignment = long_alignment;
895 session->byte_order = byte_order;
896 session->metadata_fd = -1;
897 session->uid = euid;
898 session->gid = egid;
899 session->next_enum_id = 0;
900 session->major = major;
901 session->minor = minor;
902 strncpy(session->root_shm_path, root_shm_path,
903 sizeof(session->root_shm_path));
904 session->root_shm_path[sizeof(session->root_shm_path) - 1] = '\0';
905 if (shm_path[0]) {
906 strncpy(session->shm_path, shm_path,
907 sizeof(session->shm_path));
908 session->shm_path[sizeof(session->shm_path) - 1] = '\0';
909 strncpy(session->metadata_path, shm_path,
910 sizeof(session->metadata_path));
911 session->metadata_path[sizeof(session->metadata_path) - 1] = '\0';
912 strncat(session->metadata_path, "/metadata",
913 sizeof(session->metadata_path)
914 - strlen(session->metadata_path) - 1);
915 }
916 if (session->shm_path[0]) {
917 ret = run_as_mkdir_recursive(session->shm_path,
918 S_IRWXU | S_IRWXG,
919 euid, egid);
920 if (ret) {
921 PERROR("run_as_mkdir_recursive");
922 goto error;
923 }
924 }
925 if (session->metadata_path[0]) {
926 /* Create metadata file */
927 ret = run_as_open(session->metadata_path,
928 O_WRONLY | O_CREAT | O_EXCL,
929 S_IRUSR | S_IWUSR, euid, egid);
930 if (ret < 0) {
931 PERROR("Opening metadata file");
932 goto error;
933 }
934 session->metadata_fd = ret;
935 }
936
937 session->enums = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
938 if (!session->enums) {
939 ERR("Failed to create enums hash table");
940 goto error;
941 }
942 /* hash/match functions are specified at call site. */
943 session->enums->match_fct = NULL;
944 session->enums->hash_fct = NULL;
945
946 session->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
947 if (!session->channels) {
948 goto error;
949 }
950
951 ret = lttng_uuid_generate(session->uuid);
952 if (ret) {
953 ERR("Failed to generate UST uuid (errno = %d)", ret);
954 goto error;
955 }
956
957 session->tracing_id = tracing_id;
958 session->tracing_uid = tracing_uid;
959
960 pthread_mutex_lock(&session->lock);
961 ret = ust_metadata_session_statedump(session, app, major, minor);
962 pthread_mutex_unlock(&session->lock);
963 if (ret) {
964 ERR("Failed to generate session metadata (errno = %d)", ret);
965 goto error;
966 }
967
968 *sessionp = session;
969
970 return 0;
971
972 error:
973 ust_registry_session_destroy(session);
974 free(session);
975 error_alloc:
976 return -1;
977 }
978
979 /*
980 * Destroy session registry. This does NOT free the given pointer since it
981 * might get passed as a reference. The registry lock should NOT be acquired.
982 */
983 void ust_registry_session_destroy(struct ust_registry_session *reg)
984 {
985 int ret;
986 struct lttng_ht_iter iter;
987 struct ust_registry_channel *chan;
988 struct ust_registry_enum *reg_enum;
989
990 if (!reg) {
991 return;
992 }
993
994 /* On error, EBUSY can be returned if lock. Code flow error. */
995 ret = pthread_mutex_destroy(&reg->lock);
996 assert(!ret);
997
998 if (reg->channels) {
999 rcu_read_lock();
1000 /* Destroy all event associated with this registry. */
1001 cds_lfht_for_each_entry(reg->channels->ht, &iter.iter, chan,
1002 node.node) {
1003 /* Delete the node from the ht and free it. */
1004 ret = lttng_ht_del(reg->channels, &iter);
1005 assert(!ret);
1006 destroy_channel(chan, true);
1007 }
1008 rcu_read_unlock();
1009 ht_cleanup_push(reg->channels);
1010 }
1011
1012 free(reg->metadata);
1013 if (reg->metadata_fd >= 0) {
1014 ret = close(reg->metadata_fd);
1015 if (ret) {
1016 PERROR("close");
1017 }
1018 ret = run_as_unlink(reg->metadata_path,
1019 reg->uid, reg->gid);
1020 if (ret) {
1021 PERROR("unlink");
1022 }
1023 }
1024 if (reg->root_shm_path[0]) {
1025 /*
1026 * Try deleting the directory hierarchy.
1027 */
1028 (void) run_as_rmdir_recursive(reg->root_shm_path,
1029 reg->uid, reg->gid,
1030 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
1031 }
1032 /* Destroy the enum hash table */
1033 if (reg->enums) {
1034 rcu_read_lock();
1035 /* Destroy all enum entries associated with this registry. */
1036 cds_lfht_for_each_entry(reg->enums->ht, &iter.iter, reg_enum,
1037 node.node) {
1038 ust_registry_destroy_enum(reg, reg_enum);
1039 }
1040 rcu_read_unlock();
1041 ht_cleanup_push(reg->enums);
1042 }
1043 }
This page took 0.047872 seconds and 3 git commands to generate.