Force usage of assert() condition when NDEBUG is defined
[lttng-tools.git] / src / bin / lttng-sessiond / ust-registry.c
CommitLineData
d0b96690 1/*
ab5be9fa 2 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
d0b96690 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
d0b96690 5 *
d0b96690 6 */
890d8fe4 7
6c1c0768 8#define _LGPL_SOURCE
7972aab2 9#include <inttypes.h>
d0b96690
DG
10
11#include <common/common.h>
7972aab2
DG
12#include <common/hashtable/utils.h>
13#include <lttng/lttng.h>
14
d0b96690 15#include "ust-registry.h"
8494bda5 16#include "ust-app.h"
98b73e88 17#include "ust-field-utils.h"
0b2dc8df 18#include "utils.h"
e9404c27
JG
19#include "lttng-sessiond.h"
20#include "notification-thread-commands.h"
d0b96690 21
98b73e88 22
d0b96690
DG
23/*
24 * Hash table match function for event in the registry.
25 */
26static int ht_match_event(struct cds_lfht_node *node, const void *_key)
27{
d0b96690 28 const struct ust_registry_event *key;
98b73e88
FD
29 struct ust_registry_event *event;
30 int i;
d0b96690 31
a0377dfe
FD
32 LTTNG_ASSERT(node);
33 LTTNG_ASSERT(_key);
d0b96690
DG
34
35 event = caa_container_of(node, struct ust_registry_event, node.node);
a0377dfe 36 LTTNG_ASSERT(event);
d0b96690
DG
37 key = _key;
38
98b73e88 39 /* It has to be a perfect match. First, compare the event names. */
b4d096a6 40 if (strncmp(event->name, key->name, sizeof(event->name))) {
d0b96690
DG
41 goto no_match;
42 }
43
98b73e88
FD
44 /* Compare log levels. */
45 if (event->loglevel_value != key->loglevel_value) {
46 goto no_match;
47 }
48
49 /* Compare the number of fields. */
50 if (event->nr_fields != key->nr_fields) {
51 goto no_match;
52 }
53
54 /* Compare each field individually. */
55 for (i = 0; i < event->nr_fields; i++) {
b623cb6a 56 if (!match_lttng_ust_ctl_field(&event->fields[i], &key->fields[i])) {
98b73e88
FD
57 goto no_match;
58 }
59 }
60
61 /* Compare model URI. */
62 if (event->model_emf_uri != NULL && key->model_emf_uri == NULL) {
63 goto no_match;
64 } else if(event->model_emf_uri == NULL && key->model_emf_uri != NULL) {
d0b96690 65 goto no_match;
98b73e88
FD
66 } else if (event->model_emf_uri != NULL && key->model_emf_uri != NULL) {
67 if (strcmp(event->model_emf_uri, key->model_emf_uri)) {
68 goto no_match;
69 }
d0b96690
DG
70 }
71
72 /* Match */
73 return 1;
74
75no_match:
76 return 0;
77}
78
bcd52dd9 79static unsigned long ht_hash_event(const void *_key, unsigned long seed)
7972aab2 80{
98b73e88 81 uint64_t hashed_key;
bcd52dd9 82 const struct ust_registry_event *key = _key;
7972aab2 83
a0377dfe 84 LTTNG_ASSERT(key);
7972aab2 85
98b73e88 86 hashed_key = (uint64_t) hash_key_str(key->name, seed);
7972aab2 87
98b73e88 88 return hash_key_u64(&hashed_key, seed);
7972aab2
DG
89}
90
10b56aef
MD
91static int compare_enums(const struct ust_registry_enum *reg_enum_a,
92 const struct ust_registry_enum *reg_enum_b)
93{
94 int ret = 0;
95 size_t i;
96
a0377dfe 97 LTTNG_ASSERT(strcmp(reg_enum_a->name, reg_enum_b->name) == 0);
10b56aef
MD
98 if (reg_enum_a->nr_entries != reg_enum_b->nr_entries) {
99 ret = -1;
100 goto end;
101 }
102 for (i = 0; i < reg_enum_a->nr_entries; i++) {
b623cb6a 103 const struct lttng_ust_ctl_enum_entry *entries_a, *entries_b;
10b56aef
MD
104
105 entries_a = &reg_enum_a->entries[i];
106 entries_b = &reg_enum_b->entries[i];
3b016e58 107 if (entries_a->start.value != entries_b->start.value) {
10b56aef
MD
108 ret = -1;
109 goto end;
110 }
3b016e58 111 if (entries_a->end.value != entries_b->end.value) {
10b56aef
MD
112 ret = -1;
113 goto end;
114 }
3b016e58
MD
115 if (entries_a->start.signedness != entries_b->start.signedness) {
116 ret = -1;
117 goto end;
118 }
119 if (entries_a->end.signedness != entries_b->end.signedness) {
120 ret = -1;
121 goto end;
122 }
123
10b56aef
MD
124 if (strcmp(entries_a->string, entries_b->string)) {
125 ret = -1;
126 goto end;
127 }
128 }
129end:
130 return ret;
131}
132
133/*
134 * Hash table match function for enumerations in the session. Match is
135 * performed on enumeration name, and confirmed by comparing the enum
136 * entries.
137 */
138static int ht_match_enum(struct cds_lfht_node *node, const void *_key)
139{
140 struct ust_registry_enum *_enum;
141 const struct ust_registry_enum *key;
142
a0377dfe
FD
143 LTTNG_ASSERT(node);
144 LTTNG_ASSERT(_key);
10b56aef
MD
145
146 _enum = caa_container_of(node, struct ust_registry_enum,
147 node.node);
a0377dfe 148 LTTNG_ASSERT(_enum);
10b56aef
MD
149 key = _key;
150
fc4b93fa 151 if (strncmp(_enum->name, key->name, LTTNG_UST_ABI_SYM_NAME_LEN)) {
10b56aef
MD
152 goto no_match;
153 }
154 if (compare_enums(_enum, key)) {
155 goto no_match;
156 }
157
158 /* Match. */
159 return 1;
160
161no_match:
162 return 0;
163}
164
165/*
166 * Hash table match function for enumerations in the session. Match is
167 * performed by enumeration ID.
168 */
169static int ht_match_enum_id(struct cds_lfht_node *node, const void *_key)
170{
171 struct ust_registry_enum *_enum;
172 const struct ust_registry_enum *key = _key;
173
a0377dfe
FD
174 LTTNG_ASSERT(node);
175 LTTNG_ASSERT(_key);
10b56aef
MD
176
177 _enum = caa_container_of(node, struct ust_registry_enum, node.node);
a0377dfe 178 LTTNG_ASSERT(_enum);
10b56aef
MD
179
180 if (_enum->id != key->id) {
181 goto no_match;
182 }
183
184 /* Match. */
185 return 1;
186
187no_match:
188 return 0;
189}
190
191/*
192 * Hash table hash function for enumerations in the session. The
193 * enumeration name is used for hashing.
194 */
195static unsigned long ht_hash_enum(void *_key, unsigned long seed)
196{
197 struct ust_registry_enum *key = _key;
198
a0377dfe 199 LTTNG_ASSERT(key);
10b56aef
MD
200 return hash_key_str(key->name, seed);
201}
202
8494bda5
MD
203/*
204 * Return negative value on error, 0 if OK.
205 *
206 * TODO: we could add stricter verification of more types to catch
207 * errors in liblttng-ust implementation earlier than consumption by the
208 * trace reader.
209 */
210static
b623cb6a 211int validate_event_field(struct lttng_ust_ctl_field *field,
8494bda5
MD
212 const char *event_name,
213 struct ust_app *app)
214{
da860cab
MD
215 int ret = 0;
216
8494bda5 217 switch(field->type.atype) {
b623cb6a
MJ
218 case lttng_ust_ctl_atype_integer:
219 case lttng_ust_ctl_atype_enum:
220 case lttng_ust_ctl_atype_array:
221 case lttng_ust_ctl_atype_sequence:
222 case lttng_ust_ctl_atype_string:
223 case lttng_ust_ctl_atype_variant:
224 case lttng_ust_ctl_atype_array_nestable:
225 case lttng_ust_ctl_atype_sequence_nestable:
226 case lttng_ust_ctl_atype_enum_nestable:
227 case lttng_ust_ctl_atype_variant_nestable:
da860cab 228 break;
b623cb6a 229 case lttng_ust_ctl_atype_struct:
0d32d1a9
MD
230 if (field->type.u.legacy._struct.nr_fields != 0) {
231 WARN("Unsupported non-empty struct field.");
232 ret = -EINVAL;
233 goto end;
234 }
235 break;
b623cb6a 236 case lttng_ust_ctl_atype_struct_nestable:
0d32d1a9 237 if (field->type.u.struct_nestable.nr_fields != 0) {
da860cab
MD
238 WARN("Unsupported non-empty struct field.");
239 ret = -EINVAL;
240 goto end;
241 }
8494bda5
MD
242 break;
243
b623cb6a 244 case lttng_ust_ctl_atype_float:
0d32d1a9 245 switch (field->type.u._float.mant_dig) {
8494bda5
MD
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,
0d32d1a9 250 field->type.u._float.mant_dig,
8494bda5
MD
251 field->name,
252 event_name);
da860cab
MD
253 ret = -EINVAL;
254 goto end;
8494bda5
MD
255 default:
256 break;
257 }
258 break;
259
260 default:
da860cab
MD
261 ret = -ENOENT;
262 goto end;
8494bda5 263 }
da860cab
MD
264end:
265 return ret;
8494bda5
MD
266}
267
268static
b623cb6a 269int validate_event_fields(size_t nr_fields, struct lttng_ust_ctl_field *fields,
8494bda5
MD
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
d0b96690
DG
281/*
282 * Allocate event and initialize it. This does NOT set a valid event id from a
283 * registry.
284 */
285static struct ust_registry_event *alloc_event(int session_objd,
286 int channel_objd, char *name, char *sig, size_t nr_fields,
b623cb6a 287 struct lttng_ust_ctl_field *fields, int loglevel_value,
2106efa0 288 char *model_emf_uri, struct ust_app *app)
d0b96690
DG
289{
290 struct ust_registry_event *event = NULL;
291
8494bda5
MD
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
d0b96690
DG
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;
2106efa0 311 event->loglevel_value = loglevel_value;
d0b96690
DG
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 }
7972aab2 318 cds_lfht_node_init(&event->node.node);
d0b96690
DG
319
320error:
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 */
329static 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 */
344static void destroy_event_rcu(struct rcu_head *head)
345{
7972aab2
DG
346 struct lttng_ht_node_u64 *node =
347 caa_container_of(head, struct lttng_ht_node_u64, head);
d0b96690
DG
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 */
361struct ust_registry_event *ust_registry_find_event(
362 struct ust_registry_channel *chan, char *name, char *sig)
363{
7972aab2 364 struct lttng_ht_node_u64 *node;
d0b96690
DG
365 struct lttng_ht_iter iter;
366 struct ust_registry_event *event = NULL;
367 struct ust_registry_event key;
368
a0377dfe
FD
369 LTTNG_ASSERT(chan);
370 LTTNG_ASSERT(name);
371 LTTNG_ASSERT(sig);
d0b96690
DG
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
7972aab2 378 cds_lfht_lookup(chan->ht->ht, chan->ht->hash_fct(&key, lttng_ht_seed),
d0b96690 379 chan->ht->match_fct, &key, &iter.iter);
7972aab2 380 node = lttng_ht_iter_get_node_u64(&iter);
d0b96690
DG
381 if (!node) {
382 goto end;
383 }
384 event = caa_container_of(node, struct ust_registry_event, node);
385
386end:
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 */
400int ust_registry_create_event(struct ust_registry_session *session,
45893984 401 uint64_t chan_key, int session_objd, int channel_objd, char *name,
b623cb6a 402 char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields,
2106efa0
PP
403 int loglevel_value, char *model_emf_uri, int buffer_type,
404 uint32_t *event_id_p, struct ust_app *app)
d0b96690
DG
405{
406 int ret;
7972aab2 407 uint32_t event_id;
d0b96690
DG
408 struct cds_lfht_node *nptr;
409 struct ust_registry_event *event = NULL;
45893984 410 struct ust_registry_channel *chan;
d0b96690 411
a0377dfe
FD
412 LTTNG_ASSERT(session);
413 LTTNG_ASSERT(name);
414 LTTNG_ASSERT(sig);
415 LTTNG_ASSERT(event_id_p);
d0b96690 416
d5d629b5
DG
417 rcu_read_lock();
418
d0b96690
DG
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;
d5d629b5 425 goto error_free;
d0b96690
DG
426 }
427
45893984
DG
428 chan = ust_registry_channel_find(session, chan_key);
429 if (!chan) {
430 ret = -EINVAL;
d5d629b5 431 goto error_free;
45893984
DG
432 }
433
d0b96690
DG
434 /* Check if we've reached the maximum possible id. */
435 if (ust_registry_is_max_id(chan->used_event_id)) {
436 ret = -ENOENT;
d5d629b5 437 goto error_free;
d0b96690
DG
438 }
439
440 event = alloc_event(session_objd, channel_objd, name, sig, nr_fields,
2106efa0 441 fields, loglevel_value, model_emf_uri, app);
d0b96690
DG
442 if (!event) {
443 ret = -ENOMEM;
d5d629b5 444 goto error_free;
d0b96690
DG
445 }
446
d0b96690 447 DBG3("UST registry creating event with event: %s, sig: %s, id: %u, "
7972aab2
DG
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);
d0b96690 451
d0b96690
DG
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 */
7972aab2 456 nptr = cds_lfht_add_unique(chan->ht->ht, chan->ht->hash_fct(event,
d0b96690
DG
457 lttng_ht_seed), chan->ht->match_fct, event, &event->node.node);
458 if (nptr != &event->node.node) {
7972aab2
DG
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);
a0377dfe 468 LTTNG_ASSERT(event);
7972aab2
DG
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);
d0b96690
DG
481 }
482
7972aab2 483 *event_id_p = event_id;
d0b96690 484
7972aab2
DG
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 }
d0b96690
DG
493 }
494
45893984 495 rcu_read_unlock();
d0b96690
DG
496 return 0;
497
d5d629b5
DG
498error_free:
499 free(sig);
500 free(fields);
501 free(model_emf_uri);
d0b96690
DG
502error_unlock:
503 rcu_read_unlock();
d0b96690
DG
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 */
512void 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
a0377dfe
FD
518 LTTNG_ASSERT(chan);
519 LTTNG_ASSERT(event);
d0b96690
DG
520
521 /* Delete the node first. */
522 iter.iter.node = &event->node.node;
523 ret = lttng_ht_del(chan->ht, &iter);
a0377dfe 524 LTTNG_ASSERT(!ret);
d0b96690
DG
525
526 call_rcu(&event->node.head, destroy_event_rcu);
527
528 return;
529}
530
10b56aef
MD
531static 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
540static 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 */
10dc2d10
SM
552static struct ust_registry_enum *ust_registry_lookup_enum(
553 struct ust_registry_session *session,
10b56aef
MD
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,
a752d6fa
FD
561 ht_hash_enum((void *) reg_enum_lookup, lttng_ht_seed),
562 ht_match_enum, reg_enum_lookup, &iter.iter);
10b56aef
MD
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);
568end:
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 */
576struct 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));
fc4b93fa
MD
586 strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
587 reg_enum_lookup.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
10b56aef
MD
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);
597end:
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 */
611int ust_registry_create_or_find_enum(struct ust_registry_session *session,
612 int session_objd, char *enum_name,
b623cb6a 613 struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries,
10b56aef
MD
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
a0377dfe
FD
620 LTTNG_ASSERT(session);
621 LTTNG_ASSERT(enum_name);
10b56aef
MD
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 }
fc4b93fa
MD
641 strncpy(reg_enum->name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
642 reg_enum->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
10b56aef
MD
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);
a0377dfe 668 LTTNG_ASSERT(nodep == &reg_enum->node.node);
10b56aef
MD
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;
673end:
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 */
10dc2d10 684static void ust_registry_destroy_enum(struct ust_registry_session *reg_session,
10b56aef
MD
685 struct ust_registry_enum *reg_enum)
686{
687 int ret;
688 struct lttng_ht_iter iter;
689
a0377dfe
FD
690 LTTNG_ASSERT(reg_session);
691 LTTNG_ASSERT(reg_enum);
10b56aef
MD
692
693 /* Delete the node first. */
694 iter.iter.node = &reg_enum->node.node;
695 ret = lttng_ht_del(reg_session->enums, &iter);
a0377dfe 696 LTTNG_ASSERT(!ret);
10b56aef
MD
697 call_rcu(&reg_enum->rcu_head, destroy_enum_rcu);
698}
699
36b588ed
MD
700/*
701 * We need to execute ht_destroy outside of RCU read-side critical
0b2dc8df
MD
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().
36b588ed
MD
705 */
706static
707void 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
9dbcf332 712 if (chan->ht) {
0b2dc8df 713 ht_cleanup_push(chan->ht);
9dbcf332 714 }
3295105b 715 free(chan->ctx_fields);
36b588ed
MD
716 free(chan);
717}
718
d0b96690
DG
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.
d0b96690 723 */
e9404c27 724static void destroy_channel(struct ust_registry_channel *chan, bool notif)
d0b96690
DG
725{
726 struct lttng_ht_iter iter;
727 struct ust_registry_event *event;
e9404c27 728 enum lttng_error_code cmd_ret;
d0b96690 729
a0377dfe 730 LTTNG_ASSERT(chan);
d0b96690 731
e9404c27
JG
732 if (notif) {
733 cmd_ret = notification_thread_command_remove_channel(
412d7227
SM
734 the_notification_thread_handle,
735 chan->consumer_key, LTTNG_DOMAIN_UST);
e9404c27
JG
736 if (cmd_ret != LTTNG_OK) {
737 ERR("Failed to remove channel from notification thread");
738 }
739 }
740
70987ead
JG
741 if (chan->ht) {
742 rcu_read_lock();
743 /* Destroy all event associated with this registry. */
744 cds_lfht_for_each_entry(
745 chan->ht->ht, &iter.iter, event, node.node) {
746 /* Delete the node from the ht and free it. */
747 ust_registry_destroy_event(chan, event);
748 }
749 rcu_read_unlock();
d0b96690 750 }
36b588ed 751 call_rcu(&chan->rcu_head, destroy_channel_rcu);
d0b96690
DG
752}
753
754/*
755 * Initialize registry with default values.
756 */
45893984
DG
757int ust_registry_channel_add(struct ust_registry_session *session,
758 uint64_t key)
759{
760 int ret = 0;
761 struct ust_registry_channel *chan;
762
a0377dfe 763 LTTNG_ASSERT(session);
45893984
DG
764
765 chan = zmalloc(sizeof(*chan));
766 if (!chan) {
767 PERROR("zmalloc ust registry channel");
768 ret = -ENOMEM;
9dbcf332 769 goto error_alloc;
45893984
DG
770 }
771
772 chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
773 if (!chan->ht) {
774 ret = -ENOMEM;
775 goto error;
776 }
777
778 /* Set custom match function. */
779 chan->ht->match_fct = ht_match_event;
7972aab2
DG
780 chan->ht->hash_fct = ht_hash_event;
781
782 /*
783 * Assign a channel ID right now since the event notification comes
784 * *before* the channel notify so the ID needs to be set at this point so
785 * the metadata can be dumped for that event.
786 */
787 if (ust_registry_is_max_id(session->used_channel_id)) {
788 ret = -1;
789 goto error;
790 }
791 chan->chan_id = ust_registry_get_next_chan_id(session);
45893984
DG
792
793 rcu_read_lock();
794 lttng_ht_node_init_u64(&chan->node, key);
795 lttng_ht_add_unique_u64(session->channels, &chan->node);
796 rcu_read_unlock();
797
9dbcf332
DG
798 return 0;
799
45893984 800error:
e9404c27 801 destroy_channel(chan, false);
9dbcf332 802error_alloc:
45893984
DG
803 return ret;
804}
805
806/*
807 * Find a channel in the given registry. RCU read side lock MUST be acquired
808 * before calling this function and as long as the event reference is kept by
809 * the caller.
810 *
811 * On success, the pointer is returned else NULL.
812 */
813struct ust_registry_channel *ust_registry_channel_find(
814 struct ust_registry_session *session, uint64_t key)
815{
816 struct lttng_ht_node_u64 *node;
817 struct lttng_ht_iter iter;
818 struct ust_registry_channel *chan = NULL;
819
a0377dfe
FD
820 LTTNG_ASSERT(session);
821 LTTNG_ASSERT(session->channels);
45893984 822
7972aab2
DG
823 DBG3("UST registry channel finding key %" PRIu64, key);
824
45893984
DG
825 lttng_ht_lookup(session->channels, &key, &iter);
826 node = lttng_ht_iter_get_node_u64(&iter);
827 if (!node) {
828 goto end;
829 }
830 chan = caa_container_of(node, struct ust_registry_channel, node);
831
832end:
833 return chan;
834}
835
836/*
837 * Remove channel using key from registry and free memory.
838 */
839void ust_registry_channel_del_free(struct ust_registry_session *session,
e9404c27 840 uint64_t key, bool notif)
45893984
DG
841{
842 struct lttng_ht_iter iter;
843 struct ust_registry_channel *chan;
9209cee7 844 int ret;
45893984 845
a0377dfe 846 LTTNG_ASSERT(session);
45893984
DG
847
848 rcu_read_lock();
849 chan = ust_registry_channel_find(session, key);
850 if (!chan) {
9209cee7 851 rcu_read_unlock();
45893984
DG
852 goto end;
853 }
854
855 iter.iter.node = &chan->node.node;
9209cee7 856 ret = lttng_ht_del(session->channels, &iter);
a0377dfe 857 LTTNG_ASSERT(!ret);
9209cee7 858 rcu_read_unlock();
e9404c27 859 destroy_channel(chan, notif);
45893984
DG
860
861end:
45893984
DG
862 return;
863}
864
865/*
866 * Initialize registry with default values and set the newly allocated session
867 * pointer to sessionp.
868 *
869 * Return 0 on success and sessionp is set or else return -1 and sessionp is
870 * kept untouched.
871 */
872int ust_registry_session_init(struct ust_registry_session **sessionp,
d0b96690
DG
873 struct ust_app *app,
874 uint32_t bits_per_long,
875 uint32_t uint8_t_alignment,
876 uint32_t uint16_t_alignment,
877 uint32_t uint32_t_alignment,
878 uint32_t uint64_t_alignment,
879 uint32_t long_alignment,
af6142cf
MD
880 int byte_order,
881 uint32_t major,
d7ba1388 882 uint32_t minor,
3d071855 883 const char *root_shm_path,
d7ba1388
MD
884 const char *shm_path,
885 uid_t euid,
8de88061
JR
886 gid_t egid,
887 uint64_t tracing_id,
888 uid_t tracing_uid)
d0b96690
DG
889{
890 int ret;
45893984 891 struct ust_registry_session *session;
d0b96690 892
a0377dfe 893 LTTNG_ASSERT(sessionp);
d0b96690 894
45893984
DG
895 session = zmalloc(sizeof(*session));
896 if (!session) {
897 PERROR("zmalloc ust registry session");
9dbcf332 898 goto error_alloc;
45893984 899 }
d0b96690
DG
900
901 pthread_mutex_init(&session->lock, NULL);
902 session->bits_per_long = bits_per_long;
903 session->uint8_t_alignment = uint8_t_alignment;
904 session->uint16_t_alignment = uint16_t_alignment;
905 session->uint32_t_alignment = uint32_t_alignment;
906 session->uint64_t_alignment = uint64_t_alignment;
907 session->long_alignment = long_alignment;
908 session->byte_order = byte_order;
d7ba1388 909 session->metadata_fd = -1;
4628484a
MD
910 session->uid = euid;
911 session->gid = egid;
10b56aef 912 session->next_enum_id = 0;
7062f070
JD
913 session->major = major;
914 session->minor = minor;
3d071855
MD
915 strncpy(session->root_shm_path, root_shm_path,
916 sizeof(session->root_shm_path));
917 session->root_shm_path[sizeof(session->root_shm_path) - 1] = '\0';
d7ba1388
MD
918 if (shm_path[0]) {
919 strncpy(session->shm_path, shm_path,
920 sizeof(session->shm_path));
921 session->shm_path[sizeof(session->shm_path) - 1] = '\0';
922 strncpy(session->metadata_path, shm_path,
923 sizeof(session->metadata_path));
924 session->metadata_path[sizeof(session->metadata_path) - 1] = '\0';
925 strncat(session->metadata_path, "/metadata",
926 sizeof(session->metadata_path)
927 - strlen(session->metadata_path) - 1);
928 }
929 if (session->shm_path[0]) {
930 ret = run_as_mkdir_recursive(session->shm_path,
931 S_IRWXU | S_IRWXG,
932 euid, egid);
933 if (ret) {
934 PERROR("run_as_mkdir_recursive");
935 goto error;
936 }
937 }
938 if (session->metadata_path[0]) {
939 /* Create metadata file */
4628484a 940 ret = run_as_open(session->metadata_path,
d7ba1388 941 O_WRONLY | O_CREAT | O_EXCL,
4628484a 942 S_IRUSR | S_IWUSR, euid, egid);
d7ba1388
MD
943 if (ret < 0) {
944 PERROR("Opening metadata file");
945 goto error;
946 }
947 session->metadata_fd = ret;
948 }
d0b96690 949
10b56aef
MD
950 session->enums = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
951 if (!session->enums) {
de64322e 952 ERR("Failed to create enums hash table");
10b56aef
MD
953 goto error;
954 }
955 /* hash/match functions are specified at call site. */
956 session->enums->match_fct = NULL;
957 session->enums->hash_fct = NULL;
958
45893984
DG
959 session->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
960 if (!session->channels) {
961 goto error;
962 }
963
d0b96690
DG
964 ret = lttng_uuid_generate(session->uuid);
965 if (ret) {
966 ERR("Failed to generate UST uuid (errno = %d)", ret);
967 goto error;
968 }
969
8de88061
JR
970 session->tracing_id = tracing_id;
971 session->tracing_uid = tracing_uid;
972
d0b96690 973 pthread_mutex_lock(&session->lock);
af6142cf 974 ret = ust_metadata_session_statedump(session, app, major, minor);
d0b96690
DG
975 pthread_mutex_unlock(&session->lock);
976 if (ret) {
977 ERR("Failed to generate session metadata (errno = %d)", ret);
978 goto error;
979 }
980
45893984
DG
981 *sessionp = session;
982
d0b96690
DG
983 return 0;
984
985error:
9dbcf332 986 ust_registry_session_destroy(session);
d24ff3fd 987 free(session);
9dbcf332 988error_alloc:
d0b96690
DG
989 return -1;
990}
991
992/*
993 * Destroy session registry. This does NOT free the given pointer since it
994 * might get passed as a reference. The registry lock should NOT be acquired.
995 */
996void ust_registry_session_destroy(struct ust_registry_session *reg)
997{
998 int ret;
45893984
DG
999 struct lttng_ht_iter iter;
1000 struct ust_registry_channel *chan;
10b56aef 1001 struct ust_registry_enum *reg_enum;
d0b96690 1002
286c991a
MD
1003 if (!reg) {
1004 return;
1005 }
9d8efb0e 1006
d0b96690
DG
1007 /* On error, EBUSY can be returned if lock. Code flow error. */
1008 ret = pthread_mutex_destroy(&reg->lock);
a0377dfe 1009 LTTNG_ASSERT(!ret);
d0b96690 1010
9d8efb0e
DG
1011 if (reg->channels) {
1012 rcu_read_lock();
1013 /* Destroy all event associated with this registry. */
1014 cds_lfht_for_each_entry(reg->channels->ht, &iter.iter, chan,
1015 node.node) {
1016 /* Delete the node from the ht and free it. */
1017 ret = lttng_ht_del(reg->channels, &iter);
a0377dfe 1018 LTTNG_ASSERT(!ret);
e9404c27 1019 destroy_channel(chan, true);
9d8efb0e
DG
1020 }
1021 rcu_read_unlock();
1022 ht_cleanup_push(reg->channels);
45893984 1023 }
45893984 1024
d0b96690 1025 free(reg->metadata);
d7ba1388
MD
1026 if (reg->metadata_fd >= 0) {
1027 ret = close(reg->metadata_fd);
1028 if (ret) {
1029 PERROR("close");
1030 }
4628484a
MD
1031 ret = run_as_unlink(reg->metadata_path,
1032 reg->uid, reg->gid);
d7ba1388
MD
1033 if (ret) {
1034 PERROR("unlink");
1035 }
1036 }
3d071855
MD
1037 if (reg->root_shm_path[0]) {
1038 /*
1039 * Try deleting the directory hierarchy.
1040 */
602766ec 1041 (void) run_as_rmdir_recursive(reg->root_shm_path,
f75c5439
MD
1042 reg->uid, reg->gid,
1043 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
3d071855 1044 }
10b56aef
MD
1045 /* Destroy the enum hash table */
1046 if (reg->enums) {
1047 rcu_read_lock();
1048 /* Destroy all enum entries associated with this registry. */
1049 cds_lfht_for_each_entry(reg->enums->ht, &iter.iter, reg_enum,
1050 node.node) {
1051 ust_registry_destroy_enum(reg, reg_enum);
1052 }
1053 rcu_read_unlock();
1054 ht_cleanup_push(reg->enums);
1055 }
d0b96690 1056}
This page took 0.107887 seconds and 4 git commands to generate.