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