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