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