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