SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / bin / lttng-sessiond / buffer-registry.c
CommitLineData
7972aab2 1/*
ab5be9fa 2 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
7972aab2 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
7972aab2 5 *
7972aab2
DG
6 */
7
6c1c0768 8#define _LGPL_SOURCE
7972aab2
DG
9#include <inttypes.h>
10
11#include <common/common.h>
12#include <common/hashtable/utils.h>
13
14#include "buffer-registry.h"
15#include "fd-limit.h"
16#include "ust-consumer.h"
75018ab6
JG
17#include "lttng-ust-ctl.h"
18#include "lttng-ust-error.h"
0b2dc8df 19#include "utils.h"
7972aab2
DG
20
21/*
22 * Set in main.c during initialization process of the daemon. This contains
23 * buffer_reg_uid object which are global registry for per UID buffer. Object
24 * are indexed by session id and matched by the triplet
25 * <session_id/bits_per_long/uid>.
26 */
27static struct lttng_ht *buffer_registry_uid;
28
29/*
30 * Initialized at the daemon start. This contains buffer_reg_pid object and
31 * indexed by session id.
32 */
33static struct lttng_ht *buffer_registry_pid;
34
35/*
36 * Match function for the per UID registry hash table. It matches a registry
37 * uid object with the triplet <session_id/abi/uid>.
38 */
39static int ht_match_reg_uid(struct cds_lfht_node *node, const void *_key)
40{
41 struct buffer_reg_uid *reg;
42 const struct buffer_reg_uid *key;
43
44 assert(node);
45 assert(_key);
46
47 reg = caa_container_of(node, struct buffer_reg_uid, node.node);
48 assert(reg);
49 key = _key;
50
51 if (key->session_id != reg->session_id ||
52 key->bits_per_long != reg->bits_per_long ||
53 key->uid != reg->uid) {
54 goto no_match;
55 }
56
57 /* Match */
58 return 1;
59no_match:
60 return 0;
61}
62
63/*
64 * Hash function for the per UID registry hash table. This XOR the triplet
65 * together.
66 */
bcd52dd9 67static unsigned long ht_hash_reg_uid(const void *_key, unsigned long seed)
7972aab2
DG
68{
69 uint64_t xored_key;
bcd52dd9 70 const struct buffer_reg_uid *key = _key;
7972aab2
DG
71
72 assert(key);
73
74 xored_key = (uint64_t)(key->session_id ^ key->bits_per_long ^ key->uid);
75 return hash_key_u64(&xored_key, seed);
76}
77
78/*
79 * Initialize global buffer per UID registry. Should only be called ONCE!.
80 */
81void buffer_reg_init_uid_registry(void)
82{
83 /* Should be called once. */
84 assert(!buffer_registry_uid);
85 buffer_registry_uid = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
86 assert(buffer_registry_uid);
87 buffer_registry_uid->match_fct = ht_match_reg_uid;
88 buffer_registry_uid->hash_fct = ht_hash_reg_uid;
89
90 DBG3("Global buffer per UID registry initialized");
91}
92
93/*
94 * Allocate and initialize object. Set regp with the object pointer.
95 *
96 * Return 0 on success else a negative value and regp is untouched.
97 */
d9bf3ca4 98int buffer_reg_uid_create(uint64_t session_id, uint32_t bits_per_long, uid_t uid,
d7ba1388 99 enum lttng_domain_type domain, struct buffer_reg_uid **regp,
3d071855 100 const char *root_shm_path, const char *shm_path)
7972aab2
DG
101{
102 int ret = 0;
103 struct buffer_reg_uid *reg = NULL;
104
105 assert(regp);
106
107 reg = zmalloc(sizeof(*reg));
108 if (!reg) {
109 PERROR("zmalloc buffer registry uid");
110 ret = -ENOMEM;
111 goto error;
112 }
113
114 reg->registry = zmalloc(sizeof(struct buffer_reg_session));
63c861bd 115 if (!reg->registry) {
7972aab2
DG
116 PERROR("zmalloc buffer registry uid session");
117 ret = -ENOMEM;
118 goto error;
119 }
120
121 reg->session_id = session_id;
122 reg->bits_per_long = bits_per_long;
123 reg->uid = uid;
124 reg->domain = domain;
d7ba1388 125 if (shm_path[0]) {
3d071855
MD
126 strncpy(reg->root_shm_path, root_shm_path, sizeof(reg->root_shm_path));
127 reg->root_shm_path[sizeof(reg->root_shm_path) - 1] = '\0';
d7ba1388
MD
128 strncpy(reg->shm_path, shm_path, sizeof(reg->shm_path));
129 reg->shm_path[sizeof(reg->shm_path) - 1] = '\0';
130 DBG3("shm path '%s' is assigned to uid buffer registry for session id %" PRIu64,
131 reg->shm_path, session_id);
132 }
7972aab2
DG
133 reg->registry->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
134 if (!reg->registry->channels) {
135 ret = -ENOMEM;
136 goto error_session;
137 }
138
ebdb334b
JR
139 reg->registry->maps = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
140 if (!reg->registry->maps) {
141 lttng_ht_destroy(reg->registry->channels);
142 ret = -ENOMEM;
143 goto error_session;
144 }
145
146
7972aab2
DG
147 cds_lfht_node_init(&reg->node.node);
148 *regp = reg;
149
d9bf3ca4 150 DBG3("Buffer registry per UID created id: %" PRIu64 ", ABI: %u, uid: %d, domain: %d",
7972aab2
DG
151 session_id, bits_per_long, uid, domain);
152
153 return 0;
154
155error_session:
156 free(reg->registry);
157error:
158 free(reg);
159 return ret;
160}
161
162/*
163 * Add a buffer registry per UID object to the global registry.
164 */
165void buffer_reg_uid_add(struct buffer_reg_uid *reg)
166{
167 struct cds_lfht_node *nodep;
168 struct lttng_ht *ht = buffer_registry_uid;
169
170 assert(reg);
171
d9bf3ca4 172 DBG3("Buffer registry per UID adding to global registry with id: %" PRIu64 ,
7972aab2
DG
173 reg->session_id);
174
175 rcu_read_lock();
176 nodep = cds_lfht_add_unique(ht->ht, ht->hash_fct(reg, lttng_ht_seed),
177 ht->match_fct, reg, &reg->node.node);
178 assert(nodep == &reg->node.node);
179 rcu_read_unlock();
180}
181
182/*
183 * Find a buffer registry per UID object with given params. RCU read side lock
184 * MUST be acquired before calling this and hold on to protect the object.
185 *
186 * Return the object pointer or NULL on error.
187 */
d9bf3ca4 188struct buffer_reg_uid *buffer_reg_uid_find(uint64_t session_id,
7972aab2
DG
189 uint32_t bits_per_long, uid_t uid)
190{
191 struct lttng_ht_node_u64 *node;
192 struct lttng_ht_iter iter;
193 struct buffer_reg_uid *reg = NULL, key;
194 struct lttng_ht *ht = buffer_registry_uid;
195
196 /* Setup key we are looking for. */
197 key.session_id = session_id;
198 key.bits_per_long = bits_per_long;
199 key.uid = uid;
200
d9bf3ca4 201 DBG3("Buffer registry per UID find id: %" PRIu64 ", ABI: %u, uid: %d",
7972aab2
DG
202 session_id, bits_per_long, uid);
203
204 /* Custom lookup function since it's a different key. */
205 cds_lfht_lookup(ht->ht, ht->hash_fct(&key, lttng_ht_seed), ht->match_fct,
206 &key, &iter.iter);
207 node = lttng_ht_iter_get_node_u64(&iter);
208 if (!node) {
209 goto end;
210 }
211 reg = caa_container_of(node, struct buffer_reg_uid, node);
212
213end:
214 return reg;
215}
216
217/*
218 * Initialize global buffer per PID registry. Should only be called ONCE!.
219 */
220void buffer_reg_init_pid_registry(void)
221{
222 /* Should be called once. */
223 assert(!buffer_registry_pid);
d9bf3ca4 224 buffer_registry_pid = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
7972aab2
DG
225 assert(buffer_registry_pid);
226
227 DBG3("Global buffer per PID registry initialized");
228}
229
230/*
231 * Allocate and initialize object. Set regp with the object pointer.
232 *
233 * Return 0 on success else a negative value and regp is untouched.
234 */
d7ba1388 235int buffer_reg_pid_create(uint64_t session_id, struct buffer_reg_pid **regp,
3d071855 236 const char *root_shm_path, const char *shm_path)
7972aab2
DG
237{
238 int ret = 0;
239 struct buffer_reg_pid *reg = NULL;
240
241 assert(regp);
242
243 reg = zmalloc(sizeof(*reg));
244 if (!reg) {
245 PERROR("zmalloc buffer registry pid");
246 ret = -ENOMEM;
247 goto error;
248 }
249
250 reg->registry = zmalloc(sizeof(struct buffer_reg_session));
63c861bd 251 if (!reg->registry) {
7972aab2
DG
252 PERROR("zmalloc buffer registry pid session");
253 ret = -ENOMEM;
254 goto error;
255 }
256
257 /* A cast is done here so we can use the session ID as a u64 ht node. */
258 reg->session_id = session_id;
d7ba1388 259 if (shm_path[0]) {
3d071855
MD
260 strncpy(reg->root_shm_path, root_shm_path, sizeof(reg->root_shm_path));
261 reg->root_shm_path[sizeof(reg->root_shm_path) - 1] = '\0';
d7ba1388
MD
262 strncpy(reg->shm_path, shm_path, sizeof(reg->shm_path));
263 reg->shm_path[sizeof(reg->shm_path) - 1] = '\0';
264 DBG3("shm path '%s' is assigned to pid buffer registry for session id %" PRIu64,
265 reg->shm_path, session_id);
266 }
7972aab2
DG
267 reg->registry->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
268 if (!reg->registry->channels) {
269 ret = -ENOMEM;
270 goto error_session;
271 }
272
ebdb334b
JR
273 reg->registry->maps = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
274 if (!reg->registry->maps) {
275 lttng_ht_destroy(reg->registry->channels);
276 ret = -ENOMEM;
277 goto error_session;
278 }
279
d9bf3ca4 280 lttng_ht_node_init_u64(&reg->node, reg->session_id);
7972aab2
DG
281 *regp = reg;
282
d9bf3ca4
MD
283 DBG3("Buffer registry per PID created with session id: %" PRIu64,
284 session_id);
7972aab2
DG
285
286 return 0;
287
288error_session:
289 free(reg->registry);
290error:
291 free(reg);
292 return ret;
293}
294
295/*
296 * Add a buffer registry per PID object to the global registry.
297 */
298void buffer_reg_pid_add(struct buffer_reg_pid *reg)
299{
300 assert(reg);
301
d9bf3ca4 302 DBG3("Buffer registry per PID adding to global registry with id: %" PRIu64,
7972aab2
DG
303 reg->session_id);
304
305 rcu_read_lock();
d9bf3ca4 306 lttng_ht_add_unique_u64(buffer_registry_pid, &reg->node);
7972aab2
DG
307 rcu_read_unlock();
308}
309
310/*
311 * Find a buffer registry per PID object with given params. RCU read side lock
312 * MUST be acquired before calling this and hold on to protect the object.
313 *
314 * Return the object pointer or NULL on error.
315 */
d9bf3ca4 316struct buffer_reg_pid *buffer_reg_pid_find(uint64_t session_id)
7972aab2 317{
d9bf3ca4 318 struct lttng_ht_node_u64 *node;
7972aab2
DG
319 struct lttng_ht_iter iter;
320 struct buffer_reg_pid *reg = NULL;
321 struct lttng_ht *ht = buffer_registry_pid;
322
d9bf3ca4 323 DBG3("Buffer registry per PID find id: %" PRIu64, session_id);
7972aab2 324
d9bf3ca4
MD
325 lttng_ht_lookup(ht, &session_id, &iter);
326 node = lttng_ht_iter_get_node_u64(&iter);
7972aab2
DG
327 if (!node) {
328 goto end;
329 }
330 reg = caa_container_of(node, struct buffer_reg_pid, node);
331
332end:
333 return reg;
334}
335
fb83fe64
JD
336/*
337 * Find the consumer channel key from a UST session per-uid channel key.
338 *
339 * Return the matching key or -1 if not found.
340 */
341int buffer_reg_uid_consumer_channel_key(
342 struct cds_list_head *buffer_reg_uid_list,
76604852 343 uint64_t chan_key, uint64_t *consumer_chan_key)
fb83fe64
JD
344{
345 struct lttng_ht_iter iter;
346 struct buffer_reg_uid *uid_reg = NULL;
347 struct buffer_reg_session *session_reg = NULL;
348 struct buffer_reg_channel *reg_chan;
349 int ret = -1;
350
351 rcu_read_lock();
352 /*
353 * For the per-uid registry, we have to iterate since we don't have the
354 * uid and bitness key.
355 */
356 cds_list_for_each_entry(uid_reg, buffer_reg_uid_list, lnode) {
357 session_reg = uid_reg->registry;
358 cds_lfht_for_each_entry(session_reg->channels->ht,
359 &iter.iter, reg_chan, node.node) {
360 if (reg_chan->key == chan_key) {
361 *consumer_chan_key = reg_chan->consumer_key;
362 ret = 0;
363 goto end;
364 }
365 }
366 }
367
368end:
369 rcu_read_unlock();
370 return ret;
371}
372
7972aab2
DG
373/*
374 * Allocate and initialize a buffer registry channel with the given key. Set
375 * regp with the object pointer.
376 *
377 * Return 0 on success or else a negative value keeping regp untouched.
378 */
379int buffer_reg_channel_create(uint64_t key, struct buffer_reg_channel **regp)
380{
381 struct buffer_reg_channel *reg;
382
383 assert(regp);
384
385 DBG3("Buffer registry channel create with key: %" PRIu64, key);
386
387 reg = zmalloc(sizeof(*reg));
388 if (!reg) {
389 PERROR("zmalloc buffer registry channel");
390 return -ENOMEM;
391 }
392
393 reg->key = key;
394 CDS_INIT_LIST_HEAD(&reg->streams);
395 pthread_mutex_init(&reg->stream_list_lock, NULL);
396
397 lttng_ht_node_init_u64(&reg->node, key);
398 *regp = reg;
399
400 return 0;
401}
402
ebdb334b
JR
403/*
404 * Allocate and initialize a buffer registry map with the given key. Set
405 * regp with the object pointer.
406 *
407 * Return 0 on success or else a negative value keeping regp untouched.
408 */
409int buffer_reg_map_create(uint64_t key, struct buffer_reg_map **regp)
410{
411 struct buffer_reg_map *reg;
412
413 assert(regp);
414
415 DBG3("Buffer registry map create with key: %" PRIu64, key);
416
417 reg = zmalloc(sizeof(*reg));
418 if (!reg) {
419 PERROR("zmalloc buffer registry map");
420 return -ENOMEM;
421 }
422
423 reg->key = key;
424 CDS_INIT_LIST_HEAD(&reg->counters);
425 pthread_mutex_init(&reg->counter_list_lock, NULL);
426
427 lttng_ht_node_init_u64(&reg->node, key);
428 *regp = reg;
429
430 return 0;
431}
432
7972aab2
DG
433/*
434 * Allocate and initialize a buffer registry stream. Set regp with the object
435 * pointer.
436 *
437 * Return 0 on success or else a negative value keeping regp untouched.
438 */
439int buffer_reg_stream_create(struct buffer_reg_stream **regp)
440{
441 struct buffer_reg_stream *reg;
442
443 assert(regp);
444
445 DBG3("Buffer registry creating stream");
446
447 reg = zmalloc(sizeof(*reg));
448 if (!reg) {
449 PERROR("zmalloc buffer registry stream");
450 return -ENOMEM;
451 }
452
453 *regp = reg;
454
455 return 0;
456}
457
ebdb334b
JR
458/*
459 * Allocate and initialize a buffer registry map_counter. Set regp with the object
460 * pointer.
461 *
462 * Return 0 on success or else a negative value keeping regp untouched.
463 */
464int buffer_reg_map_counter_create(struct buffer_reg_map_counter **regp)
465{
466 struct buffer_reg_map_counter *reg;
467
468 assert(regp);
469
470 DBG3("Buffer registry creating map_counter");
471
472 reg = zmalloc(sizeof(*reg));
473 if (!reg) {
474 PERROR("zmalloc buffer registry map_counter");
475 return -ENOMEM;
476 }
477
478 *regp = reg;
479
480 return 0;
481}
482
7972aab2
DG
483/*
484 * Add stream to the list in the channel.
485 */
486void buffer_reg_stream_add(struct buffer_reg_stream *stream,
487 struct buffer_reg_channel *channel)
488{
489 assert(stream);
490 assert(channel);
491
492 pthread_mutex_lock(&channel->stream_list_lock);
493 cds_list_add_tail(&stream->lnode, &channel->streams);
5c786ded 494 channel->stream_count++;
7972aab2
DG
495 pthread_mutex_unlock(&channel->stream_list_lock);
496}
497
ebdb334b
JR
498/*
499 * Add map_counter to the list in the map.
500 */
501void buffer_reg_map_counter_add(struct buffer_reg_map_counter *map_counter,
502 struct buffer_reg_map *map)
503{
504 assert(map_counter);
505 assert(map);
506
507 pthread_mutex_lock(&map->counter_list_lock);
508 cds_list_add_tail(&map_counter->lnode, &map->counters);
509 map->counter_count++;
510 pthread_mutex_unlock(&map->counter_list_lock);
511}
512
7972aab2
DG
513/*
514 * Add a buffer registry channel object to the given session.
515 */
516void buffer_reg_channel_add(struct buffer_reg_session *session,
517 struct buffer_reg_channel *channel)
518{
519 assert(session);
520 assert(channel);
521
522 rcu_read_lock();
523 lttng_ht_add_unique_u64(session->channels, &channel->node);
524 rcu_read_unlock();
525}
526
ebdb334b
JR
527/*
528 * Add a buffer registry map object to the given session.
529 */
530void buffer_reg_map_add(struct buffer_reg_session *session,
531 struct buffer_reg_map *map)
532{
533 assert(session);
534 assert(map);
535
536 rcu_read_lock();
537 lttng_ht_add_unique_u64(session->maps, &map->node);
538 rcu_read_unlock();
539}
540
7972aab2
DG
541/*
542 * Find a buffer registry channel object with the given key. RCU read side lock
543 * MUST be acquired and hold on until the object reference is not needed
544 * anymore.
545 *
546 * Return the object pointer or NULL on error.
547 */
548struct buffer_reg_channel *buffer_reg_channel_find(uint64_t key,
549 struct buffer_reg_uid *reg)
550{
551 struct lttng_ht_node_u64 *node;
552 struct lttng_ht_iter iter;
553 struct buffer_reg_channel *chan = NULL;
554 struct lttng_ht *ht;
555
556 assert(reg);
557
558 switch (reg->domain) {
559 case LTTNG_DOMAIN_UST:
560 ht = reg->registry->channels;
561 break;
562 default:
563 assert(0);
564 goto end;
565 }
566
567 lttng_ht_lookup(ht, &key, &iter);
568 node = lttng_ht_iter_get_node_u64(&iter);
569 if (!node) {
570 goto end;
571 }
572 chan = caa_container_of(node, struct buffer_reg_channel, node);
573
574end:
575 return chan;
576}
577
ebdb334b
JR
578/*
579 * Find a buffer registry map object with the given key. RCU read side lock
580 * MUST be acquired and hold on until the object reference is not needed
581 * anymore.
582 *
583 * Return the object pointer or NULL on error.
584 */
585struct buffer_reg_map *buffer_reg_map_find(uint64_t key,
586 struct buffer_reg_uid *reg)
587{
588 struct lttng_ht_node_u64 *node;
589 struct lttng_ht_iter iter;
590 struct buffer_reg_map *map = NULL;
591 struct lttng_ht *ht;
592
593 assert(reg);
594
595 switch (reg->domain) {
596 case LTTNG_DOMAIN_UST:
597 ht = reg->registry->maps;
598 break;
599 default:
600 assert(0);
601 goto end;
602 }
603
604 lttng_ht_lookup(ht, &key, &iter);
605 node = lttng_ht_iter_get_node_u64(&iter);
606 if (!node) {
607 goto end;
608 }
609 map = caa_container_of(node, struct buffer_reg_map, node);
610
611end:
612 return map;
613}
614
7972aab2
DG
615/*
616 * Destroy a buffer registry stream with the given domain.
617 */
618void buffer_reg_stream_destroy(struct buffer_reg_stream *regp,
619 enum lttng_domain_type domain)
620{
621 if (!regp) {
622 return;
623 }
624
625 DBG3("Buffer registry stream destroy with handle %d",
626 regp->obj.ust->handle);
627
628 switch (domain) {
629 case LTTNG_DOMAIN_UST:
630 {
631 int ret;
632
fb45065e 633 ret = ust_app_release_object(NULL, regp->obj.ust);
7972aab2
DG
634 if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
635 ERR("Buffer reg stream release obj handle %d failed with ret %d",
636 regp->obj.ust->handle, ret);
637 }
638 free(regp->obj.ust);
639 lttng_fd_put(LTTNG_FD_APPS, 2);
640 break;
641 }
642 default:
643 assert(0);
644 }
645
646 free(regp);
647 return;
648}
649
ebdb334b
JR
650/*
651 * Destroy a buffer registry map_counter with the given domain.
652 */
653void buffer_reg_map_counter_destroy(struct buffer_reg_map_counter *regp,
654 enum lttng_domain_type domain)
655{
656 if (!regp) {
657 return;
658 }
659
660 DBG3("Buffer registry map counter destroy with handle %d",
661 regp->obj.ust->handle);
662
663 switch (domain) {
664 case LTTNG_DOMAIN_UST:
665 {
666 int ret;
667
668 ret = ust_app_release_object(NULL, regp->obj.ust);
669 if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
670 ERR("Buffer reg map counter release obj handle %d failed with ret %d",
671 regp->obj.ust->handle, ret);
672 }
673 free(regp->obj.ust);
674 lttng_fd_put(LTTNG_FD_APPS, 2);
675 break;
676 }
677 default:
678 assert(0);
679 }
680
681 free(regp);
682 return;
683}
684
7972aab2
DG
685/*
686 * Remove buffer registry channel object from the session hash table. RCU read
687 * side lock MUST be acquired before calling this.
688 */
689void buffer_reg_channel_remove(struct buffer_reg_session *session,
690 struct buffer_reg_channel *regp)
691{
692 int ret;
693 struct lttng_ht_iter iter;
694
695 assert(session);
696 assert(regp);
697
698 iter.iter.node = &regp->node.node;
699 ret = lttng_ht_del(session->channels, &iter);
700 assert(!ret);
701}
702
ebdb334b
JR
703/*
704 * Remove buffer registry map object from the session hash table. RCU read
705 * side lock MUST be acquired before calling this.
706 */
707void buffer_reg_map_remove(struct buffer_reg_session *session,
708 struct buffer_reg_map *regp)
709{
710 int ret;
711 struct lttng_ht_iter iter;
712
713 assert(session);
714 assert(regp);
715
716 iter.iter.node = &regp->node.node;
717 ret = lttng_ht_del(session->maps, &iter);
718 assert(!ret);
719}
720
7972aab2
DG
721/*
722 * Destroy a buffer registry channel with the given domain.
723 */
724void buffer_reg_channel_destroy(struct buffer_reg_channel *regp,
725 enum lttng_domain_type domain)
726{
727 if (!regp) {
728 return;
729 }
730
07d2ae95 731 DBG3("Buffer registry channel destroy with key %" PRIu32, regp->key);
7972aab2
DG
732
733 switch (domain) {
734 case LTTNG_DOMAIN_UST:
735 {
736 int ret;
737 struct buffer_reg_stream *sreg, *stmp;
738 /* Wipe stream */
739 cds_list_for_each_entry_safe(sreg, stmp, &regp->streams, lnode) {
740 cds_list_del(&sreg->lnode);
5c786ded 741 regp->stream_count--;
7972aab2
DG
742 buffer_reg_stream_destroy(sreg, domain);
743 }
744
55d7e860 745 if (regp->obj.ust) {
fb45065e 746 ret = ust_app_release_object(NULL, regp->obj.ust);
55d7e860
MD
747 if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
748 ERR("Buffer reg channel release obj handle %d failed with ret %d",
749 regp->obj.ust->handle, ret);
750 }
751 free(regp->obj.ust);
7972aab2 752 }
7972aab2
DG
753 lttng_fd_put(LTTNG_FD_APPS, 1);
754 break;
755 }
756 default:
757 assert(0);
758 }
759
760 free(regp);
761 return;
762}
763
ebdb334b
JR
764/*
765 * Destroy a buffer registry map with the given domain.
766 */
767void buffer_reg_map_destroy(struct buffer_reg_map *regp,
768 enum lttng_domain_type domain)
769{
770 if (!regp) {
771 return;
772 }
773
774 DBG3("Buffer registry map destroy with key %" PRIu32, regp->key);
775
776 switch (domain) {
777 case LTTNG_DOMAIN_UST:
778 {
779 int ret;
780 struct buffer_reg_map_counter *map_counter_reg, *tmp;
781 /* Wipe counter */
782 cds_list_for_each_entry_safe(map_counter_reg, tmp, &regp->counters, lnode) {
783 cds_list_del(&map_counter_reg->lnode);
784 regp->counter_count--;
785 buffer_reg_map_counter_destroy(map_counter_reg, domain);
786 }
787
788 if (regp->obj.ust) {
789 ret = ust_app_release_object(NULL, regp->obj.ust);
790 if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
791 ERR("Buffer reg map release obj handle %d failed with ret %d",
792 regp->obj.ust->handle, ret);
793 }
794 free(regp->obj.ust);
795 }
796 lttng_fd_put(LTTNG_FD_APPS, 1);
797 break;
798 }
799 default:
800 assert(0);
801 }
802
803 free(regp);
804 return;
805}
806
7972aab2
DG
807/*
808 * Destroy a buffer registry session with the given domain.
36b588ed
MD
809 *
810 * Should *NOT* be called with RCU read-side lock held.
7972aab2 811 */
36b588ed 812static void buffer_reg_session_destroy(struct buffer_reg_session *regp,
7972aab2
DG
813 enum lttng_domain_type domain)
814{
815 int ret;
816 struct lttng_ht_iter iter;
817 struct buffer_reg_channel *reg_chan;
ebdb334b 818 struct buffer_reg_map *reg_map;
7972aab2
DG
819
820 DBG3("Buffer registry session destroy");
821
822 /* Destroy all channels. */
823 rcu_read_lock();
824 cds_lfht_for_each_entry(regp->channels->ht, &iter.iter, reg_chan,
825 node.node) {
826 ret = lttng_ht_del(regp->channels, &iter);
827 assert(!ret);
828 buffer_reg_channel_destroy(reg_chan, domain);
829 }
ebdb334b
JR
830 cds_lfht_for_each_entry(regp->maps->ht, &iter.iter, reg_map,
831 node.node) {
832 ret = lttng_ht_del(regp->maps, &iter);
833 assert(!ret);
834 buffer_reg_map_destroy(reg_map, domain);
835 }
7972aab2
DG
836 rcu_read_unlock();
837
0b2dc8df 838 ht_cleanup_push(regp->channels);
ebdb334b 839 ht_cleanup_push(regp->maps);
36b588ed 840
7972aab2
DG
841 switch (domain) {
842 case LTTNG_DOMAIN_UST:
843 ust_registry_session_destroy(regp->reg.ust);
844 free(regp->reg.ust);
845 break;
846 default:
847 assert(0);
848 }
849
850 free(regp);
851 return;
852}
853
854/*
36b588ed 855 * Remove buffer registry UID object from the global hash table.
7972aab2
DG
856 */
857void buffer_reg_uid_remove(struct buffer_reg_uid *regp)
858{
859 int ret;
860 struct lttng_ht_iter iter;
861
862 assert(regp);
863
36b588ed 864 rcu_read_lock();
7972aab2
DG
865 iter.iter.node = &regp->node.node;
866 ret = lttng_ht_del(buffer_registry_uid, &iter);
867 assert(!ret);
36b588ed 868 rcu_read_unlock();
7972aab2
DG
869}
870
871static void rcu_free_buffer_reg_uid(struct rcu_head *head)
872{
873 struct lttng_ht_node_u64 *node =
874 caa_container_of(head, struct lttng_ht_node_u64, head);
875 struct buffer_reg_uid *reg =
876 caa_container_of(node, struct buffer_reg_uid, node);
877
878 buffer_reg_session_destroy(reg->registry, reg->domain);
879 free(reg);
880}
881
882static void rcu_free_buffer_reg_pid(struct rcu_head *head)
883{
d9bf3ca4
MD
884 struct lttng_ht_node_u64 *node =
885 caa_container_of(head, struct lttng_ht_node_u64, head);
7972aab2
DG
886 struct buffer_reg_pid *reg =
887 caa_container_of(node, struct buffer_reg_pid, node);
888
889 buffer_reg_session_destroy(reg->registry, LTTNG_DOMAIN_UST);
890 free(reg);
891}
892
893/*
894 * Destroy buffer registry per UID. The given pointer is NOT removed from any
895 * list or hash table. Use buffer_reg_pid_remove() before calling this function
896 * for the case that the object is in the global hash table.
897 */
898void buffer_reg_uid_destroy(struct buffer_reg_uid *regp,
899 struct consumer_output *consumer)
900{
901 struct consumer_socket *socket;
902
903 if (!regp) {
904 return;
905 }
906
d9bf3ca4 907 DBG3("Buffer registry per UID destroy with id: %" PRIu64 ", ABI: %u, uid: %d",
7972aab2
DG
908 regp->session_id, regp->bits_per_long, regp->uid);
909
910 if (!consumer) {
911 goto destroy;
912 }
913
36b588ed 914 rcu_read_lock();
7972aab2
DG
915 /* Get the right socket from the consumer object. */
916 socket = consumer_find_socket_by_bitness(regp->bits_per_long,
917 consumer);
918 if (!socket) {
36b588ed 919 goto unlock;
7972aab2
DG
920 }
921
922 switch (regp->domain) {
923 case LTTNG_DOMAIN_UST:
924 if (regp->registry->reg.ust->metadata_key) {
925 /* Return value does not matter. This call will print errors. */
926 (void) consumer_close_metadata(socket,
927 regp->registry->reg.ust->metadata_key);
928 }
929 break;
930 default:
931 assert(0);
36b588ed 932 rcu_read_unlock();
7972aab2
DG
933 return;
934 }
935
36b588ed
MD
936unlock:
937 rcu_read_unlock();
7972aab2
DG
938destroy:
939 call_rcu(&regp->node.head, rcu_free_buffer_reg_uid);
940}
941
942/*
943 * Remove buffer registry UID object from the global hash table. RCU read side
944 * lock MUST be acquired before calling this.
945 */
946void buffer_reg_pid_remove(struct buffer_reg_pid *regp)
947{
948 int ret;
949 struct lttng_ht_iter iter;
950
951 assert(regp);
952
953 iter.iter.node = &regp->node.node;
954 ret = lttng_ht_del(buffer_registry_pid, &iter);
955 assert(!ret);
956}
957
958/*
959 * Destroy buffer registry per PID. The pointer is NOT removed from the global
960 * hash table. Call buffer_reg_pid_remove() before that if the object was
961 * previously added to the global hash table.
962 */
963void buffer_reg_pid_destroy(struct buffer_reg_pid *regp)
964{
965 if (!regp) {
966 return;
967 }
968
d9bf3ca4
MD
969 DBG3("Buffer registry per PID destroy with id: %" PRIu64,
970 regp->session_id);
7972aab2
DG
971
972 /* This registry is only used by UST. */
973 call_rcu(&regp->node.head, rcu_free_buffer_reg_pid);
974}
975
976/*
977 * Destroy per PID and UID registry hash table.
36b588ed
MD
978 *
979 * Should *NOT* be called with RCU read-side lock held.
7972aab2
DG
980 */
981void buffer_reg_destroy_registries(void)
982{
983 DBG3("Buffer registry destroy all registry");
0b2dc8df
MD
984 ht_cleanup_push(buffer_registry_uid);
985 ht_cleanup_push(buffer_registry_pid);
7972aab2 986}
This page took 0.110748 seconds and 5 git commands to generate.