SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / bin / lttng-sessiond / buffer-registry.c
1 /*
2 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
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"
17 #include "lttng-ust-ctl.h"
18 #include "lttng-ust-error.h"
19 #include "utils.h"
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 */
27 static 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 */
33 static 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 */
39 static 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;
59 no_match:
60 return 0;
61 }
62
63 /*
64 * Hash function for the per UID registry hash table. This XOR the triplet
65 * together.
66 */
67 static unsigned long ht_hash_reg_uid(const void *_key, unsigned long seed)
68 {
69 uint64_t xored_key;
70 const struct buffer_reg_uid *key = _key;
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 */
81 void 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 */
98 int buffer_reg_uid_create(uint64_t session_id, uint32_t bits_per_long, uid_t uid,
99 enum lttng_domain_type domain, struct buffer_reg_uid **regp,
100 const char *root_shm_path, const char *shm_path)
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));
115 if (!reg->registry) {
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;
125 if (shm_path[0]) {
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';
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 }
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
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
147 cds_lfht_node_init(&reg->node.node);
148 *regp = reg;
149
150 DBG3("Buffer registry per UID created id: %" PRIu64 ", ABI: %u, uid: %d, domain: %d",
151 session_id, bits_per_long, uid, domain);
152
153 return 0;
154
155 error_session:
156 free(reg->registry);
157 error:
158 free(reg);
159 return ret;
160 }
161
162 /*
163 * Add a buffer registry per UID object to the global registry.
164 */
165 void 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
172 DBG3("Buffer registry per UID adding to global registry with id: %" PRIu64 ,
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 */
188 struct buffer_reg_uid *buffer_reg_uid_find(uint64_t session_id,
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
201 DBG3("Buffer registry per UID find id: %" PRIu64 ", ABI: %u, uid: %d",
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
213 end:
214 return reg;
215 }
216
217 /*
218 * Initialize global buffer per PID registry. Should only be called ONCE!.
219 */
220 void buffer_reg_init_pid_registry(void)
221 {
222 /* Should be called once. */
223 assert(!buffer_registry_pid);
224 buffer_registry_pid = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
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 */
235 int buffer_reg_pid_create(uint64_t session_id, struct buffer_reg_pid **regp,
236 const char *root_shm_path, const char *shm_path)
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));
251 if (!reg->registry) {
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;
259 if (shm_path[0]) {
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';
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 }
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
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
280 lttng_ht_node_init_u64(&reg->node, reg->session_id);
281 *regp = reg;
282
283 DBG3("Buffer registry per PID created with session id: %" PRIu64,
284 session_id);
285
286 return 0;
287
288 error_session:
289 free(reg->registry);
290 error:
291 free(reg);
292 return ret;
293 }
294
295 /*
296 * Add a buffer registry per PID object to the global registry.
297 */
298 void buffer_reg_pid_add(struct buffer_reg_pid *reg)
299 {
300 assert(reg);
301
302 DBG3("Buffer registry per PID adding to global registry with id: %" PRIu64,
303 reg->session_id);
304
305 rcu_read_lock();
306 lttng_ht_add_unique_u64(buffer_registry_pid, &reg->node);
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 */
316 struct buffer_reg_pid *buffer_reg_pid_find(uint64_t session_id)
317 {
318 struct lttng_ht_node_u64 *node;
319 struct lttng_ht_iter iter;
320 struct buffer_reg_pid *reg = NULL;
321 struct lttng_ht *ht = buffer_registry_pid;
322
323 DBG3("Buffer registry per PID find id: %" PRIu64, session_id);
324
325 lttng_ht_lookup(ht, &session_id, &iter);
326 node = lttng_ht_iter_get_node_u64(&iter);
327 if (!node) {
328 goto end;
329 }
330 reg = caa_container_of(node, struct buffer_reg_pid, node);
331
332 end:
333 return reg;
334 }
335
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 */
341 int buffer_reg_uid_consumer_channel_key(
342 struct cds_list_head *buffer_reg_uid_list,
343 uint64_t chan_key, uint64_t *consumer_chan_key)
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
368 end:
369 rcu_read_unlock();
370 return ret;
371 }
372
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 */
379 int 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
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 */
409 int 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
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 */
439 int 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
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 */
464 int 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
483 /*
484 * Add stream to the list in the channel.
485 */
486 void 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);
494 channel->stream_count++;
495 pthread_mutex_unlock(&channel->stream_list_lock);
496 }
497
498 /*
499 * Add map_counter to the list in the map.
500 */
501 void 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
513 /*
514 * Add a buffer registry channel object to the given session.
515 */
516 void 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
527 /*
528 * Add a buffer registry map object to the given session.
529 */
530 void 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
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 */
548 struct 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
574 end:
575 return chan;
576 }
577
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 */
585 struct 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
611 end:
612 return map;
613 }
614
615 /*
616 * Destroy a buffer registry stream with the given domain.
617 */
618 void 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
633 ret = ust_app_release_object(NULL, regp->obj.ust);
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
650 /*
651 * Destroy a buffer registry map_counter with the given domain.
652 */
653 void 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
685 /*
686 * Remove buffer registry channel object from the session hash table. RCU read
687 * side lock MUST be acquired before calling this.
688 */
689 void 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
703 /*
704 * Remove buffer registry map object from the session hash table. RCU read
705 * side lock MUST be acquired before calling this.
706 */
707 void 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
721 /*
722 * Destroy a buffer registry channel with the given domain.
723 */
724 void buffer_reg_channel_destroy(struct buffer_reg_channel *regp,
725 enum lttng_domain_type domain)
726 {
727 if (!regp) {
728 return;
729 }
730
731 DBG3("Buffer registry channel destroy with key %" PRIu32, regp->key);
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);
741 regp->stream_count--;
742 buffer_reg_stream_destroy(sreg, domain);
743 }
744
745 if (regp->obj.ust) {
746 ret = ust_app_release_object(NULL, regp->obj.ust);
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);
752 }
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
764 /*
765 * Destroy a buffer registry map with the given domain.
766 */
767 void 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
807 /*
808 * Destroy a buffer registry session with the given domain.
809 *
810 * Should *NOT* be called with RCU read-side lock held.
811 */
812 static void buffer_reg_session_destroy(struct buffer_reg_session *regp,
813 enum lttng_domain_type domain)
814 {
815 int ret;
816 struct lttng_ht_iter iter;
817 struct buffer_reg_channel *reg_chan;
818 struct buffer_reg_map *reg_map;
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 }
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 }
836 rcu_read_unlock();
837
838 ht_cleanup_push(regp->channels);
839 ht_cleanup_push(regp->maps);
840
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 /*
855 * Remove buffer registry UID object from the global hash table.
856 */
857 void buffer_reg_uid_remove(struct buffer_reg_uid *regp)
858 {
859 int ret;
860 struct lttng_ht_iter iter;
861
862 assert(regp);
863
864 rcu_read_lock();
865 iter.iter.node = &regp->node.node;
866 ret = lttng_ht_del(buffer_registry_uid, &iter);
867 assert(!ret);
868 rcu_read_unlock();
869 }
870
871 static 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
882 static void rcu_free_buffer_reg_pid(struct rcu_head *head)
883 {
884 struct lttng_ht_node_u64 *node =
885 caa_container_of(head, struct lttng_ht_node_u64, head);
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 */
898 void 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
907 DBG3("Buffer registry per UID destroy with id: %" PRIu64 ", ABI: %u, uid: %d",
908 regp->session_id, regp->bits_per_long, regp->uid);
909
910 if (!consumer) {
911 goto destroy;
912 }
913
914 rcu_read_lock();
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) {
919 goto unlock;
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);
932 rcu_read_unlock();
933 return;
934 }
935
936 unlock:
937 rcu_read_unlock();
938 destroy:
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 */
946 void 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 */
963 void buffer_reg_pid_destroy(struct buffer_reg_pid *regp)
964 {
965 if (!regp) {
966 return;
967 }
968
969 DBG3("Buffer registry per PID destroy with id: %" PRIu64,
970 regp->session_id);
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.
978 *
979 * Should *NOT* be called with RCU read-side lock held.
980 */
981 void buffer_reg_destroy_registries(void)
982 {
983 DBG3("Buffer registry destroy all registry");
984 ht_cleanup_push(buffer_registry_uid);
985 ht_cleanup_push(buffer_registry_pid);
986 }
This page took 0.049988 seconds and 5 git commands to generate.