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