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