6a35284fe70eab9435052a86874537d2936b40f7
[lttng-tools.git] / src / bin / lttng-sessiond / buffer-registry.c
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 */
35 static 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 */
41 static 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 */
47 static 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;
67 no_match:
68 return 0;
69 }
70
71 /*
72 * Hash function for the per UID registry hash table. This XOR the triplet
73 * together.
74 */
75 static 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 */
89 void 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 */
106 int 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
147 error_session:
148 free(reg->registry);
149 error:
150 free(reg);
151 return ret;
152 }
153
154 /*
155 * Add a buffer registry per UID object to the global registry.
156 */
157 void 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 */
180 struct 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
205 end:
206 return reg;
207 }
208
209 /*
210 * Initialize global buffer per PID registry. Should only be called ONCE!.
211 */
212 void 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 */
227 int 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
264 error_session:
265 free(reg->registry);
266 error:
267 free(reg);
268 return ret;
269 }
270
271 /*
272 * Add a buffer registry per PID object to the global registry.
273 */
274 void 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 */
292 struct 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
308 end:
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 */
318 int 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 */
348 int 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 */
370 void 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 */
384 void 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 */
402 struct 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
428 end:
429 return chan;
430 }
431
432 /*
433 * Destroy a buffer registry stream with the given domain.
434 */
435 void 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 */
471 void 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 */
488 void buffer_reg_channel_destroy(struct buffer_reg_channel *regp,
489 enum lttng_domain_type domain)
490 {
491 if (!regp) {
492 return;
493 }
494
495 DBG3("Buffer registry channel destroy with key %" PRIu32, regp->key);
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
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);
515 }
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.
529 *
530 * Should *NOT* be called with RCU read-side lock held.
531 */
532 static void buffer_reg_session_destroy(struct buffer_reg_session *regp,
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 }
549 rcu_read_unlock();
550
551 lttng_ht_destroy(regp->channels);
552
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 /*
567 * Remove buffer registry UID object from the global hash table.
568 */
569 void buffer_reg_uid_remove(struct buffer_reg_uid *regp)
570 {
571 int ret;
572 struct lttng_ht_iter iter;
573
574 assert(regp);
575
576 rcu_read_lock();
577 iter.iter.node = &regp->node.node;
578 ret = lttng_ht_del(buffer_registry_uid, &iter);
579 assert(!ret);
580 rcu_read_unlock();
581 }
582
583 static 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
594 static 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 */
610 void 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
626 rcu_read_lock();
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) {
631 goto unlock;
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);
644 rcu_read_unlock();
645 return;
646 }
647
648 unlock:
649 rcu_read_unlock();
650 destroy:
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 */
658 void 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 */
675 void 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.
689 *
690 * Should *NOT* be called with RCU read-side lock held.
691 */
692 void 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.041689 seconds and 3 git commands to generate.