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