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
28dc0326
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++) {
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
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
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;
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
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
d0b96690
DG
292 event = zmalloc(sizeof(*event));
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
319 * safe to pass a NULL pointer. This shoudl be called inside a call RCU if the
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
362 assert(chan);
363 assert(name);
364 assert(sig);
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
7972aab2 371 cds_lfht_lookup(chan->ht->ht, chan->ht->hash_fct(&key, lttng_ht_seed),
d0b96690 372 chan->ht->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
DG
404
405 assert(session);
d0b96690
DG
406 assert(name);
407 assert(sig);
7972aab2 408 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 */
7972aab2 449 nptr = cds_lfht_add_unique(chan->ht->ht, chan->ht->hash_fct(event,
d0b96690
DG
450 lttng_ht_seed), chan->ht->match_fct, event, &event->node.node);
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);
461 assert(event);
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
511 assert(chan);
512 assert(event);
513
514 /* Delete the node first. */
515 iter.iter.node = &event->node.node;
516 ret = lttng_ht_del(chan->ht, &iter);
517 assert(!ret);
518
519 call_rcu(&event->node.head, destroy_event_rcu);
520
521 return;
522}
523
10b56aef
MD
524static void destroy_enum(struct ust_registry_enum *reg_enum)
525{
526 if (!reg_enum) {
527 return;
528 }
529 free(reg_enum->entries);
530 free(reg_enum);
531}
532
533static void destroy_enum_rcu(struct rcu_head *head)
534{
535 struct ust_registry_enum *reg_enum =
536 caa_container_of(head, struct ust_registry_enum, rcu_head);
537
538 destroy_enum(reg_enum);
539}
540
541/*
542 * Lookup enumeration by name and comparing enumeration entries.
543 * Needs to be called from RCU read-side critical section.
544 */
10dc2d10
SM
545static struct ust_registry_enum *ust_registry_lookup_enum(
546 struct ust_registry_session *session,
10b56aef
MD
547 const struct ust_registry_enum *reg_enum_lookup)
548{
549 struct ust_registry_enum *reg_enum = NULL;
550 struct lttng_ht_node_str *node;
551 struct lttng_ht_iter iter;
552
553 cds_lfht_lookup(session->enums->ht,
a752d6fa
FD
554 ht_hash_enum((void *) reg_enum_lookup, lttng_ht_seed),
555 ht_match_enum, reg_enum_lookup, &iter.iter);
10b56aef
MD
556 node = lttng_ht_iter_get_node_str(&iter);
557 if (!node) {
558 goto end;
559 }
560 reg_enum = caa_container_of(node, struct ust_registry_enum, node);
561end:
562 return reg_enum;
563}
564
565/*
566 * Lookup enumeration by enum ID.
567 * Needs to be called from RCU read-side critical section.
568 */
569struct ust_registry_enum *
570 ust_registry_lookup_enum_by_id(struct ust_registry_session *session,
571 const char *enum_name, uint64_t enum_id)
572{
573 struct ust_registry_enum *reg_enum = NULL;
574 struct lttng_ht_node_str *node;
575 struct lttng_ht_iter iter;
576 struct ust_registry_enum reg_enum_lookup;
577
578 memset(&reg_enum_lookup, 0, sizeof(reg_enum_lookup));
fc4b93fa
MD
579 strncpy(reg_enum_lookup.name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
580 reg_enum_lookup.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
10b56aef
MD
581 reg_enum_lookup.id = enum_id;
582 cds_lfht_lookup(session->enums->ht,
583 ht_hash_enum((void *) &reg_enum_lookup, lttng_ht_seed),
584 ht_match_enum_id, &reg_enum_lookup, &iter.iter);
585 node = lttng_ht_iter_get_node_str(&iter);
586 if (!node) {
587 goto end;
588 }
589 reg_enum = caa_container_of(node, struct ust_registry_enum, node);
590end:
591 return reg_enum;
592}
593
594/*
595 * Create a ust_registry_enum from the given parameters and add it to the
596 * registry hash table, or find it if already there.
597 *
598 * On success, return 0 else a negative value.
599 *
600 * Should be called with session registry mutex held.
601 *
602 * We receive ownership of entries.
603 */
604int ust_registry_create_or_find_enum(struct ust_registry_session *session,
605 int session_objd, char *enum_name,
b623cb6a 606 struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries,
10b56aef
MD
607 uint64_t *enum_id)
608{
609 int ret = 0;
610 struct cds_lfht_node *nodep;
611 struct ust_registry_enum *reg_enum = NULL, *old_reg_enum;
612
613 assert(session);
614 assert(enum_name);
615
616 rcu_read_lock();
617
618 /*
619 * This should not happen but since it comes from the UST tracer, an
620 * external party, don't assert and simply validate values.
621 */
622 if (session_objd < 0) {
623 ret = -EINVAL;
624 goto end;
625 }
626
627 /* Check if the enumeration was already dumped */
628 reg_enum = zmalloc(sizeof(*reg_enum));
629 if (!reg_enum) {
630 PERROR("zmalloc ust registry enumeration");
631 ret = -ENOMEM;
632 goto end;
633 }
fc4b93fa
MD
634 strncpy(reg_enum->name, enum_name, LTTNG_UST_ABI_SYM_NAME_LEN);
635 reg_enum->name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
10b56aef
MD
636 /* entries will be owned by reg_enum. */
637 reg_enum->entries = entries;
638 reg_enum->nr_entries = nr_entries;
639 entries = NULL;
640
641 old_reg_enum = ust_registry_lookup_enum(session, reg_enum);
642 if (old_reg_enum) {
643 DBG("enum %s already in sess_objd: %u", enum_name, session_objd);
644 /* Fall through. Use prior enum. */
645 destroy_enum(reg_enum);
646 reg_enum = old_reg_enum;
647 } else {
648 DBG("UST registry creating enum: %s, sess_objd: %u",
649 enum_name, session_objd);
650 if (session->next_enum_id == -1ULL) {
651 ret = -EOVERFLOW;
652 destroy_enum(reg_enum);
653 goto end;
654 }
655 reg_enum->id = session->next_enum_id++;
656 cds_lfht_node_init(&reg_enum->node.node);
657 nodep = cds_lfht_add_unique(session->enums->ht,
658 ht_hash_enum(reg_enum, lttng_ht_seed),
659 ht_match_enum_id, reg_enum,
660 &reg_enum->node.node);
661 assert(nodep == &reg_enum->node.node);
662 }
663 DBG("UST registry reply with enum %s with id %" PRIu64 " in sess_objd: %u",
664 enum_name, reg_enum->id, session_objd);
665 *enum_id = reg_enum->id;
666end:
667 free(entries);
668 rcu_read_unlock();
669 return ret;
670}
671
672/*
673 * For a given enumeration in a registry, delete the entry and destroy
674 * the enumeration.
675 * This MUST be called within a RCU read side lock section.
676 */
10dc2d10 677static void ust_registry_destroy_enum(struct ust_registry_session *reg_session,
10b56aef
MD
678 struct ust_registry_enum *reg_enum)
679{
680 int ret;
681 struct lttng_ht_iter iter;
682
683 assert(reg_session);
684 assert(reg_enum);
685
686 /* Delete the node first. */
687 iter.iter.node = &reg_enum->node.node;
688 ret = lttng_ht_del(reg_session->enums, &iter);
689 assert(!ret);
690 call_rcu(&reg_enum->rcu_head, destroy_enum_rcu);
691}
692
36b588ed
MD
693/*
694 * We need to execute ht_destroy outside of RCU read-side critical
0b2dc8df
MD
695 * section and outside of call_rcu thread, so we postpone its execution
696 * using ht_cleanup_push. It is simpler than to change the semantic of
697 * the many callers of delete_ust_app_session().
36b588ed
MD
698 */
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
9dbcf332 705 if (chan->ht) {
0b2dc8df 706 ht_cleanup_push(chan->ht);
9dbcf332 707 }
3295105b 708 free(chan->ctx_fields);
36b588ed
MD
709 free(chan);
710}
711
d0b96690
DG
712/*
713 * Destroy every element of the registry and free the memory. This does NOT
714 * free the registry pointer since it might not have been allocated before so
715 * it's the caller responsability.
d0b96690 716 */
e9404c27 717static void destroy_channel(struct ust_registry_channel *chan, bool notif)
d0b96690
DG
718{
719 struct lttng_ht_iter iter;
720 struct ust_registry_event *event;
e9404c27 721 enum lttng_error_code cmd_ret;
d0b96690
DG
722
723 assert(chan);
724
e9404c27
JG
725 if (notif) {
726 cmd_ret = notification_thread_command_remove_channel(
412d7227
SM
727 the_notification_thread_handle,
728 chan->consumer_key, LTTNG_DOMAIN_UST);
e9404c27
JG
729 if (cmd_ret != LTTNG_OK) {
730 ERR("Failed to remove channel from notification thread");
731 }
732 }
733
70987ead
JG
734 if (chan->ht) {
735 rcu_read_lock();
736 /* Destroy all event associated with this registry. */
737 cds_lfht_for_each_entry(
738 chan->ht->ht, &iter.iter, event, node.node) {
739 /* Delete the node from the ht and free it. */
740 ust_registry_destroy_event(chan, event);
741 }
742 rcu_read_unlock();
d0b96690 743 }
36b588ed 744 call_rcu(&chan->rcu_head, destroy_channel_rcu);
d0b96690
DG
745}
746
747/*
748 * Initialize registry with default values.
749 */
45893984
DG
750int ust_registry_channel_add(struct ust_registry_session *session,
751 uint64_t key)
752{
753 int ret = 0;
754 struct ust_registry_channel *chan;
755
756 assert(session);
757
758 chan = zmalloc(sizeof(*chan));
759 if (!chan) {
760 PERROR("zmalloc ust registry channel");
761 ret = -ENOMEM;
9dbcf332 762 goto error_alloc;
45893984
DG
763 }
764
765 chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
766 if (!chan->ht) {
767 ret = -ENOMEM;
768 goto error;
769 }
770
771 /* Set custom match function. */
772 chan->ht->match_fct = ht_match_event;
7972aab2
DG
773 chan->ht->hash_fct = ht_hash_event;
774
775 /*
776 * Assign a channel ID right now since the event notification comes
777 * *before* the channel notify so the ID needs to be set at this point so
778 * the metadata can be dumped for that event.
779 */
780 if (ust_registry_is_max_id(session->used_channel_id)) {
781 ret = -1;
782 goto error;
783 }
784 chan->chan_id = ust_registry_get_next_chan_id(session);
45893984
DG
785
786 rcu_read_lock();
787 lttng_ht_node_init_u64(&chan->node, key);
788 lttng_ht_add_unique_u64(session->channels, &chan->node);
789 rcu_read_unlock();
790
9dbcf332
DG
791 return 0;
792
45893984 793error:
e9404c27 794 destroy_channel(chan, false);
9dbcf332 795error_alloc:
45893984
DG
796 return ret;
797}
798
799/*
800 * Find a channel in the given registry. RCU read side lock MUST be acquired
801 * before calling this function and as long as the event reference is kept by
802 * the caller.
803 *
804 * On success, the pointer is returned else NULL.
805 */
806struct ust_registry_channel *ust_registry_channel_find(
807 struct ust_registry_session *session, uint64_t key)
808{
809 struct lttng_ht_node_u64 *node;
810 struct lttng_ht_iter iter;
811 struct ust_registry_channel *chan = NULL;
812
813 assert(session);
814 assert(session->channels);
815
7972aab2
DG
816 DBG3("UST registry channel finding key %" PRIu64, key);
817
45893984
DG
818 lttng_ht_lookup(session->channels, &key, &iter);
819 node = lttng_ht_iter_get_node_u64(&iter);
820 if (!node) {
821 goto end;
822 }
823 chan = caa_container_of(node, struct ust_registry_channel, node);
824
825end:
826 return chan;
827}
828
829/*
830 * Remove channel using key from registry and free memory.
831 */
832void ust_registry_channel_del_free(struct ust_registry_session *session,
e9404c27 833 uint64_t key, bool notif)
45893984
DG
834{
835 struct lttng_ht_iter iter;
836 struct ust_registry_channel *chan;
9209cee7 837 int ret;
45893984
DG
838
839 assert(session);
840
841 rcu_read_lock();
842 chan = ust_registry_channel_find(session, key);
843 if (!chan) {
9209cee7 844 rcu_read_unlock();
45893984
DG
845 goto end;
846 }
847
848 iter.iter.node = &chan->node.node;
9209cee7
MD
849 ret = lttng_ht_del(session->channels, &iter);
850 assert(!ret);
851 rcu_read_unlock();
e9404c27 852 destroy_channel(chan, notif);
45893984
DG
853
854end:
45893984
DG
855 return;
856}
857
858/*
859 * Initialize registry with default values and set the newly allocated session
860 * pointer to sessionp.
861 *
862 * Return 0 on success and sessionp is set or else return -1 and sessionp is
863 * kept untouched.
864 */
865int ust_registry_session_init(struct ust_registry_session **sessionp,
d0b96690
DG
866 struct ust_app *app,
867 uint32_t bits_per_long,
868 uint32_t uint8_t_alignment,
869 uint32_t uint16_t_alignment,
870 uint32_t uint32_t_alignment,
871 uint32_t uint64_t_alignment,
872 uint32_t long_alignment,
af6142cf
MD
873 int byte_order,
874 uint32_t major,
d7ba1388 875 uint32_t minor,
3d071855 876 const char *root_shm_path,
d7ba1388
MD
877 const char *shm_path,
878 uid_t euid,
8de88061
JR
879 gid_t egid,
880 uint64_t tracing_id,
881 uid_t tracing_uid)
d0b96690
DG
882{
883 int ret;
45893984 884 struct ust_registry_session *session;
d0b96690 885
45893984 886 assert(sessionp);
d0b96690 887
45893984
DG
888 session = zmalloc(sizeof(*session));
889 if (!session) {
890 PERROR("zmalloc ust registry session");
9dbcf332 891 goto error_alloc;
45893984 892 }
d0b96690
DG
893
894 pthread_mutex_init(&session->lock, NULL);
895 session->bits_per_long = bits_per_long;
896 session->uint8_t_alignment = uint8_t_alignment;
897 session->uint16_t_alignment = uint16_t_alignment;
898 session->uint32_t_alignment = uint32_t_alignment;
899 session->uint64_t_alignment = uint64_t_alignment;
900 session->long_alignment = long_alignment;
901 session->byte_order = byte_order;
d7ba1388 902 session->metadata_fd = -1;
4628484a
MD
903 session->uid = euid;
904 session->gid = egid;
10b56aef 905 session->next_enum_id = 0;
7062f070
JD
906 session->major = major;
907 session->minor = minor;
3d071855
MD
908 strncpy(session->root_shm_path, root_shm_path,
909 sizeof(session->root_shm_path));
910 session->root_shm_path[sizeof(session->root_shm_path) - 1] = '\0';
d7ba1388
MD
911 if (shm_path[0]) {
912 strncpy(session->shm_path, shm_path,
913 sizeof(session->shm_path));
914 session->shm_path[sizeof(session->shm_path) - 1] = '\0';
915 strncpy(session->metadata_path, shm_path,
916 sizeof(session->metadata_path));
917 session->metadata_path[sizeof(session->metadata_path) - 1] = '\0';
918 strncat(session->metadata_path, "/metadata",
919 sizeof(session->metadata_path)
920 - strlen(session->metadata_path) - 1);
921 }
922 if (session->shm_path[0]) {
923 ret = run_as_mkdir_recursive(session->shm_path,
924 S_IRWXU | S_IRWXG,
925 euid, egid);
926 if (ret) {
927 PERROR("run_as_mkdir_recursive");
928 goto error;
929 }
930 }
931 if (session->metadata_path[0]) {
932 /* Create metadata file */
4628484a 933 ret = run_as_open(session->metadata_path,
d7ba1388 934 O_WRONLY | O_CREAT | O_EXCL,
4628484a 935 S_IRUSR | S_IWUSR, euid, egid);
d7ba1388
MD
936 if (ret < 0) {
937 PERROR("Opening metadata file");
938 goto error;
939 }
940 session->metadata_fd = ret;
941 }
d0b96690 942
10b56aef
MD
943 session->enums = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
944 if (!session->enums) {
de64322e 945 ERR("Failed to create enums hash table");
10b56aef
MD
946 goto error;
947 }
948 /* hash/match functions are specified at call site. */
949 session->enums->match_fct = NULL;
950 session->enums->hash_fct = NULL;
951
45893984
DG
952 session->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
953 if (!session->channels) {
954 goto error;
955 }
956
d0b96690
DG
957 ret = lttng_uuid_generate(session->uuid);
958 if (ret) {
959 ERR("Failed to generate UST uuid (errno = %d)", ret);
960 goto error;
961 }
962
8de88061
JR
963 session->tracing_id = tracing_id;
964 session->tracing_uid = tracing_uid;
965
d0b96690 966 pthread_mutex_lock(&session->lock);
af6142cf 967 ret = ust_metadata_session_statedump(session, app, major, minor);
d0b96690
DG
968 pthread_mutex_unlock(&session->lock);
969 if (ret) {
970 ERR("Failed to generate session metadata (errno = %d)", ret);
971 goto error;
972 }
973
45893984
DG
974 *sessionp = session;
975
d0b96690
DG
976 return 0;
977
978error:
9dbcf332 979 ust_registry_session_destroy(session);
d24ff3fd 980 free(session);
9dbcf332 981error_alloc:
d0b96690
DG
982 return -1;
983}
984
985/*
986 * Destroy session registry. This does NOT free the given pointer since it
987 * might get passed as a reference. The registry lock should NOT be acquired.
988 */
989void ust_registry_session_destroy(struct ust_registry_session *reg)
990{
991 int ret;
45893984
DG
992 struct lttng_ht_iter iter;
993 struct ust_registry_channel *chan;
10b56aef 994 struct ust_registry_enum *reg_enum;
d0b96690 995
286c991a
MD
996 if (!reg) {
997 return;
998 }
9d8efb0e 999
d0b96690
DG
1000 /* On error, EBUSY can be returned if lock. Code flow error. */
1001 ret = pthread_mutex_destroy(&reg->lock);
1002 assert(!ret);
1003
9d8efb0e
DG
1004 if (reg->channels) {
1005 rcu_read_lock();
1006 /* Destroy all event associated with this registry. */
1007 cds_lfht_for_each_entry(reg->channels->ht, &iter.iter, chan,
1008 node.node) {
1009 /* Delete the node from the ht and free it. */
1010 ret = lttng_ht_del(reg->channels, &iter);
1011 assert(!ret);
e9404c27 1012 destroy_channel(chan, true);
9d8efb0e
DG
1013 }
1014 rcu_read_unlock();
1015 ht_cleanup_push(reg->channels);
45893984 1016 }
45893984 1017
d0b96690 1018 free(reg->metadata);
d7ba1388
MD
1019 if (reg->metadata_fd >= 0) {
1020 ret = close(reg->metadata_fd);
1021 if (ret) {
1022 PERROR("close");
1023 }
4628484a
MD
1024 ret = run_as_unlink(reg->metadata_path,
1025 reg->uid, reg->gid);
d7ba1388
MD
1026 if (ret) {
1027 PERROR("unlink");
1028 }
1029 }
3d071855
MD
1030 if (reg->root_shm_path[0]) {
1031 /*
1032 * Try deleting the directory hierarchy.
1033 */
602766ec 1034 (void) run_as_rmdir_recursive(reg->root_shm_path,
f75c5439
MD
1035 reg->uid, reg->gid,
1036 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG);
3d071855 1037 }
10b56aef
MD
1038 /* Destroy the enum hash table */
1039 if (reg->enums) {
1040 rcu_read_lock();
1041 /* Destroy all enum entries associated with this registry. */
1042 cds_lfht_for_each_entry(reg->enums->ht, &iter.iter, reg_enum,
1043 node.node) {
1044 ust_registry_destroy_enum(reg, reg_enum);
1045 }
1046 rcu_read_unlock();
1047 ht_cleanup_push(reg->enums);
1048 }
d0b96690 1049}
This page took 0.108154 seconds and 4 git commands to generate.