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