2 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
12 #include <urcu/compiler.h>
15 #include <common/error.h>
16 #include <common/hashtable/hashtable.h>
17 #include <common/index-allocator.h>
18 #include <common/kernel-ctl/kernel-ctl.h>
19 #include <common/shm.h>
20 #include <lttng/trigger/trigger-internal.h>
22 #include "event-notifier-error-accounting.h"
23 #include "lttng-ust-error.h"
26 struct index_ht_entry
{
27 struct lttng_ht_node_u64 node
;
28 uint64_t error_counter_index
;
29 struct rcu_head rcu_head
;
32 struct error_account_entry
{
33 struct lttng_ht_node_u64 node
;
34 struct rcu_head rcu_head
;
35 struct ustctl_daemon_counter
*daemon_counter
;
37 * Those `lttng_ust_object_data` are anonymous handles to the counters
39 * They are only used to be duplicated for each new applications of the
40 * user. To destroy them, call with the `sock` parameter set to -1.
41 * e.g. `ustctl_release_object(-1, data)`;
43 struct lttng_ust_object_data
*counter
;
44 struct lttng_ust_object_data
**cpu_counters
;
45 int nr_counter_cpu_fds
;
48 struct kernel_error_account_entry
{
49 int kernel_event_notifier_error_counter_fd
;
52 static struct kernel_error_account_entry kernel_error_accountant
= { 0 };
54 /* Hashtable mapping event notifier token to index_ht_entry */
55 static struct lttng_ht
*error_counter_indexes_ht
;
57 /* Hashtable mapping uid to error_account_entry */
58 static struct lttng_ht
*error_counter_uid_ht
;
60 static uint64_t error_counter_size
= 0;
61 struct lttng_index_allocator
*index_allocator
;
64 const char *error_accounting_status_str(
65 enum event_notifier_error_accounting_status status
)
68 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
:
70 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
:
72 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND
:
74 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
:
76 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE
:
77 return "NO_INDEX_AVAILABLE";
78 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
:
85 enum event_notifier_error_accounting_status
86 event_notifier_error_accounting_init(uint64_t nb_bucket
)
88 enum event_notifier_error_accounting_status status
;
90 index_allocator
= lttng_index_allocator_create(nb_bucket
);
91 if (!index_allocator
) {
92 ERR("Failed to allocate event notifier error counter index");
93 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
94 goto error_index_allocator
;
97 error_counter_indexes_ht
= lttng_ht_new(16, LTTNG_HT_TYPE_U64
);
98 error_counter_uid_ht
= lttng_ht_new(16, LTTNG_HT_TYPE_U64
);
99 error_counter_size
= nb_bucket
;
101 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
103 error_index_allocator
:
108 enum event_notifier_error_accounting_status
get_error_counter_index_for_token(
109 uint64_t tracer_token
, uint64_t *error_counter_index
)
111 struct lttng_ht_node_u64
*node
;
112 struct lttng_ht_iter iter
;
113 struct index_ht_entry
*index_entry
;;
114 enum event_notifier_error_accounting_status status
;
116 lttng_ht_lookup(error_counter_indexes_ht
, &tracer_token
, &iter
);
117 node
= lttng_ht_iter_get_node_u64(&iter
);
119 index_entry
= caa_container_of(node
, struct index_ht_entry
, node
);
120 *error_counter_index
= index_entry
->error_counter_index
;
121 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
123 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND
;
129 #ifdef HAVE_LIBLTTNG_UST_CTL
131 struct error_account_entry
*get_uid_accounting_entry(const struct ust_app
*app
)
133 struct error_account_entry
*entry
;
134 struct lttng_ht_node_u64
*node
;
135 struct lttng_ht_iter iter
;
136 uint64_t key
= app
->uid
;
138 lttng_ht_lookup(error_counter_uid_ht
, &key
, &iter
);
139 node
= lttng_ht_iter_get_node_u64(&iter
);
143 entry
= caa_container_of(node
, struct error_account_entry
, node
);
150 struct error_account_entry
*create_uid_accounting_entry(
151 const struct ust_app
*app
)
154 struct ustctl_counter_dimension dimension
[1] = {0};
155 struct ustctl_daemon_counter
*daemon_counter
;
156 struct lttng_ust_object_data
*counter
, **counter_cpus
;
157 int *counter_cpu_fds
;
158 struct error_account_entry
*entry
= NULL
;
160 entry
= zmalloc(sizeof(struct error_account_entry
));
162 PERROR("Allocating event notifier error acounting entry")
166 entry
->nr_counter_cpu_fds
= ustctl_get_nr_cpu_per_counter();
167 counter_cpu_fds
= zmalloc(entry
->nr_counter_cpu_fds
* sizeof(*counter_cpu_fds
));
168 if (!counter_cpu_fds
) {
170 goto error_counter_cpu_fds_alloc
;
173 counter_cpus
= zmalloc(entry
->nr_counter_cpu_fds
* sizeof(**counter_cpus
));
176 goto error_counter_cpus_alloc
;
179 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
180 counter_cpu_fds
[i
] = shm_create_anonymous("event-notifier-error-accounting");
181 //FIXME error handling
185 dimension
[0].size
= error_counter_size
;
186 dimension
[0].has_underflow
= false;
187 dimension
[0].has_overflow
= false;
189 daemon_counter
= ustctl_create_counter(1, dimension
, 0, -1,
190 entry
->nr_counter_cpu_fds
, counter_cpu_fds
,
191 USTCTL_COUNTER_BITNESS_32
,
192 USTCTL_COUNTER_ARITHMETIC_MODULAR
,
193 USTCTL_COUNTER_ALLOC_PER_CPU
,
195 assert(daemon_counter
);
197 ret
= ustctl_create_counter_data(daemon_counter
, &counter
);
200 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
201 ret
= ustctl_create_counter_cpu_data(daemon_counter
, i
,
206 entry
->daemon_counter
= daemon_counter
;
207 entry
->counter
= counter
;
208 entry
->cpu_counters
= counter_cpus
;
210 lttng_ht_node_init_u64(&entry
->node
, app
->uid
);
211 lttng_ht_add_unique_u64(error_counter_uid_ht
, &entry
->node
);
213 free(counter_cpu_fds
);
217 error_counter_cpus_alloc
:
218 free(counter_cpu_fds
);
219 error_counter_cpu_fds_alloc
:
228 enum event_notifier_error_accounting_status
send_counter_data_to_ust(
230 struct lttng_ust_object_data
*new_counter
)
233 enum event_notifier_error_accounting_status status
;
235 /* Attach counter to trigger group */
236 pthread_mutex_lock(&app
->sock_lock
);
237 ret
= ustctl_send_counter_data_to_ust(app
->sock
,
238 app
->event_notifier_group
.object
->handle
, new_counter
);
239 pthread_mutex_unlock(&app
->sock_lock
);
241 if (ret
!= -EPIPE
&& ret
!= -LTTNG_UST_ERR_EXITING
) {
242 ERR("Error ustctl send counter data to app pid: %d with ret %d",
244 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
246 DBG3("UST app send counter data to ust failed. Application is dead.");
247 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
;
252 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
258 enum event_notifier_error_accounting_status
send_counter_cpu_data_to_ust(
260 struct lttng_ust_object_data
*counter
,
261 struct lttng_ust_object_data
*counter_cpu
)
264 enum event_notifier_error_accounting_status status
;
266 pthread_mutex_lock(&app
->sock_lock
);
267 ret
= ustctl_send_counter_cpu_data_to_ust(app
->sock
,
268 counter
, counter_cpu
);
269 pthread_mutex_unlock(&app
->sock_lock
);
271 if (ret
!= -EPIPE
&& ret
!= -LTTNG_UST_ERR_EXITING
) {
272 ERR("Error ustctl send counter cpu data to app pid: %d with ret %d",
274 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
276 DBG3("UST app send counter cpu data to ust failed. Application is dead.");
277 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
;
282 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
287 enum event_notifier_error_accounting_status
event_notifier_error_accounting_register_app(
292 struct lttng_ust_object_data
*new_counter
;
293 struct error_account_entry
*entry
;
294 enum event_notifier_error_accounting_status status
;
297 * Check if we already have a error counter for the user id of this
298 * app. If not, create one.
301 entry
= get_uid_accounting_entry(app
);
303 entry
= create_uid_accounting_entry(app
);
306 /* Duplicate counter object data*/
307 ret
= ustctl_duplicate_ust_object_data(&new_counter
,
311 status
= send_counter_data_to_ust(app
, new_counter
);
312 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
313 ERR("Error sending counter data to UST tracer: status=%s",
314 error_accounting_status_str(status
));
319 app
->event_notifier_group
.counter
= new_counter
;
320 app
->event_notifier_group
.nr_counter_cpu
= entry
->nr_counter_cpu_fds
;
321 app
->event_notifier_group
.counter_cpu
=
322 zmalloc(entry
->nr_counter_cpu_fds
* sizeof(struct lttng_ust_object_data
));
324 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
325 struct lttng_ust_object_data
*new_counter_cpu
= NULL
;
327 ret
= ustctl_duplicate_ust_object_data(&new_counter_cpu
,
328 entry
->cpu_counters
[i
]);
331 status
= send_counter_cpu_data_to_ust(app
, new_counter
,
333 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
334 ERR("Error sending counter cpu data to UST tracer: status=%s",
335 error_accounting_status_str(status
));
338 app
->event_notifier_group
.counter_cpu
[i
] = new_counter_cpu
;
346 enum event_notifier_error_accounting_status
347 event_notifier_error_accounting_unregister_app(struct ust_app
*app
)
349 enum event_notifier_error_accounting_status status
;
350 struct error_account_entry
*entry
;
354 entry
= get_uid_accounting_entry(app
);
356 ERR("Event notitifier error accounting entry not found on app teardown");
357 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
361 for (i
= 0; i
< app
->event_notifier_group
.nr_counter_cpu
; i
++) {
362 ustctl_release_object(app
->sock
,
363 app
->event_notifier_group
.counter_cpu
[i
]);
364 free(app
->event_notifier_group
.counter_cpu
[i
]);
367 free(app
->event_notifier_group
.counter_cpu
);
369 ustctl_release_object(app
->sock
, app
->event_notifier_group
.counter
);
370 free(app
->event_notifier_group
.counter
);
372 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
379 enum event_notifier_error_accounting_status
380 event_notifier_error_accounting_ust_get_count(
381 const struct lttng_trigger
*trigger
, uint64_t *count
)
383 struct lttng_ht_iter iter
;
384 struct error_account_entry
*uid_entry
;
385 uint64_t error_counter_index
, global_sum
= 0;
386 enum event_notifier_error_accounting_status status
;
387 size_t dimension_indexes
[1];
390 * Go over all error counters (ignoring uid) as a trigger (and trigger
391 * errors) can be generated from any applications that this session
392 * daemon is managing.
397 status
= get_error_counter_index_for_token(
398 lttng_trigger_get_tracer_token(trigger
), &error_counter_index
);
399 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
400 ERR("Error getting index for token: status=%s",
401 error_accounting_status_str(status
));
405 dimension_indexes
[0] = error_counter_index
;
407 cds_lfht_for_each_entry(error_counter_uid_ht
->ht
, &iter
.iter
,
408 uid_entry
, node
.node
) {
410 int64_t local_value
= 0;
411 bool overflow
= 0, underflow
= 0;
412 ret
= ustctl_counter_aggregate(uid_entry
->daemon_counter
,
413 dimension_indexes
, &local_value
, &overflow
,
417 /* should always be zero or above. */
418 assert(local_value
>= 0);
419 global_sum
+= (uint64_t) local_value
;
425 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
433 enum event_notifier_error_accounting_status
event_notifier_error_accounting_ust_clear(
434 const struct lttng_trigger
*trigger
)
436 struct lttng_ht_iter iter
;
437 struct error_account_entry
*uid_entry
;
438 uint64_t error_counter_index
;
439 enum event_notifier_error_accounting_status status
;
440 size_t dimension_indexes
[1];
443 * Go over all error counters (ignoring uid) as a trigger (and trigger
444 * errors) can be generated from any applications that this session
445 * daemon is managing.
449 status
= get_error_counter_index_for_token(
450 lttng_trigger_get_tracer_token(trigger
),
451 &error_counter_index
);
452 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
453 ERR("Error getting index for token: status=%s",
454 error_accounting_status_str(status
));
458 dimension_indexes
[0] = error_counter_index
;
460 cds_lfht_for_each_entry(error_counter_uid_ht
->ht
, &iter
.iter
,
461 uid_entry
, node
.node
) {
463 ret
= ustctl_counter_clear(uid_entry
->daemon_counter
,
468 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
473 #endif /* HAVE_LIBLTTNG_UST_CTL */
476 enum event_notifier_error_accounting_status
event_notifier_error_accounting_kernel_clear(
477 const struct lttng_trigger
*trigger
)
480 uint64_t error_counter_index
;
481 enum event_notifier_error_accounting_status status
;
482 struct lttng_kernel_counter_clear counter_clear
= {0};
485 status
= get_error_counter_index_for_token(
486 lttng_trigger_get_tracer_token(trigger
),
487 &error_counter_index
);
488 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
489 ERR("Error getting index for token: status=%s",
490 error_accounting_status_str(status
));
494 counter_clear
.index
.number_dimensions
= 1;
495 counter_clear
.index
.dimension_indexes
[0] = error_counter_index
;
497 ret
= kernctl_counter_clear(
498 kernel_error_accountant
.kernel_event_notifier_error_counter_fd
,
501 ERR("Error clearing event notifier error counter");
502 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
506 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
512 enum event_notifier_error_accounting_status
event_notifier_error_accounting_register_kernel(
513 int kernel_event_notifier_group_fd
)
515 int local_fd
= -1, ret
;
516 enum event_notifier_error_accounting_status status
;
517 struct lttng_kernel_counter_conf error_counter_conf
= {0};
519 error_counter_conf
.arithmetic
= LTTNG_KERNEL_COUNTER_ARITHMETIC_MODULAR
;
520 error_counter_conf
.bitness
= LTTNG_KERNEL_COUNTER_BITNESS_64
;
521 error_counter_conf
.global_sum_step
= 0;
522 error_counter_conf
.number_dimensions
= 1;
523 error_counter_conf
.dimensions
[0].size
= error_counter_size
;
524 error_counter_conf
.dimensions
[0].has_underflow
= false;
525 error_counter_conf
.dimensions
[0].has_overflow
= false;
527 ret
= kernctl_create_event_notifier_group_error_counter(
528 kernel_event_notifier_group_fd
, &error_counter_conf
);
530 PERROR("ioctl kernel create event notifier group error counter");
531 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
538 /* Prevent fd duplication after execlp() */
539 ret
= fcntl(local_fd
, F_SETFD
, FD_CLOEXEC
);
541 PERROR("fcntl event notifier error counter fd");
542 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
546 DBG("Kernel event notifier group error counter (fd: %d)", local_fd
);
548 kernel_error_accountant
.kernel_event_notifier_error_counter_fd
= local_fd
;
549 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
556 enum event_notifier_error_accounting_status
create_error_counter_index_for_token(
557 uint64_t tracer_token
, uint64_t *error_counter_index
)
559 struct index_ht_entry
*index_entry
;;
560 enum lttng_index_allocator_status index_alloc_status
;
561 uint64_t local_error_counter_index
;
562 enum event_notifier_error_accounting_status status
;
564 /* Allocate a new index for that counter. */
565 index_alloc_status
= lttng_index_allocator_alloc(index_allocator
,
566 &local_error_counter_index
);
567 switch (index_alloc_status
) {
568 case LTTNG_INDEX_ALLOCATOR_STATUS_EMPTY
:
569 DBG("No more index available in the configured event notifier error counter:"
570 "number-of-indices=%"PRIu64
,
571 lttng_index_allocator_get_index_count(
573 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE
;
575 case LTTNG_INDEX_ALLOCATOR_STATUS_OK
:
578 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
582 index_entry
= zmalloc(sizeof(*index_entry
));
583 if (index_entry
== NULL
) {
584 PERROR("Event notifier error counter hashtable entry zmalloc");
585 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
589 index_entry
->error_counter_index
= local_error_counter_index
;
590 lttng_ht_node_init_u64(&index_entry
->node
, tracer_token
);
592 lttng_ht_add_unique_u64(error_counter_indexes_ht
, &index_entry
->node
);
594 *error_counter_index
= local_error_counter_index
;
595 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
600 enum event_notifier_error_accounting_status
event_notifier_error_accounting_register_event_notifier(
601 const struct lttng_trigger
*trigger
,
602 uint64_t *error_counter_index
)
604 enum event_notifier_error_accounting_status status
;
605 uint64_t local_error_counter_index
;
609 * Check if this event notifier already has a error counter index
612 status
= get_error_counter_index_for_token(
613 lttng_trigger_get_tracer_token(trigger
),
614 &local_error_counter_index
);
616 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND
:
617 DBG("Event notifier error counter index for this tracer token not found. Allocating a new one.");
618 status
= create_error_counter_index_for_token(
619 lttng_trigger_get_tracer_token(trigger
),
620 &local_error_counter_index
);
621 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
622 ERR("Error creating index for token: status=%s",
623 error_accounting_status_str(status
));
626 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
:
627 *error_counter_index
= local_error_counter_index
;
628 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
640 enum event_notifier_error_accounting_status
event_notifier_error_accounting_kernel_get_count(
641 const struct lttng_trigger
*trigger
, uint64_t *count
)
643 struct lttng_kernel_counter_aggregate counter_aggregate
= {0};
644 enum event_notifier_error_accounting_status status
;
645 uint64_t error_counter_index
;
649 status
= get_error_counter_index_for_token(
650 lttng_trigger_get_tracer_token(trigger
), &error_counter_index
);
651 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
652 ERR("Error getting index for token: status=%s",
653 error_accounting_status_str(status
));
657 counter_aggregate
.index
.number_dimensions
= 1;
658 counter_aggregate
.index
.dimension_indexes
[0] = error_counter_index
;
660 assert(kernel_error_accountant
.kernel_event_notifier_error_counter_fd
);
662 ret
= kernctl_counter_get_aggregate_value(
663 kernel_error_accountant
.kernel_event_notifier_error_counter_fd
,
666 ERR("Error getting event notifier error count.");
667 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
671 if (counter_aggregate
.value
.value
< 0) {
672 ERR("Event notifier error counter less than zero.");
673 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
677 /* Error count can't be negative. */
678 assert(counter_aggregate
.value
.value
>= 0);
679 *count
= (uint64_t) counter_aggregate
.value
.value
;
681 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
688 enum event_notifier_error_accounting_status
event_notifier_error_accounting_get_count(
689 const struct lttng_trigger
*trigger
, uint64_t *count
)
691 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
692 case LTTNG_DOMAIN_KERNEL
:
693 return event_notifier_error_accounting_kernel_get_count(trigger
, count
);
694 case LTTNG_DOMAIN_UST
:
695 #ifdef HAVE_LIBLTTNG_UST_CTL
696 return event_notifier_error_accounting_ust_get_count(trigger
, count
);
698 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
699 #endif /* HAVE_LIBLTTNG_UST_CTL */
706 enum event_notifier_error_accounting_status
event_notifier_error_accounting_clear(
707 const struct lttng_trigger
*trigger
)
709 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
710 case LTTNG_DOMAIN_KERNEL
:
711 return event_notifier_error_accounting_kernel_clear(trigger
);
712 case LTTNG_DOMAIN_UST
:
713 #ifdef HAVE_LIBLTTNG_UST_CTL
714 return event_notifier_error_accounting_ust_clear(trigger
);
716 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
717 #endif /* HAVE_LIBLTTNG_UST_CTL */
723 static void free_index_ht_entry(struct rcu_head
*head
)
725 struct index_ht_entry
*entry
= caa_container_of(head
,
726 struct index_ht_entry
, rcu_head
);
730 void event_notifier_error_accounting_unregister_event_notifier(
731 const struct lttng_trigger
*trigger
)
733 struct lttng_ht_iter iter
;
734 struct lttng_ht_node_u64
*node
;
735 struct index_ht_entry
*index_entry
;
736 enum event_notifier_error_accounting_status status
;
737 enum lttng_index_allocator_status index_alloc_status
;
738 uint64_t tracer_token
= lttng_trigger_get_tracer_token(trigger
);
740 status
= event_notifier_error_accounting_clear(trigger
);
741 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
742 ERR("Error clearing event notifier error counter index: status=%s",
743 error_accounting_status_str(status
));
747 lttng_ht_lookup(error_counter_indexes_ht
, &tracer_token
, &iter
);
748 node
= lttng_ht_iter_get_node_u64(&iter
);
750 index_entry
= caa_container_of(node
, struct index_ht_entry
, node
);
751 index_alloc_status
= lttng_index_allocator_release(
753 index_entry
->error_counter_index
);
754 if (index_alloc_status
!= LTTNG_INDEX_ALLOCATOR_STATUS_OK
) {
755 ERR("Error releasing event notifier error counter index: status=%s",
756 error_accounting_status_str(status
));
759 lttng_ht_del(error_counter_indexes_ht
, &iter
);
760 call_rcu(&index_entry
->rcu_head
, free_index_ht_entry
);
765 static void free_error_account_entry(struct rcu_head
*head
)
767 struct error_account_entry
*entry
= caa_container_of(head
,
768 struct error_account_entry
, rcu_head
);
769 #ifdef HAVE_LIBLTTNG_UST_CTL
771 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
772 ustctl_release_object(-1, entry
->cpu_counters
[i
]);
773 free(entry
->cpu_counters
[i
]);
776 free(entry
->cpu_counters
);
778 ustctl_release_object(-1, entry
->counter
);
779 free(entry
->counter
);
781 ustctl_destroy_counter(entry
->daemon_counter
);
782 #endif /* HAVE_LIBLTTNG_UST_CTL */
787 void event_notifier_error_accounting_fini(void)
789 struct lttng_ht_iter iter
;
790 struct index_ht_entry
*index_entry
;
791 struct error_account_entry
*uid_entry
;
793 lttng_index_allocator_destroy(index_allocator
);
795 if (kernel_error_accountant
.kernel_event_notifier_error_counter_fd
) {
796 int ret
= close(kernel_error_accountant
.kernel_event_notifier_error_counter_fd
);
798 PERROR("Closing kernel event notifier error counter");
804 cds_lfht_for_each_entry(error_counter_uid_ht
->ht
, &iter
.iter
,
805 uid_entry
, node
.node
) {
806 cds_lfht_del(error_counter_uid_ht
->ht
, &uid_entry
->node
.node
);
807 call_rcu(&uid_entry
->rcu_head
, free_error_account_entry
);
810 cds_lfht_for_each_entry(error_counter_indexes_ht
->ht
, &iter
.iter
,
811 index_entry
, node
.node
) {
812 cds_lfht_del(error_counter_indexes_ht
->ht
, &index_entry
->node
.node
);
813 call_rcu(&index_entry
->rcu_head
, free_index_ht_entry
);
818 lttng_ht_destroy(error_counter_uid_ht
);
819 lttng_ht_destroy(error_counter_indexes_ht
);