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