Fix ua_chan assert
[lttng-tools.git] / src / bin / lttng-sessiond / buffer-registry.c
CommitLineData
7972aab2
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 */
17
18#define _GNU_SOURCE
19#include <inttypes.h>
20
21#include <common/common.h>
22#include <common/hashtable/utils.h>
23
24#include "buffer-registry.h"
25#include "fd-limit.h"
26#include "ust-consumer.h"
27#include "ust-ctl.h"
28
29/*
30 * Set in main.c during initialization process of the daemon. This contains
31 * buffer_reg_uid object which are global registry for per UID buffer. Object
32 * are indexed by session id and matched by the triplet
33 * <session_id/bits_per_long/uid>.
34 */
35static struct lttng_ht *buffer_registry_uid;
36
37/*
38 * Initialized at the daemon start. This contains buffer_reg_pid object and
39 * indexed by session id.
40 */
41static struct lttng_ht *buffer_registry_pid;
42
43/*
44 * Match function for the per UID registry hash table. It matches a registry
45 * uid object with the triplet <session_id/abi/uid>.
46 */
47static int ht_match_reg_uid(struct cds_lfht_node *node, const void *_key)
48{
49 struct buffer_reg_uid *reg;
50 const struct buffer_reg_uid *key;
51
52 assert(node);
53 assert(_key);
54
55 reg = caa_container_of(node, struct buffer_reg_uid, node.node);
56 assert(reg);
57 key = _key;
58
59 if (key->session_id != reg->session_id ||
60 key->bits_per_long != reg->bits_per_long ||
61 key->uid != reg->uid) {
62 goto no_match;
63 }
64
65 /* Match */
66 return 1;
67no_match:
68 return 0;
69}
70
71/*
72 * Hash function for the per UID registry hash table. This XOR the triplet
73 * together.
74 */
75static unsigned long ht_hash_reg_uid(void *_key, unsigned long seed)
76{
77 uint64_t xored_key;
78 struct buffer_reg_uid *key = _key;
79
80 assert(key);
81
82 xored_key = (uint64_t)(key->session_id ^ key->bits_per_long ^ key->uid);
83 return hash_key_u64(&xored_key, seed);
84}
85
86/*
87 * Initialize global buffer per UID registry. Should only be called ONCE!.
88 */
89void buffer_reg_init_uid_registry(void)
90{
91 /* Should be called once. */
92 assert(!buffer_registry_uid);
93 buffer_registry_uid = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
94 assert(buffer_registry_uid);
95 buffer_registry_uid->match_fct = ht_match_reg_uid;
96 buffer_registry_uid->hash_fct = ht_hash_reg_uid;
97
98 DBG3("Global buffer per UID registry initialized");
99}
100
101/*
102 * Allocate and initialize object. Set regp with the object pointer.
103 *
104 * Return 0 on success else a negative value and regp is untouched.
105 */
106int buffer_reg_uid_create(int session_id, uint32_t bits_per_long, uid_t uid,
107 enum lttng_domain_type domain, struct buffer_reg_uid **regp)
108{
109 int ret = 0;
110 struct buffer_reg_uid *reg = NULL;
111
112 assert(regp);
113
114 reg = zmalloc(sizeof(*reg));
115 if (!reg) {
116 PERROR("zmalloc buffer registry uid");
117 ret = -ENOMEM;
118 goto error;
119 }
120
121 reg->registry = zmalloc(sizeof(struct buffer_reg_session));
122 if (!reg) {
123 PERROR("zmalloc buffer registry uid session");
124 ret = -ENOMEM;
125 goto error;
126 }
127
128 reg->session_id = session_id;
129 reg->bits_per_long = bits_per_long;
130 reg->uid = uid;
131 reg->domain = domain;
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 cds_lfht_node_init(&reg->node.node);
140 *regp = reg;
141
142 DBG3("Buffer registry per UID created id: %d, ABI: %u, uid: %d, domain: %d",
143 session_id, bits_per_long, uid, domain);
144
145 return 0;
146
147error_session:
148 free(reg->registry);
149error:
150 free(reg);
151 return ret;
152}
153
154/*
155 * Add a buffer registry per UID object to the global registry.
156 */
157void buffer_reg_uid_add(struct buffer_reg_uid *reg)
158{
159 struct cds_lfht_node *nodep;
160 struct lttng_ht *ht = buffer_registry_uid;
161
162 assert(reg);
163
164 DBG3("Buffer registry per UID adding to global registry with id: %d",
165 reg->session_id);
166
167 rcu_read_lock();
168 nodep = cds_lfht_add_unique(ht->ht, ht->hash_fct(reg, lttng_ht_seed),
169 ht->match_fct, reg, &reg->node.node);
170 assert(nodep == &reg->node.node);
171 rcu_read_unlock();
172}
173
174/*
175 * Find a buffer registry per UID object with given params. RCU read side lock
176 * MUST be acquired before calling this and hold on to protect the object.
177 *
178 * Return the object pointer or NULL on error.
179 */
180struct buffer_reg_uid *buffer_reg_uid_find(int session_id,
181 uint32_t bits_per_long, uid_t uid)
182{
183 struct lttng_ht_node_u64 *node;
184 struct lttng_ht_iter iter;
185 struct buffer_reg_uid *reg = NULL, key;
186 struct lttng_ht *ht = buffer_registry_uid;
187
188 /* Setup key we are looking for. */
189 key.session_id = session_id;
190 key.bits_per_long = bits_per_long;
191 key.uid = uid;
192
193 DBG3("Buffer registry per UID find id: %d, ABI: %u, uid: %d",
194 session_id, bits_per_long, uid);
195
196 /* Custom lookup function since it's a different key. */
197 cds_lfht_lookup(ht->ht, ht->hash_fct(&key, lttng_ht_seed), ht->match_fct,
198 &key, &iter.iter);
199 node = lttng_ht_iter_get_node_u64(&iter);
200 if (!node) {
201 goto end;
202 }
203 reg = caa_container_of(node, struct buffer_reg_uid, node);
204
205end:
206 return reg;
207}
208
209/*
210 * Initialize global buffer per PID registry. Should only be called ONCE!.
211 */
212void buffer_reg_init_pid_registry(void)
213{
214 /* Should be called once. */
215 assert(!buffer_registry_pid);
216 buffer_registry_pid = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
217 assert(buffer_registry_pid);
218
219 DBG3("Global buffer per PID registry initialized");
220}
221
222/*
223 * Allocate and initialize object. Set regp with the object pointer.
224 *
225 * Return 0 on success else a negative value and regp is untouched.
226 */
227int buffer_reg_pid_create(int session_id, struct buffer_reg_pid **regp)
228{
229 int ret = 0;
230 struct buffer_reg_pid *reg = NULL;
231
232 assert(regp);
233
234 reg = zmalloc(sizeof(*reg));
235 if (!reg) {
236 PERROR("zmalloc buffer registry pid");
237 ret = -ENOMEM;
238 goto error;
239 }
240
241 reg->registry = zmalloc(sizeof(struct buffer_reg_session));
242 if (!reg) {
243 PERROR("zmalloc buffer registry pid session");
244 ret = -ENOMEM;
245 goto error;
246 }
247
248 /* A cast is done here so we can use the session ID as a u64 ht node. */
249 reg->session_id = session_id;
250
251 reg->registry->channels = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
252 if (!reg->registry->channels) {
253 ret = -ENOMEM;
254 goto error_session;
255 }
256
257 lttng_ht_node_init_ulong(&reg->node, reg->session_id);
258 *regp = reg;
259
260 DBG3("Buffer registry per PID created with session id: %d", session_id);
261
262 return 0;
263
264error_session:
265 free(reg->registry);
266error:
267 free(reg);
268 return ret;
269}
270
271/*
272 * Add a buffer registry per PID object to the global registry.
273 */
274void buffer_reg_pid_add(struct buffer_reg_pid *reg)
275{
276 assert(reg);
277
278 DBG3("Buffer registry per PID adding to global registry with id: %d",
279 reg->session_id);
280
281 rcu_read_lock();
282 lttng_ht_add_unique_ulong(buffer_registry_pid, &reg->node);
283 rcu_read_unlock();
284}
285
286/*
287 * Find a buffer registry per PID object with given params. RCU read side lock
288 * MUST be acquired before calling this and hold on to protect the object.
289 *
290 * Return the object pointer or NULL on error.
291 */
292struct buffer_reg_pid *buffer_reg_pid_find(int session_id)
293{
294 struct lttng_ht_node_ulong *node;
295 struct lttng_ht_iter iter;
296 struct buffer_reg_pid *reg = NULL;
297 struct lttng_ht *ht = buffer_registry_pid;
298
299 DBG3("Buffer registry per PID find id: %d", session_id);
300
301 lttng_ht_lookup(ht, (void *)((unsigned long) session_id), &iter);
302 node = lttng_ht_iter_get_node_ulong(&iter);
303 if (!node) {
304 goto end;
305 }
306 reg = caa_container_of(node, struct buffer_reg_pid, node);
307
308end:
309 return reg;
310}
311
312/*
313 * Allocate and initialize a buffer registry channel with the given key. Set
314 * regp with the object pointer.
315 *
316 * Return 0 on success or else a negative value keeping regp untouched.
317 */
318int buffer_reg_channel_create(uint64_t key, struct buffer_reg_channel **regp)
319{
320 struct buffer_reg_channel *reg;
321
322 assert(regp);
323
324 DBG3("Buffer registry channel create with key: %" PRIu64, key);
325
326 reg = zmalloc(sizeof(*reg));
327 if (!reg) {
328 PERROR("zmalloc buffer registry channel");
329 return -ENOMEM;
330 }
331
332 reg->key = key;
333 CDS_INIT_LIST_HEAD(&reg->streams);
334 pthread_mutex_init(&reg->stream_list_lock, NULL);
335
336 lttng_ht_node_init_u64(&reg->node, key);
337 *regp = reg;
338
339 return 0;
340}
341
342/*
343 * Allocate and initialize a buffer registry stream. Set regp with the object
344 * pointer.
345 *
346 * Return 0 on success or else a negative value keeping regp untouched.
347 */
348int buffer_reg_stream_create(struct buffer_reg_stream **regp)
349{
350 struct buffer_reg_stream *reg;
351
352 assert(regp);
353
354 DBG3("Buffer registry creating stream");
355
356 reg = zmalloc(sizeof(*reg));
357 if (!reg) {
358 PERROR("zmalloc buffer registry stream");
359 return -ENOMEM;
360 }
361
362 *regp = reg;
363
364 return 0;
365}
366
367/*
368 * Add stream to the list in the channel.
369 */
370void buffer_reg_stream_add(struct buffer_reg_stream *stream,
371 struct buffer_reg_channel *channel)
372{
373 assert(stream);
374 assert(channel);
375
376 pthread_mutex_lock(&channel->stream_list_lock);
377 cds_list_add_tail(&stream->lnode, &channel->streams);
378 pthread_mutex_unlock(&channel->stream_list_lock);
379}
380
381/*
382 * Add a buffer registry channel object to the given session.
383 */
384void buffer_reg_channel_add(struct buffer_reg_session *session,
385 struct buffer_reg_channel *channel)
386{
387 assert(session);
388 assert(channel);
389
390 rcu_read_lock();
391 lttng_ht_add_unique_u64(session->channels, &channel->node);
392 rcu_read_unlock();
393}
394
395/*
396 * Find a buffer registry channel object with the given key. RCU read side lock
397 * MUST be acquired and hold on until the object reference is not needed
398 * anymore.
399 *
400 * Return the object pointer or NULL on error.
401 */
402struct buffer_reg_channel *buffer_reg_channel_find(uint64_t key,
403 struct buffer_reg_uid *reg)
404{
405 struct lttng_ht_node_u64 *node;
406 struct lttng_ht_iter iter;
407 struct buffer_reg_channel *chan = NULL;
408 struct lttng_ht *ht;
409
410 assert(reg);
411
412 switch (reg->domain) {
413 case LTTNG_DOMAIN_UST:
414 ht = reg->registry->channels;
415 break;
416 default:
417 assert(0);
418 goto end;
419 }
420
421 lttng_ht_lookup(ht, &key, &iter);
422 node = lttng_ht_iter_get_node_u64(&iter);
423 if (!node) {
424 goto end;
425 }
426 chan = caa_container_of(node, struct buffer_reg_channel, node);
427
428end:
429 return chan;
430}
431
432/*
433 * Destroy a buffer registry stream with the given domain.
434 */
435void buffer_reg_stream_destroy(struct buffer_reg_stream *regp,
436 enum lttng_domain_type domain)
437{
438 if (!regp) {
439 return;
440 }
441
442 DBG3("Buffer registry stream destroy with handle %d",
443 regp->obj.ust->handle);
444
445 switch (domain) {
446 case LTTNG_DOMAIN_UST:
447 {
448 int ret;
449
450 ret = ust_ctl_release_object(-1, regp->obj.ust);
451 if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
452 ERR("Buffer reg stream release obj handle %d failed with ret %d",
453 regp->obj.ust->handle, ret);
454 }
455 free(regp->obj.ust);
456 lttng_fd_put(LTTNG_FD_APPS, 2);
457 break;
458 }
459 default:
460 assert(0);
461 }
462
463 free(regp);
464 return;
465}
466
467/*
468 * Remove buffer registry channel object from the session hash table. RCU read
469 * side lock MUST be acquired before calling this.
470 */
471void buffer_reg_channel_remove(struct buffer_reg_session *session,
472 struct buffer_reg_channel *regp)
473{
474 int ret;
475 struct lttng_ht_iter iter;
476
477 assert(session);
478 assert(regp);
479
480 iter.iter.node = &regp->node.node;
481 ret = lttng_ht_del(session->channels, &iter);
482 assert(!ret);
483}
484
485/*
486 * Destroy a buffer registry channel with the given domain.
487 */
488void buffer_reg_channel_destroy(struct buffer_reg_channel *regp,
489 enum lttng_domain_type domain)
490{
491 if (!regp) {
492 return;
493 }
494
07d2ae95 495 DBG3("Buffer registry channel destroy with key %" PRIu32, regp->key);
7972aab2
DG
496
497 switch (domain) {
498 case LTTNG_DOMAIN_UST:
499 {
500 int ret;
501 struct buffer_reg_stream *sreg, *stmp;
502 /* Wipe stream */
503 cds_list_for_each_entry_safe(sreg, stmp, &regp->streams, lnode) {
504 cds_list_del(&sreg->lnode);
505 buffer_reg_stream_destroy(sreg, domain);
506 }
507
55d7e860
MD
508 if (regp->obj.ust) {
509 ret = ust_ctl_release_object(-1, regp->obj.ust);
510 if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
511 ERR("Buffer reg channel release obj handle %d failed with ret %d",
512 regp->obj.ust->handle, ret);
513 }
514 free(regp->obj.ust);
7972aab2 515 }
7972aab2
DG
516 lttng_fd_put(LTTNG_FD_APPS, 1);
517 break;
518 }
519 default:
520 assert(0);
521 }
522
523 free(regp);
524 return;
525}
526
527/*
528 * Destroy a buffer registry session with the given domain.
36b588ed
MD
529 *
530 * Should *NOT* be called with RCU read-side lock held.
7972aab2 531 */
36b588ed 532static void buffer_reg_session_destroy(struct buffer_reg_session *regp,
7972aab2
DG
533 enum lttng_domain_type domain)
534{
535 int ret;
536 struct lttng_ht_iter iter;
537 struct buffer_reg_channel *reg_chan;
538
539 DBG3("Buffer registry session destroy");
540
541 /* Destroy all channels. */
542 rcu_read_lock();
543 cds_lfht_for_each_entry(regp->channels->ht, &iter.iter, reg_chan,
544 node.node) {
545 ret = lttng_ht_del(regp->channels, &iter);
546 assert(!ret);
547 buffer_reg_channel_destroy(reg_chan, domain);
548 }
7972aab2
DG
549 rcu_read_unlock();
550
36b588ed
MD
551 lttng_ht_destroy(regp->channels);
552
7972aab2
DG
553 switch (domain) {
554 case LTTNG_DOMAIN_UST:
555 ust_registry_session_destroy(regp->reg.ust);
556 free(regp->reg.ust);
557 break;
558 default:
559 assert(0);
560 }
561
562 free(regp);
563 return;
564}
565
566/*
36b588ed 567 * Remove buffer registry UID object from the global hash table.
7972aab2
DG
568 */
569void buffer_reg_uid_remove(struct buffer_reg_uid *regp)
570{
571 int ret;
572 struct lttng_ht_iter iter;
573
574 assert(regp);
575
36b588ed 576 rcu_read_lock();
7972aab2
DG
577 iter.iter.node = &regp->node.node;
578 ret = lttng_ht_del(buffer_registry_uid, &iter);
579 assert(!ret);
36b588ed 580 rcu_read_unlock();
7972aab2
DG
581}
582
583static void rcu_free_buffer_reg_uid(struct rcu_head *head)
584{
585 struct lttng_ht_node_u64 *node =
586 caa_container_of(head, struct lttng_ht_node_u64, head);
587 struct buffer_reg_uid *reg =
588 caa_container_of(node, struct buffer_reg_uid, node);
589
590 buffer_reg_session_destroy(reg->registry, reg->domain);
591 free(reg);
592}
593
594static void rcu_free_buffer_reg_pid(struct rcu_head *head)
595{
596 struct lttng_ht_node_ulong *node =
597 caa_container_of(head, struct lttng_ht_node_ulong, head);
598 struct buffer_reg_pid *reg =
599 caa_container_of(node, struct buffer_reg_pid, node);
600
601 buffer_reg_session_destroy(reg->registry, LTTNG_DOMAIN_UST);
602 free(reg);
603}
604
605/*
606 * Destroy buffer registry per UID. The given pointer is NOT removed from any
607 * list or hash table. Use buffer_reg_pid_remove() before calling this function
608 * for the case that the object is in the global hash table.
609 */
610void buffer_reg_uid_destroy(struct buffer_reg_uid *regp,
611 struct consumer_output *consumer)
612{
613 struct consumer_socket *socket;
614
615 if (!regp) {
616 return;
617 }
618
619 DBG3("Buffer registry per UID destroy with id: %d, ABI: %u, uid: %d",
620 regp->session_id, regp->bits_per_long, regp->uid);
621
622 if (!consumer) {
623 goto destroy;
624 }
625
36b588ed 626 rcu_read_lock();
7972aab2
DG
627 /* Get the right socket from the consumer object. */
628 socket = consumer_find_socket_by_bitness(regp->bits_per_long,
629 consumer);
630 if (!socket) {
36b588ed 631 goto unlock;
7972aab2
DG
632 }
633
634 switch (regp->domain) {
635 case LTTNG_DOMAIN_UST:
636 if (regp->registry->reg.ust->metadata_key) {
637 /* Return value does not matter. This call will print errors. */
638 (void) consumer_close_metadata(socket,
639 regp->registry->reg.ust->metadata_key);
640 }
641 break;
642 default:
643 assert(0);
36b588ed 644 rcu_read_unlock();
7972aab2
DG
645 return;
646 }
647
36b588ed
MD
648unlock:
649 rcu_read_unlock();
7972aab2
DG
650destroy:
651 call_rcu(&regp->node.head, rcu_free_buffer_reg_uid);
652}
653
654/*
655 * Remove buffer registry UID object from the global hash table. RCU read side
656 * lock MUST be acquired before calling this.
657 */
658void buffer_reg_pid_remove(struct buffer_reg_pid *regp)
659{
660 int ret;
661 struct lttng_ht_iter iter;
662
663 assert(regp);
664
665 iter.iter.node = &regp->node.node;
666 ret = lttng_ht_del(buffer_registry_pid, &iter);
667 assert(!ret);
668}
669
670/*
671 * Destroy buffer registry per PID. The pointer is NOT removed from the global
672 * hash table. Call buffer_reg_pid_remove() before that if the object was
673 * previously added to the global hash table.
674 */
675void buffer_reg_pid_destroy(struct buffer_reg_pid *regp)
676{
677 if (!regp) {
678 return;
679 }
680
681 DBG3("Buffer registry per PID destroy with id: %d", regp->session_id);
682
683 /* This registry is only used by UST. */
684 call_rcu(&regp->node.head, rcu_free_buffer_reg_pid);
685}
686
687/*
688 * Destroy per PID and UID registry hash table.
36b588ed
MD
689 *
690 * Should *NOT* be called with RCU read-side lock held.
7972aab2
DG
691 */
692void buffer_reg_destroy_registries(void)
693{
694 DBG3("Buffer registry destroy all registry");
695 lttng_ht_destroy(buffer_registry_uid);
696 lttng_ht_destroy(buffer_registry_pid);
697}
This page took 0.048526 seconds and 4 git commands to generate.