2 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
8 #include "event-notifier-error-accounting.hpp"
9 #include "lttng-ust-error.hpp"
10 #include "ust-app.hpp"
12 #include <common/error.hpp>
13 #include <common/hashtable/hashtable.hpp>
14 #include <common/index-allocator.hpp>
15 #include <common/kernel-ctl/kernel-ctl.hpp>
16 #include <common/shm.hpp>
17 #include <common/urcu.hpp>
19 #include <lttng/trigger/trigger-internal.hpp>
26 #include <urcu/compiler.h>
28 #define ERROR_COUNTER_INDEX_HT_INITIAL_SIZE 16
31 struct index_ht_entry
{
32 struct lttng_ht_node_u64 node
;
33 uint64_t error_counter_index
;
34 struct rcu_head rcu_head
;
37 struct ust_error_accounting_entry
{
40 struct lttng_ht_node_u64 node
;
41 struct rcu_head rcu_head
;
42 struct lttng_ust_ctl_daemon_counter
*daemon_counter
;
44 * Those `lttng_ust_abi_object_data` are anonymous handles to the
46 * They are only used to be duplicated for each new applications of the
47 * user. To destroy them, call with the `sock` parameter set to -1.
48 * e.g. `lttng_ust_ctl_release_object(-1, data)`;
50 struct lttng_ust_abi_object_data
*counter
;
51 struct lttng_ust_abi_object_data
**cpu_counters
;
52 int nr_counter_cpu_fds
;
55 struct kernel_error_accounting_entry
{
59 struct kernel_error_accounting_entry kernel_error_accounting_entry
;
61 /* Hashtable mapping uid to error_account_entry. */
62 struct lttng_ht
*error_counter_uid_ht
;
64 struct error_accounting_state
{
65 struct lttng_index_allocator
*index_allocator
;
66 /* Hashtable mapping event notifier token to index_ht_entry. */
67 struct lttng_ht
*indices_ht
;
68 uint64_t number_indices
;
71 struct error_accounting_state ust_state
;
72 struct error_accounting_state kernel_state
;
75 static inline void get_trigger_info_for_log(const struct lttng_trigger
*trigger
,
76 const char **trigger_name
,
77 uid_t
*trigger_owner_uid
)
79 enum lttng_trigger_status trigger_status
;
81 trigger_status
= lttng_trigger_get_name(trigger
, trigger_name
);
82 switch (trigger_status
) {
83 case LTTNG_TRIGGER_STATUS_OK
:
85 case LTTNG_TRIGGER_STATUS_UNSET
:
86 *trigger_name
= "(anonymous)";
92 trigger_status
= lttng_trigger_get_owner_uid(trigger
, trigger_owner_uid
);
93 LTTNG_ASSERT(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
96 static inline const char *
97 error_accounting_status_str(enum event_notifier_error_accounting_status status
)
100 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
:
102 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
:
104 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND
:
106 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
:
108 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE
:
109 return "NO_INDEX_AVAILABLE";
110 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
:
117 #ifdef HAVE_LIBLTTNG_UST_CTL
119 struct event_notifier_counter
{
120 pthread_mutex_t lock
;
124 struct event_notifier_counter the_event_notifier_counter
;
127 static void free_ust_error_accounting_entry(struct rcu_head
*head
)
130 struct ust_error_accounting_entry
*entry
=
131 lttng::utils::container_of(head
, &ust_error_accounting_entry::rcu_head
);
133 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
134 lttng_ust_ctl_release_object(-1, entry
->cpu_counters
[i
]);
135 free(entry
->cpu_counters
[i
]);
138 free(entry
->cpu_counters
);
140 lttng_ust_ctl_release_object(-1, entry
->counter
);
141 free(entry
->counter
);
143 lttng_ust_ctl_destroy_counter(entry
->daemon_counter
);
148 static bool ust_error_accounting_entry_get(struct ust_error_accounting_entry
*entry
)
150 return urcu_ref_get_unless_zero(&entry
->ref
);
153 static void ust_error_accounting_entry_release(struct urcu_ref
*entry_ref
)
155 struct ust_error_accounting_entry
*entry
=
156 lttng::utils::container_of(entry_ref
, &ust_error_accounting_entry::ref
);
158 const lttng::urcu::read_lock_guard read_lock
;
159 cds_lfht_del(error_counter_uid_ht
->ht
, &entry
->node
.node
);
160 call_rcu(&entry
->rcu_head
, free_ust_error_accounting_entry
);
163 static void ust_error_accounting_entry_put(struct ust_error_accounting_entry
*entry
)
169 urcu_ref_put(&entry
->ref
, ust_error_accounting_entry_release
);
173 * Put one reference to every UID entries.
175 static void put_ref_all_ust_error_accounting_entry()
177 ASSERT_LOCKED(the_event_notifier_counter
.lock
);
179 for (auto *uid_entry
:
180 lttng::urcu::lfht_iteration_adapter
<ust_error_accounting_entry
,
181 decltype(ust_error_accounting_entry::node
),
182 &ust_error_accounting_entry::node
>(
183 *error_counter_uid_ht
->ht
)) {
184 ust_error_accounting_entry_put(uid_entry
);
189 * Get one reference to every UID entries.
191 static void get_ref_all_ust_error_accounting_entry()
193 ASSERT_LOCKED(the_event_notifier_counter
.lock
);
195 for (auto *uid_entry
:
196 lttng::urcu::lfht_iteration_adapter
<ust_error_accounting_entry
,
197 decltype(ust_error_accounting_entry::node
),
198 &ust_error_accounting_entry::node
>(
199 *error_counter_uid_ht
->ht
)) {
200 ust_error_accounting_entry_get(uid_entry
);
204 #endif /* HAVE_LIBLTTNG_UST_CTL */
206 static enum event_notifier_error_accounting_status
207 init_error_accounting_state(struct error_accounting_state
*state
, uint64_t index_count
)
209 enum event_notifier_error_accounting_status status
;
213 state
->number_indices
= index_count
;
215 state
->index_allocator
= lttng_index_allocator_create(index_count
);
216 if (!state
->index_allocator
) {
217 ERR("Failed to allocate event notifier error counter index allocator");
218 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
222 state
->indices_ht
= lttng_ht_new(ERROR_COUNTER_INDEX_HT_INITIAL_SIZE
, LTTNG_HT_TYPE_U64
);
223 if (!state
->indices_ht
) {
224 ERR("Failed to allocate error counter indices hash table");
225 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
226 goto error_indices_ht
;
229 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
233 lttng_index_allocator_destroy(state
->index_allocator
);
234 state
->index_allocator
= nullptr;
239 static void fini_error_accounting_state(struct error_accounting_state
*state
)
244 * Will assert if some error counter indices were not released (an
247 lttng_ht_destroy(state
->indices_ht
);
248 lttng_index_allocator_destroy(state
->index_allocator
);
251 enum event_notifier_error_accounting_status
252 event_notifier_error_accounting_init(uint64_t buffer_size_kernel
, uint64_t buffer_size_ust
)
254 enum event_notifier_error_accounting_status status
;
256 status
= init_error_accounting_state(&kernel_state
, buffer_size_kernel
);
257 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
258 ERR("Failed to initialize kernel event notifier accounting state: status = %s",
259 error_accounting_status_str(status
));
263 status
= init_error_accounting_state(&ust_state
, buffer_size_ust
);
264 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
265 ERR("Failed to initialize UST event notifier accounting state: status = %s",
266 error_accounting_status_str(status
));
267 goto error_ust_state
;
270 error_counter_uid_ht
= lttng_ht_new(ERROR_COUNTER_INDEX_HT_INITIAL_SIZE
, LTTNG_HT_TYPE_U64
);
271 if (!error_counter_uid_ht
) {
272 ERR("Failed to allocate UID to error counter accountant hash table");
273 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
277 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
281 fini_error_accounting_state(&ust_state
);
283 fini_error_accounting_state(&kernel_state
);
289 * Return the error counteur index associated to this event notifier tracer
290 * token. Returns _STATUS_OK if found and _STATUS_NOT_FOUND otherwise.
292 static enum event_notifier_error_accounting_status
get_error_counter_index_for_token(
293 struct error_accounting_state
*state
, uint64_t tracer_token
, uint64_t *error_counter_index
)
295 struct lttng_ht_node_u64
*node
;
296 struct lttng_ht_iter iter
;
297 const struct index_ht_entry
*index_entry
;
298 enum event_notifier_error_accounting_status status
;
299 const lttng::urcu::read_lock_guard read_guard
;
301 lttng_ht_lookup(state
->indices_ht
, &tracer_token
, &iter
);
302 node
= lttng_ht_iter_get_node
<lttng_ht_node_u64
>(&iter
);
304 index_entry
= lttng::utils::container_of(node
, &index_ht_entry::node
);
305 *error_counter_index
= index_entry
->error_counter_index
;
306 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
308 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND
;
314 #ifdef HAVE_LIBLTTNG_UST_CTL
316 * Find the entry for this app's UID, the caller acquires a reference if the
319 static struct ust_error_accounting_entry
*ust_error_accounting_entry_find(struct lttng_ht
*uid_ht
,
320 const struct ust_app
*app
)
322 struct ust_error_accounting_entry
*entry
;
323 struct lttng_ht_node_u64
*node
;
324 struct lttng_ht_iter iter
;
325 uint64_t key
= app
->uid
;
327 lttng_ht_lookup(uid_ht
, &key
, &iter
);
328 node
= lttng_ht_iter_get_node
<lttng_ht_node_u64
>(&iter
);
329 if (node
== nullptr) {
334 entry
= lttng::utils::container_of(node
, &ust_error_accounting_entry::node
);
336 got_ref
= ust_error_accounting_entry_get(entry
);
346 * Create the entry for this app's UID, the caller acquires a reference to the
349 static struct ust_error_accounting_entry
*
350 ust_error_accounting_entry_create(const struct ust_app
*app
)
352 int i
, ret
, *cpu_counter_fds
= nullptr;
353 struct lttng_ust_ctl_daemon_counter
*daemon_counter
;
354 struct lttng_ust_abi_object_data
*counter
, **cpu_counters
;
355 struct ust_error_accounting_entry
*entry
= nullptr;
356 lttng_ust_ctl_counter_dimension dimension
= {};
358 dimension
.size
= ust_state
.number_indices
;
359 dimension
.has_underflow
= false;
360 dimension
.has_overflow
= false;
362 if (!ust_app_supports_counters(app
)) {
363 DBG("Refusing to create accounting entry for application (unsupported feature): app name = '%s', app ppid = %d",
369 entry
= zmalloc
<ust_error_accounting_entry
>();
371 PERROR("Failed to allocate event notifier error acounting entry")
375 urcu_ref_init(&entry
->ref
);
376 entry
->uid
= app
->uid
;
377 entry
->nr_counter_cpu_fds
= lttng_ust_ctl_get_nr_cpu_per_counter();
379 cpu_counter_fds
= calloc
<int>(entry
->nr_counter_cpu_fds
);
380 if (!cpu_counter_fds
) {
381 PERROR("Failed to allocate event notifier error counter file descriptors array: application uid = %d, application name = '%s', pid = %d, allocation size = %zu",
385 entry
->nr_counter_cpu_fds
* sizeof(*cpu_counter_fds
));
386 goto error_counter_cpu_fds_alloc
;
389 /* Initialize to an invalid fd value to closes fds in case of error. */
390 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
391 cpu_counter_fds
[i
] = -1;
394 cpu_counters
= calloc
<lttng_ust_abi_object_data
*>(entry
->nr_counter_cpu_fds
);
396 PERROR("Failed to allocate event notifier error counter lttng_ust_abi_object_data array: application uid = %d, application name = '%s', pid = %d, allocation size = %zu",
400 entry
->nr_counter_cpu_fds
* sizeof(struct lttng_ust_abi_object_data
*));
401 goto error_counter_cpus_alloc
;
404 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
405 cpu_counter_fds
[i
] = shm_create_anonymous("event-notifier-error-accounting");
406 if (cpu_counter_fds
[i
] == -1) {
407 ERR("Failed to create event notifier error accounting shared memory for application user: application uid = %d, pid = %d, application name = '%s'",
411 goto error_shm_alloc
;
416 * Ownership of the file descriptors transferred to the ustctl object.
418 daemon_counter
= lttng_ust_ctl_create_counter(1,
422 entry
->nr_counter_cpu_fds
,
424 LTTNG_UST_CTL_COUNTER_BITNESS_32
,
425 LTTNG_UST_CTL_COUNTER_ARITHMETIC_MODULAR
,
426 LTTNG_UST_CTL_COUNTER_ALLOC_PER_CPU
,
428 if (!daemon_counter
) {
429 goto error_create_daemon_counter
;
432 ret
= lttng_ust_ctl_create_counter_data(daemon_counter
, &counter
);
434 ERR("Failed to create userspace tracer counter data for application user: uid = %d, pid = %d, application name = '%s'",
438 goto error_create_counter_data
;
441 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
442 ret
= lttng_ust_ctl_create_counter_cpu_data(daemon_counter
, i
, &cpu_counters
[i
]);
444 ERR("Failed to create userspace tracer counter cpu data for application user: uid = %d, pid = %d, application name = '%s'",
448 goto error_create_counter_cpu_data
;
452 entry
->daemon_counter
= daemon_counter
;
453 entry
->counter
= counter
;
454 entry
->cpu_counters
= cpu_counters
;
456 lttng_ht_node_init_u64(&entry
->node
, entry
->uid
);
457 lttng_ht_add_unique_u64(error_counter_uid_ht
, &entry
->node
);
461 error_create_counter_cpu_data
:
462 /* Teardown any allocated cpu counters. */
463 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
464 if (!cpu_counters
[i
]) {
466 * Early-exit when error occurred before all cpu
467 * counters could be initialized.
472 lttng_ust_ctl_release_object(-1, cpu_counters
[i
]);
473 free(cpu_counters
[i
]);
476 lttng_ust_ctl_release_object(-1, entry
->counter
);
477 free(entry
->counter
);
478 error_create_counter_data
:
479 lttng_ust_ctl_destroy_counter(daemon_counter
);
480 error_create_daemon_counter
:
482 /* Error occurred before per-cpu SHMs were handed-off to ustctl. */
483 if (cpu_counter_fds
) {
484 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
485 if (cpu_counter_fds
[i
] < 0) {
487 * Early-exit when error occurred before all cpu
488 * counter shm fds could be initialized.
493 ret
= close(cpu_counter_fds
[i
]);
495 PERROR("Failed to close error counter per-CPU shm file descriptor: fd = %d",
502 error_counter_cpus_alloc
:
503 error_counter_cpu_fds_alloc
:
508 free(cpu_counter_fds
);
512 static enum event_notifier_error_accounting_status
513 send_counter_data_to_ust(struct ust_app
*app
, struct lttng_ust_abi_object_data
*new_counter
)
516 enum event_notifier_error_accounting_status status
;
518 /* Attach counter to trigger group. */
519 pthread_mutex_lock(&app
->sock_lock
);
520 ret
= lttng_ust_ctl_send_counter_data_to_ust(
521 app
->sock
, app
->event_notifier_group
.object
->handle
, new_counter
);
522 pthread_mutex_unlock(&app
->sock_lock
);
524 if (ret
!= -EPIPE
&& ret
!= -LTTNG_UST_ERR_EXITING
) {
525 ERR("Failed to send counter data to application: application name = '%s', pid = %d, ret = %d",
529 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
531 DBG3("Failed to send counter data to application (application is dead): application name = '%s', pid = %d, ret = %d",
535 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
;
541 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
546 static enum event_notifier_error_accounting_status
547 send_counter_cpu_data_to_ust(struct ust_app
*app
,
548 struct lttng_ust_abi_object_data
*counter
,
549 struct lttng_ust_abi_object_data
*counter_cpu
)
552 enum event_notifier_error_accounting_status status
;
554 pthread_mutex_lock(&app
->sock_lock
);
555 ret
= lttng_ust_ctl_send_counter_cpu_data_to_ust(app
->sock
, counter
, counter_cpu
);
556 pthread_mutex_unlock(&app
->sock_lock
);
558 if (ret
!= -EPIPE
&& ret
!= -LTTNG_UST_ERR_EXITING
) {
559 ERR("Failed to send counter CPU data to application: application name = '%s', pid = %d, ret = %d",
563 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
565 DBG3("Failed to send counter CPU data to application: application name = '%s', pid = %d, ret = %d",
569 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
;
575 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
580 enum event_notifier_error_accounting_status
581 event_notifier_error_accounting_register_app(struct ust_app
*app
)
585 struct lttng_ust_abi_object_data
*new_counter
;
586 struct ust_error_accounting_entry
*entry
;
587 enum event_notifier_error_accounting_status status
;
588 struct lttng_ust_abi_object_data
**cpu_counters
;
589 const lttng::urcu::read_lock_guard read_lock
;
591 if (!ust_app_supports_counters(app
)) {
592 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_UNSUPPORTED
;
597 * Check if we already have a error counter for the user id of this
598 * app. If not, create one.
600 entry
= ust_error_accounting_entry_find(error_counter_uid_ht
, app
);
601 if (entry
== nullptr) {
603 * Take the event notifier counter lock before creating the new
604 * entry to ensure that no event notifier is registered between
605 * the the entry creation and event notifier count check.
607 pthread_mutex_lock(&the_event_notifier_counter
.lock
);
609 entry
= ust_error_accounting_entry_create(app
);
611 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
612 pthread_mutex_unlock(&the_event_notifier_counter
.lock
);
613 goto error_creating_entry
;
617 * We just created a new UID entry, If there are event
618 * notifiers already registered, take one reference on their
621 if (the_event_notifier_counter
.count
> 0) {
622 ust_error_accounting_entry_get(entry
);
625 pthread_mutex_unlock(&the_event_notifier_counter
.lock
);
628 /* Duplicate counter object data. */
629 ret
= lttng_ust_ctl_duplicate_ust_object_data(&new_counter
, entry
->counter
);
631 ERR("Failed to duplicate event notifier error accounting counter for application user: application uid = %d, pid = %d, application name = '%s'",
635 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
636 goto error_duplicate_counter
;
639 status
= send_counter_data_to_ust(app
, new_counter
);
640 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
641 if (status
== EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
) {
642 goto error_send_counter_data
;
645 ERR("Failed to send counter data to application tracer: status = %s, application uid = %d, pid = %d, application name = '%s'",
646 error_accounting_status_str(status
),
650 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
651 goto error_send_counter_data
;
654 cpu_counters
= calloc
<lttng_ust_abi_object_data
*>(entry
->nr_counter_cpu_fds
);
656 PERROR("Failed to allocate event notifier error counter lttng_ust_abi_object_data array: application uid = %d, application name = '%s', pid = %d, allocation size = %zu",
660 entry
->nr_counter_cpu_fds
* sizeof(**cpu_counters
));
661 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
662 goto error_allocate_cpu_counters
;
665 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
666 struct lttng_ust_abi_object_data
*new_counter_cpu
= nullptr;
668 ret
= lttng_ust_ctl_duplicate_ust_object_data(&new_counter_cpu
,
669 entry
->cpu_counters
[i
]);
671 ERR("Failed to duplicate userspace tracer counter cpu data for application user: uid = %d, pid = %d, application name = '%s'",
675 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
676 goto error_duplicate_cpu_counter
;
679 cpu_counters
[i
] = new_counter_cpu
;
681 status
= send_counter_cpu_data_to_ust(app
, new_counter
, new_counter_cpu
);
682 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
683 if (status
== EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
) {
684 goto error_send_cpu_counter_data
;
687 ERR("Failed to send counter cpu data to application tracer: status = %s, application uid = %d, pid = %d, application name = '%s'",
688 error_accounting_status_str(status
),
692 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
693 goto error_send_cpu_counter_data
;
697 app
->event_notifier_group
.counter
= new_counter
;
698 new_counter
= nullptr;
699 app
->event_notifier_group
.nr_counter_cpu
= entry
->nr_counter_cpu_fds
;
700 app
->event_notifier_group
.counter_cpu
= cpu_counters
;
701 cpu_counters
= nullptr;
704 error_send_cpu_counter_data
:
705 error_duplicate_cpu_counter
:
706 /* Teardown any duplicated cpu counters. */
707 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
708 if (!cpu_counters
[i
]) {
710 * Early-exit when error occurred before all cpu
711 * counters could be initialized.
716 lttng_ust_ctl_release_object(-1, cpu_counters
[i
]);
717 free(cpu_counters
[i
]);
722 error_allocate_cpu_counters
:
723 error_send_counter_data
:
724 lttng_ust_ctl_release_object(-1, new_counter
);
726 error_duplicate_counter
:
727 ust_error_accounting_entry_put(entry
);
728 error_creating_entry
:
729 app
->event_notifier_group
.counter
= nullptr;
734 enum event_notifier_error_accounting_status
735 event_notifier_error_accounting_unregister_app(struct ust_app
*app
)
737 enum event_notifier_error_accounting_status status
;
738 struct ust_error_accounting_entry
*entry
;
741 const lttng::urcu::read_lock_guard read_lock
;
743 /* If an error occurred during app registration no entry was created. */
744 if (!app
->event_notifier_group
.counter
) {
745 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
749 entry
= ust_error_accounting_entry_find(error_counter_uid_ht
, app
);
750 if (entry
== nullptr) {
751 ERR("Failed to find event notitifier error accounting entry on application teardown: pid = %d, application name = '%s'",
754 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
758 * Put the entry twice as we acquired a reference from the
759 * `ust_error_accounting_entry_find()` above.
761 ust_error_accounting_entry_put(entry
);
762 ust_error_accounting_entry_put(entry
);
765 for (i
= 0; i
< app
->event_notifier_group
.nr_counter_cpu
; i
++) {
766 lttng_ust_ctl_release_object(app
->sock
, app
->event_notifier_group
.counter_cpu
[i
]);
767 free(app
->event_notifier_group
.counter_cpu
[i
]);
770 free(app
->event_notifier_group
.counter_cpu
);
772 lttng_ust_ctl_release_object(app
->sock
, app
->event_notifier_group
.counter
);
773 free(app
->event_notifier_group
.counter
);
775 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
780 static enum event_notifier_error_accounting_status
781 event_notifier_error_accounting_ust_get_count(const struct lttng_trigger
*trigger
, uint64_t *count
)
783 uint64_t error_counter_index
, global_sum
= 0;
784 enum event_notifier_error_accounting_status status
;
785 size_t dimension_indexes
[1];
786 const uint64_t tracer_token
= lttng_trigger_get_tracer_token(trigger
);
787 uid_t trigger_owner_uid
;
788 const char *trigger_name
;
790 const lttng::urcu::read_lock_guard read_lock
;
792 get_trigger_info_for_log(trigger
, &trigger_name
, &trigger_owner_uid
);
794 status
= get_error_counter_index_for_token(&ust_state
, tracer_token
, &error_counter_index
);
795 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
796 ERR("Failed to retrieve index for tracer token: token = %" PRIu64
797 ", trigger name = '%s', trigger owner uid = %d, status = %s",
800 (int) trigger_owner_uid
,
801 error_accounting_status_str(status
));
805 dimension_indexes
[0] = error_counter_index
;
808 * Iterate over all the UID entries.
809 * We aggregate the value of all uid entries regardless of if the uid
810 * matches the trigger's uid because a user that is allowed to register
811 * a trigger to a given sessiond is also allowed to create an event
812 * notifier on all apps that this sessiond is aware of.
814 for (auto *uid_entry
:
815 lttng::urcu::lfht_iteration_adapter
<ust_error_accounting_entry
,
816 decltype(ust_error_accounting_entry::node
),
817 &ust_error_accounting_entry::node
>(
818 *error_counter_uid_ht
->ht
)) {
820 int64_t local_value
= 0;
821 bool overflow
= false, underflow
= false;
823 ret
= lttng_ust_ctl_counter_aggregate(uid_entry
->daemon_counter
,
828 if (ret
|| local_value
< 0) {
830 ERR("Failed to aggregate event notifier error counter values of trigger: trigger name = '%s', trigger owner uid = %d",
832 (int) trigger_owner_uid
);
833 } else if (local_value
< 0) {
834 ERR("Negative event notifier error counter value encountered during aggregation: trigger name = '%s', trigger owner uid = %d, value = %" PRId64
,
836 (int) trigger_owner_uid
,
842 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
846 /* Cast is safe as negative values are checked-for above. */
847 global_sum
+= (uint64_t) local_value
;
851 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
857 static enum event_notifier_error_accounting_status
858 event_notifier_error_accounting_ust_clear(const struct lttng_trigger
*trigger
)
860 uint64_t error_counter_index
;
861 enum event_notifier_error_accounting_status status
;
862 size_t dimension_index
;
863 const uint64_t tracer_token
= lttng_trigger_get_tracer_token(trigger
);
865 const lttng::urcu::read_lock_guard read_lock
;
867 status
= get_error_counter_index_for_token(&ust_state
, tracer_token
, &error_counter_index
);
868 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
869 uid_t trigger_owner_uid
;
870 const char *trigger_name
;
872 get_trigger_info_for_log(trigger
, &trigger_name
, &trigger_owner_uid
);
874 ERR("Failed to retrieve index for tracer token: token = %" PRIu64
875 ", trigger name = '%s', trigger owner uid = %d, status = %s",
878 (int) trigger_owner_uid
,
879 error_accounting_status_str(status
));
883 dimension_index
= error_counter_index
;
886 * Go over all error counters (ignoring uid) as a trigger (and trigger
887 * errors) can be generated from any applications that this session
888 * daemon is managing.
890 for (auto *uid_entry
:
891 lttng::urcu::lfht_iteration_adapter
<ust_error_accounting_entry
,
892 decltype(ust_error_accounting_entry::node
),
893 &ust_error_accounting_entry::node
>(
894 *error_counter_uid_ht
->ht
)) {
896 lttng_ust_ctl_counter_clear(uid_entry
->daemon_counter
, &dimension_index
);
899 uid_t trigger_owner_uid
;
900 const char *trigger_name
;
902 get_trigger_info_for_log(trigger
, &trigger_name
, &trigger_owner_uid
);
903 ERR("Failed to clear event notifier counter value for trigger: counter uid = %d, trigger name = '%s', trigger owner uid = %d",
904 (int) uid_entry
->node
.key
,
906 (int) trigger_owner_uid
);
907 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
912 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
916 #endif /* HAVE_LIBLTTNG_UST_CTL */
918 static enum event_notifier_error_accounting_status
919 event_notifier_error_accounting_kernel_clear(const struct lttng_trigger
*trigger
)
922 uint64_t error_counter_index
;
923 enum event_notifier_error_accounting_status status
;
924 struct lttng_kernel_abi_counter_clear counter_clear
= {};
926 status
= get_error_counter_index_for_token(
927 &kernel_state
, lttng_trigger_get_tracer_token(trigger
), &error_counter_index
);
928 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
929 uid_t trigger_owner_uid
;
930 const char *trigger_name
;
932 get_trigger_info_for_log(trigger
, &trigger_name
, &trigger_owner_uid
);
934 ERR("Failed to get event notifier error counter index: trigger owner uid = %d, trigger name = '%s', status = '%s'",
937 error_accounting_status_str(status
));
941 counter_clear
.index
.number_dimensions
= 1;
942 counter_clear
.index
.dimension_indexes
[0] = error_counter_index
;
944 ret
= kernctl_counter_clear(kernel_error_accounting_entry
.error_counter_fd
, &counter_clear
);
946 uid_t trigger_owner_uid
;
947 const char *trigger_name
;
949 get_trigger_info_for_log(trigger
, &trigger_name
, &trigger_owner_uid
);
951 ERR("Failed to clear kernel event notifier error counter: trigger owner uid = %d, trigger name = '%s'",
954 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
958 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
963 enum event_notifier_error_accounting_status
964 event_notifier_error_accounting_register_kernel(int kernel_event_notifier_group_fd
)
966 int error_counter_fd
= -1, ret
;
967 enum event_notifier_error_accounting_status status
;
968 lttng_kernel_abi_counter_conf error_counter_conf
= {
969 .arithmetic
= LTTNG_KERNEL_ABI_COUNTER_ARITHMETIC_MODULAR
,
970 .bitness
= sizeof(void *) == sizeof(uint32_t) ?
971 LTTNG_KERNEL_ABI_COUNTER_BITNESS_32
:
972 LTTNG_KERNEL_ABI_COUNTER_BITNESS_64
,
973 .number_dimensions
= 1,
974 .global_sum_step
= 0,
979 error_counter_conf
.dimensions
[0].size
= kernel_state
.number_indices
;
980 error_counter_conf
.dimensions
[0].has_underflow
= false;
981 error_counter_conf
.dimensions
[0].has_overflow
= false;
983 ret
= kernctl_create_event_notifier_group_error_counter(kernel_event_notifier_group_fd
,
984 &error_counter_conf
);
986 PERROR("Failed to create event notifier group error counter through kernel ioctl: kernel_event_notifier_group_fd = %d",
987 kernel_event_notifier_group_fd
);
988 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
992 error_counter_fd
= ret
;
994 /* Prevent fd duplication after execlp(). */
995 ret
= fcntl(error_counter_fd
, F_SETFD
, FD_CLOEXEC
);
997 PERROR("Failed to set FD_CLOEXEC flag on event notifier error counter file descriptor: error_counter_fd = %d",
999 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
1003 DBG("Created kernel event notifier group error counter: fd = %d", error_counter_fd
);
1005 kernel_error_accounting_entry
.error_counter_fd
= error_counter_fd
;
1006 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1012 static enum event_notifier_error_accounting_status
create_error_counter_index_for_token(
1013 struct error_accounting_state
*state
, uint64_t tracer_token
, uint64_t *error_counter_index
)
1015 struct index_ht_entry
*index_entry
;
1016 enum lttng_index_allocator_status index_alloc_status
;
1017 uint64_t local_error_counter_index
;
1018 enum event_notifier_error_accounting_status status
;
1020 LTTNG_ASSERT(state
);
1022 /* Allocate a new index for that counter. */
1023 index_alloc_status
=
1024 lttng_index_allocator_alloc(state
->index_allocator
, &local_error_counter_index
);
1025 switch (index_alloc_status
) {
1026 case LTTNG_INDEX_ALLOCATOR_STATUS_EMPTY
:
1027 DBG("No indices left in the configured event notifier error counter: "
1028 "number-of-indices = %" PRIu64
,
1029 lttng_index_allocator_get_index_count(state
->index_allocator
));
1030 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE
;
1032 case LTTNG_INDEX_ALLOCATOR_STATUS_OK
:
1035 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
1039 index_entry
= zmalloc
<index_ht_entry
>();
1040 if (index_entry
== nullptr) {
1041 PERROR("Failed to allocate event notifier error counter hash table entry");
1042 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
1046 index_entry
->error_counter_index
= local_error_counter_index
;
1047 lttng_ht_node_init_u64(&index_entry
->node
, tracer_token
);
1048 lttng_ht_add_unique_u64(state
->indices_ht
, &index_entry
->node
);
1050 DBG("Allocated error counter index for tracer token: tracer token = %" PRIu64
1051 ", index = %" PRIu64
,
1053 local_error_counter_index
);
1054 *error_counter_index
= local_error_counter_index
;
1055 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1060 enum event_notifier_error_accounting_status
1061 event_notifier_error_accounting_register_event_notifier(const struct lttng_trigger
*trigger
,
1062 uint64_t *error_counter_index
)
1064 enum event_notifier_error_accounting_status status
;
1065 uint64_t local_error_counter_index
;
1066 struct error_accounting_state
*state
;
1068 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1069 case LTTNG_DOMAIN_KERNEL
:
1070 state
= &kernel_state
;
1072 case LTTNG_DOMAIN_UST
:
1073 case LTTNG_DOMAIN_PYTHON
:
1074 case LTTNG_DOMAIN_JUL
:
1075 case LTTNG_DOMAIN_LOG4J
:
1076 case LTTNG_DOMAIN_LOG4J2
:
1084 * Check if this event notifier already has a error counter index
1087 status
= get_error_counter_index_for_token(
1088 state
, lttng_trigger_get_tracer_token(trigger
), &local_error_counter_index
);
1090 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND
:
1092 uid_t trigger_owner_uid
;
1093 const char *trigger_name
;
1095 get_trigger_info_for_log(trigger
, &trigger_name
, &trigger_owner_uid
);
1097 DBG("Event notifier error counter index not found for tracer token (allocating a new one): trigger name = '%s', trigger owner uid = %d, tracer token = %" PRIu64
,
1100 lttng_trigger_get_tracer_token(trigger
));
1102 status
= create_error_counter_index_for_token(
1103 state
, lttng_trigger_get_tracer_token(trigger
), &local_error_counter_index
);
1104 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
1105 ERR("Error creating index for token: status = %s, trigger name = '%s', trigger owner uid = %d",
1106 error_accounting_status_str(status
),
1113 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
:
1114 *error_counter_index
= local_error_counter_index
;
1115 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1121 #ifdef HAVE_LIBLTTNG_UST_CTL
1122 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1123 case LTTNG_DOMAIN_UST
:
1124 case LTTNG_DOMAIN_PYTHON
:
1125 case LTTNG_DOMAIN_JUL
:
1126 case LTTNG_DOMAIN_LOG4J
:
1127 case LTTNG_DOMAIN_LOG4J2
:
1128 pthread_mutex_lock(&the_event_notifier_counter
.lock
);
1129 the_event_notifier_counter
.count
++;
1130 if (the_event_notifier_counter
.count
== 1) {
1132 * On the first event notifier, we get a reference to
1133 * every existing UID entries. This ensures that the
1134 * entries are kept around if there are still
1135 * registered event notifiers but no apps.
1137 get_ref_all_ust_error_accounting_entry();
1139 pthread_mutex_unlock(&the_event_notifier_counter
.lock
);
1144 #endif /* HAVE_LIBLTTNG_UST_CTL */
1150 static enum event_notifier_error_accounting_status
1151 event_notifier_error_accounting_kernel_get_count(const struct lttng_trigger
*trigger
,
1154 struct lttng_kernel_abi_counter_aggregate counter_aggregate
= {};
1155 enum event_notifier_error_accounting_status status
;
1156 uint64_t error_counter_index
;
1159 status
= get_error_counter_index_for_token(
1160 &kernel_state
, lttng_trigger_get_tracer_token(trigger
), &error_counter_index
);
1161 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
1162 ERR("Error getting index for token: status=%s",
1163 error_accounting_status_str(status
));
1167 counter_aggregate
.index
.number_dimensions
= 1;
1168 counter_aggregate
.index
.dimension_indexes
[0] = error_counter_index
;
1170 LTTNG_ASSERT(kernel_error_accounting_entry
.error_counter_fd
);
1172 ret
= kernctl_counter_get_aggregate_value(kernel_error_accounting_entry
.error_counter_fd
,
1173 &counter_aggregate
);
1174 if (ret
|| counter_aggregate
.value
.value
< 0) {
1175 uid_t trigger_owner_uid
;
1176 const char *trigger_name
;
1178 get_trigger_info_for_log(trigger
, &trigger_name
, &trigger_owner_uid
);
1180 if (counter_aggregate
.value
.value
< 0) {
1181 ERR("Invalid negative event notifier error counter value: trigger owner = %d, trigger name = '%s', value = %" PRId64
,
1184 counter_aggregate
.value
.value
);
1186 ERR("Failed to getting event notifier error count: trigger owner = %d, trigger name = '%s', ret = %d",
1192 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
1196 /* Error count can't be negative. */
1197 LTTNG_ASSERT(counter_aggregate
.value
.value
>= 0);
1198 *count
= (uint64_t) counter_aggregate
.value
.value
;
1200 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1206 enum event_notifier_error_accounting_status
1207 event_notifier_error_accounting_get_count(const struct lttng_trigger
*trigger
, uint64_t *count
)
1209 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1210 case LTTNG_DOMAIN_KERNEL
:
1211 return event_notifier_error_accounting_kernel_get_count(trigger
, count
);
1212 case LTTNG_DOMAIN_UST
:
1213 case LTTNG_DOMAIN_PYTHON
:
1214 case LTTNG_DOMAIN_JUL
:
1215 case LTTNG_DOMAIN_LOG4J
:
1216 case LTTNG_DOMAIN_LOG4J2
:
1217 #ifdef HAVE_LIBLTTNG_UST_CTL
1218 return event_notifier_error_accounting_ust_get_count(trigger
, count
);
1221 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1222 #endif /* HAVE_LIBLTTNG_UST_CTL */
1228 static enum event_notifier_error_accounting_status
1229 event_notifier_error_accounting_clear(const struct lttng_trigger
*trigger
)
1231 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1232 case LTTNG_DOMAIN_KERNEL
:
1233 return event_notifier_error_accounting_kernel_clear(trigger
);
1234 case LTTNG_DOMAIN_UST
:
1235 case LTTNG_DOMAIN_PYTHON
:
1236 case LTTNG_DOMAIN_JUL
:
1237 case LTTNG_DOMAIN_LOG4J
:
1238 case LTTNG_DOMAIN_LOG4J2
:
1239 #ifdef HAVE_LIBLTTNG_UST_CTL
1240 return event_notifier_error_accounting_ust_clear(trigger
);
1242 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1243 #endif /* HAVE_LIBLTTNG_UST_CTL */
1249 static void free_index_ht_entry(struct rcu_head
*head
)
1251 auto *entry
= lttng::utils::container_of(head
, &index_ht_entry::rcu_head
);
1256 void event_notifier_error_accounting_unregister_event_notifier(const struct lttng_trigger
*trigger
)
1258 struct lttng_ht_iter iter
;
1259 struct lttng_ht_node_u64
*node
;
1260 const uint64_t tracer_token
= lttng_trigger_get_tracer_token(trigger
);
1261 enum event_notifier_error_accounting_status status
;
1262 struct error_accounting_state
*state
;
1264 const lttng::urcu::read_lock_guard read_lock
;
1266 status
= event_notifier_error_accounting_clear(trigger
);
1267 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
1268 /* Trigger details already logged by callee on error. */
1269 ERR("Failed to clear event notifier error counter during unregistration of event notifier: status = '%s'",
1270 error_accounting_status_str(status
));
1274 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1275 case LTTNG_DOMAIN_KERNEL
:
1276 state
= &kernel_state
;
1278 #ifdef HAVE_LIBLTTNG_UST_CTL
1279 case LTTNG_DOMAIN_UST
:
1280 case LTTNG_DOMAIN_PYTHON
:
1281 case LTTNG_DOMAIN_JUL
:
1282 case LTTNG_DOMAIN_LOG4J
:
1283 case LTTNG_DOMAIN_LOG4J2
:
1286 pthread_mutex_lock(&the_event_notifier_counter
.lock
);
1287 the_event_notifier_counter
.count
--;
1288 if (the_event_notifier_counter
.count
== 0) {
1290 * When unregistering the last event notifier, put one
1291 * reference to every uid entries on the behalf of all
1294 put_ref_all_ust_error_accounting_entry();
1297 pthread_mutex_unlock(&the_event_notifier_counter
.lock
);
1300 #endif /* HAVE_LIBLTTNG_UST_CTL */
1305 lttng_ht_lookup(state
->indices_ht
, &tracer_token
, &iter
);
1306 node
= lttng_ht_iter_get_node
<lttng_ht_node_u64
>(&iter
);
1309 struct index_ht_entry
*index_entry
=
1310 lttng::utils::container_of(node
, &index_ht_entry::node
);
1311 enum lttng_index_allocator_status index_alloc_status
;
1313 index_alloc_status
= lttng_index_allocator_release(
1314 state
->index_allocator
, index_entry
->error_counter_index
);
1315 if (index_alloc_status
!= LTTNG_INDEX_ALLOCATOR_STATUS_OK
) {
1316 uid_t trigger_owner_uid
;
1317 const char *trigger_name
;
1319 get_trigger_info_for_log(trigger
, &trigger_name
, &trigger_owner_uid
);
1321 ERR("Failed to release event notifier error counter index: index = %" PRIu64
1322 ", trigger name = '%s', trigger owner uid = %d",
1323 index_entry
->error_counter_index
,
1325 (int) trigger_owner_uid
);
1326 /* Don't exit, perform the rest of the clean-up. */
1329 del_ret
= lttng_ht_del(state
->indices_ht
, &iter
);
1330 LTTNG_ASSERT(!del_ret
);
1331 call_rcu(&index_entry
->rcu_head
, free_index_ht_entry
);
1337 void event_notifier_error_accounting_fini()
1339 if (kernel_error_accounting_entry
.error_counter_fd
) {
1340 const int ret
= close(kernel_error_accounting_entry
.error_counter_fd
);
1343 PERROR("Failed to close kernel event notifier error counter");
1347 lttng_ht_destroy(error_counter_uid_ht
);
1349 fini_error_accounting_state(&kernel_state
);
1350 fini_error_accounting_state(&ust_state
);