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.hpp>
16 #include <common/hashtable/hashtable.hpp>
17 #include <common/index-allocator.hpp>
18 #include <common/kernel-ctl/kernel-ctl.hpp>
19 #include <common/shm.hpp>
20 #include <lttng/trigger/trigger-internal.hpp>
22 #include "event-notifier-error-accounting.hpp"
23 #include "lttng-ust-error.hpp"
24 #include "ust-app.hpp"
26 #define ERROR_COUNTER_INDEX_HT_INITIAL_SIZE 16
29 struct index_ht_entry
{
30 struct lttng_ht_node_u64 node
;
31 uint64_t error_counter_index
;
32 struct rcu_head rcu_head
;
35 struct ust_error_accounting_entry
{
38 struct lttng_ht_node_u64 node
;
39 struct rcu_head rcu_head
;
40 struct lttng_ust_ctl_daemon_counter
*daemon_counter
;
42 * Those `lttng_ust_abi_object_data` are anonymous handles to the
44 * They are only used to be duplicated for each new applications of the
45 * user. To destroy them, call with the `sock` parameter set to -1.
46 * e.g. `lttng_ust_ctl_release_object(-1, data)`;
48 struct lttng_ust_abi_object_data
*counter
;
49 struct lttng_ust_abi_object_data
**cpu_counters
;
50 int nr_counter_cpu_fds
;
53 struct kernel_error_accounting_entry
{
57 struct kernel_error_accounting_entry kernel_error_accounting_entry
;
59 /* Hashtable mapping uid to error_account_entry. */
60 struct lttng_ht
*error_counter_uid_ht
;
62 struct error_accounting_state
{
63 struct lttng_index_allocator
*index_allocator
;
64 /* Hashtable mapping event notifier token to index_ht_entry. */
65 struct lttng_ht
*indices_ht
;
66 uint64_t number_indices
;
69 struct error_accounting_state ust_state
;
70 struct error_accounting_state kernel_state
;
73 static inline void get_trigger_info_for_log(const struct lttng_trigger
*trigger
,
74 const char **trigger_name
,
75 uid_t
*trigger_owner_uid
)
77 enum lttng_trigger_status trigger_status
;
79 trigger_status
= lttng_trigger_get_name(trigger
, trigger_name
);
80 switch (trigger_status
) {
81 case LTTNG_TRIGGER_STATUS_OK
:
83 case LTTNG_TRIGGER_STATUS_UNSET
:
84 *trigger_name
= "(anonymous)";
90 trigger_status
= lttng_trigger_get_owner_uid(trigger
,
92 LTTNG_ASSERT(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
96 const char *error_accounting_status_str(
97 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
);
149 bool ust_error_accounting_entry_get(struct ust_error_accounting_entry
*entry
)
151 return urcu_ref_get_unless_zero(&entry
->ref
);
155 void ust_error_accounting_entry_release(struct urcu_ref
*entry_ref
)
157 struct ust_error_accounting_entry
*entry
=
158 lttng::utils::container_of(entry_ref
, &ust_error_accounting_entry::ref
);
161 cds_lfht_del(error_counter_uid_ht
->ht
, &entry
->node
.node
);
162 call_rcu(&entry
->rcu_head
, free_ust_error_accounting_entry
);
168 void ust_error_accounting_entry_put(struct ust_error_accounting_entry
*entry
)
174 urcu_ref_put(&entry
->ref
, ust_error_accounting_entry_release
);
178 * Put one reference to every UID entries.
181 void put_ref_all_ust_error_accounting_entry(void)
183 struct lttng_ht_iter iter
;
184 struct ust_error_accounting_entry
*uid_entry
;
186 ASSERT_LOCKED(the_event_notifier_counter
.lock
);
189 cds_lfht_for_each_entry(error_counter_uid_ht
->ht
, &iter
.iter
,
190 uid_entry
, node
.node
) {
191 ust_error_accounting_entry_put(uid_entry
);
198 * Get one reference to every UID entries.
201 void get_ref_all_ust_error_accounting_entry(void)
203 struct lttng_ht_iter iter
;
204 struct ust_error_accounting_entry
*uid_entry
;
206 ASSERT_LOCKED(the_event_notifier_counter
.lock
);
209 cds_lfht_for_each_entry(error_counter_uid_ht
->ht
, &iter
.iter
,
210 uid_entry
, node
.node
) {
211 ust_error_accounting_entry_get(uid_entry
);
217 #endif /* HAVE_LIBLTTNG_UST_CTL */
220 enum event_notifier_error_accounting_status
221 init_error_accounting_state(struct error_accounting_state
*state
,
222 uint64_t index_count
)
224 enum event_notifier_error_accounting_status status
;
228 state
->number_indices
= index_count
;
230 state
->index_allocator
= lttng_index_allocator_create(index_count
);
231 if (!state
->index_allocator
) {
232 ERR("Failed to allocate event notifier error counter index allocator");
233 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
237 state
->indices_ht
= lttng_ht_new(ERROR_COUNTER_INDEX_HT_INITIAL_SIZE
,
239 if (!state
->indices_ht
) {
240 ERR("Failed to allocate error counter indices hash table");
241 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
242 goto error_indices_ht
;
245 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
249 lttng_index_allocator_destroy(state
->index_allocator
);
250 state
->index_allocator
= NULL
;
256 void fini_error_accounting_state(struct error_accounting_state
*state
)
261 * Will assert if some error counter indices were not released (an
264 lttng_ht_destroy(state
->indices_ht
);
265 lttng_index_allocator_destroy(state
->index_allocator
);
268 enum event_notifier_error_accounting_status
269 event_notifier_error_accounting_init(uint64_t buffer_size_kernel
,
270 uint64_t buffer_size_ust
)
272 enum event_notifier_error_accounting_status status
;
274 status
= init_error_accounting_state(&kernel_state
, buffer_size_kernel
);
275 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
276 ERR("Failed to initialize kernel event notifier accounting state: status = %s",
277 error_accounting_status_str(status
));
281 status
= init_error_accounting_state(&ust_state
, buffer_size_ust
);
282 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
283 ERR("Failed to initialize UST event notifier accounting state: status = %s",
284 error_accounting_status_str(status
));
285 goto error_ust_state
;
288 error_counter_uid_ht
= lttng_ht_new(
289 ERROR_COUNTER_INDEX_HT_INITIAL_SIZE
, LTTNG_HT_TYPE_U64
);
290 if (!error_counter_uid_ht
) {
291 ERR("Failed to allocate UID to error counter accountant hash table");
292 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
296 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
300 fini_error_accounting_state(&ust_state
);
302 fini_error_accounting_state(&kernel_state
);
308 * Return the error counteur index associated to this event notifier tracer
309 * token. Returns _STATUS_OK if found and _STATUS_NOT_FOUND otherwise.
312 enum event_notifier_error_accounting_status
get_error_counter_index_for_token(
313 struct error_accounting_state
*state
, uint64_t tracer_token
,
314 uint64_t *error_counter_index
)
316 struct lttng_ht_node_u64
*node
;
317 struct lttng_ht_iter iter
;
318 const struct index_ht_entry
*index_entry
;
319 enum event_notifier_error_accounting_status status
;
322 lttng_ht_lookup(state
->indices_ht
, &tracer_token
, &iter
);
323 node
= lttng_ht_iter_get_node_u64(&iter
);
325 index_entry
= lttng::utils::container_of(node
, &index_ht_entry::node
);
326 *error_counter_index
= index_entry
->error_counter_index
;
327 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
329 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND
;
336 #ifdef HAVE_LIBLTTNG_UST_CTL
338 * Find the entry for this app's UID, the caller acquires a reference if the
342 struct ust_error_accounting_entry
*ust_error_accounting_entry_find(
343 struct lttng_ht
*uid_ht
, const struct ust_app
*app
)
345 struct ust_error_accounting_entry
*entry
;
346 struct lttng_ht_node_u64
*node
;
347 struct lttng_ht_iter iter
;
348 uint64_t key
= app
->uid
;
350 lttng_ht_lookup(uid_ht
, &key
, &iter
);
351 node
= lttng_ht_iter_get_node_u64(&iter
);
357 entry
= caa_container_of(node
,
358 struct ust_error_accounting_entry
, node
);
360 got_ref
= ust_error_accounting_entry_get(entry
);
370 * Create the entry for this app's UID, the caller acquires a reference to the
374 struct ust_error_accounting_entry
*ust_error_accounting_entry_create(
375 const struct ust_app
*app
)
377 int i
, ret
, *cpu_counter_fds
= NULL
;
378 struct lttng_ust_ctl_daemon_counter
*daemon_counter
;
379 struct lttng_ust_abi_object_data
*counter
, **cpu_counters
;
380 struct ust_error_accounting_entry
*entry
= NULL
;
381 lttng_ust_ctl_counter_dimension dimension
;
383 dimension
.size
= ust_state
.number_indices
;
384 dimension
.has_underflow
= false;
385 dimension
.has_overflow
= false;
387 if (!ust_app_supports_counters(app
)) {
388 DBG("Refusing to create accounting entry for application (unsupported feature): app name = '%s', app ppid = %d",
389 app
->name
, (int) app
->ppid
);
393 entry
= zmalloc
<ust_error_accounting_entry
>();
395 PERROR("Failed to allocate event notifier error acounting entry")
399 urcu_ref_init(&entry
->ref
);
400 entry
->uid
= app
->uid
;
401 entry
->nr_counter_cpu_fds
= lttng_ust_ctl_get_nr_cpu_per_counter();
403 cpu_counter_fds
= calloc
<int>(entry
->nr_counter_cpu_fds
);
404 if (!cpu_counter_fds
) {
405 PERROR("Failed to allocate event notifier error counter file descriptors array: application uid = %d, application name = '%s', pid = %d, allocation size = %zu",
406 (int) app
->uid
, app
->name
, (int) app
->pid
,
407 entry
->nr_counter_cpu_fds
* sizeof(*cpu_counter_fds
));
408 goto error_counter_cpu_fds_alloc
;
411 /* Initialize to an invalid fd value to closes fds in case of error. */
412 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
413 cpu_counter_fds
[i
] = -1;
416 cpu_counters
= calloc
<lttng_ust_abi_object_data
*>(entry
->nr_counter_cpu_fds
);
418 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",
419 (int) app
->uid
, app
->name
, (int) app
->pid
,
420 entry
->nr_counter_cpu_fds
* sizeof(struct lttng_ust_abi_object_data
*));
421 goto error_counter_cpus_alloc
;
424 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
425 cpu_counter_fds
[i
] = shm_create_anonymous("event-notifier-error-accounting");
426 if (cpu_counter_fds
[i
] == -1) {
427 ERR("Failed to create event notifier error accounting shared memory for application user: application uid = %d, pid = %d, application name = '%s'",
428 (int) app
->uid
, (int) app
->pid
, app
->name
);
429 goto error_shm_alloc
;
434 * Ownership of the file descriptors transferred to the ustctl object.
436 daemon_counter
= lttng_ust_ctl_create_counter(1, &dimension
, 0, -1,
437 entry
->nr_counter_cpu_fds
, cpu_counter_fds
,
438 LTTNG_UST_CTL_COUNTER_BITNESS_32
,
439 LTTNG_UST_CTL_COUNTER_ARITHMETIC_MODULAR
,
440 LTTNG_UST_CTL_COUNTER_ALLOC_PER_CPU
,
442 if (!daemon_counter
) {
443 goto error_create_daemon_counter
;
446 ret
= lttng_ust_ctl_create_counter_data(daemon_counter
, &counter
);
448 ERR("Failed to create userspace tracer counter data for application user: uid = %d, pid = %d, application name = '%s'",
449 (int) app
->uid
, (int) app
->pid
, app
->name
);
450 goto error_create_counter_data
;
453 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
454 ret
= lttng_ust_ctl_create_counter_cpu_data(daemon_counter
, i
,
457 ERR("Failed to create userspace tracer counter cpu data for application user: uid = %d, pid = %d, application name = '%s'",
458 (int) app
->uid
, (int) app
->pid
,
460 goto error_create_counter_cpu_data
;
464 entry
->daemon_counter
= daemon_counter
;
465 entry
->counter
= counter
;
466 entry
->cpu_counters
= cpu_counters
;
468 lttng_ht_node_init_u64(&entry
->node
, entry
->uid
);
469 lttng_ht_add_unique_u64(error_counter_uid_ht
, &entry
->node
);
473 error_create_counter_cpu_data
:
474 /* Teardown any allocated cpu counters. */
475 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
476 if (!cpu_counters
[i
]) {
478 * Early-exit when error occurred before all cpu
479 * counters could be initialized.
484 lttng_ust_ctl_release_object(-1, cpu_counters
[i
]);
485 free(cpu_counters
[i
]);
488 lttng_ust_ctl_release_object(-1, entry
->counter
);
489 free(entry
->counter
);
490 error_create_counter_data
:
491 lttng_ust_ctl_destroy_counter(daemon_counter
);
492 error_create_daemon_counter
:
494 /* Error occurred before per-cpu SHMs were handed-off to ustctl. */
495 if (cpu_counter_fds
) {
496 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
497 if (cpu_counter_fds
[i
] < 0) {
499 * Early-exit when error occurred before all cpu
500 * counter shm fds could be initialized.
505 ret
= close(cpu_counter_fds
[i
]);
507 PERROR("Failed to close error counter per-CPU shm file descriptor: fd = %d",
514 error_counter_cpus_alloc
:
515 error_counter_cpu_fds_alloc
:
520 free(cpu_counter_fds
);
525 enum event_notifier_error_accounting_status
send_counter_data_to_ust(
527 struct lttng_ust_abi_object_data
*new_counter
)
530 enum event_notifier_error_accounting_status status
;
532 /* Attach counter to trigger group. */
533 pthread_mutex_lock(&app
->sock_lock
);
534 ret
= lttng_ust_ctl_send_counter_data_to_ust(app
->sock
,
535 app
->event_notifier_group
.object
->handle
, new_counter
);
536 pthread_mutex_unlock(&app
->sock_lock
);
538 if (ret
!= -EPIPE
&& ret
!= -LTTNG_UST_ERR_EXITING
) {
539 ERR("Failed to send counter data to application: application name = '%s', pid = %d, ret = %d",
540 app
->name
, app
->pid
, ret
);
541 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
543 DBG3("Failed to send counter data to application (application is dead): application name = '%s', pid = %d, ret = %d",
544 app
->name
, app
->pid
, ret
);
545 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
;
551 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
557 enum event_notifier_error_accounting_status
send_counter_cpu_data_to_ust(
559 struct lttng_ust_abi_object_data
*counter
,
560 struct lttng_ust_abi_object_data
*counter_cpu
)
563 enum event_notifier_error_accounting_status status
;
565 pthread_mutex_lock(&app
->sock_lock
);
566 ret
= lttng_ust_ctl_send_counter_cpu_data_to_ust(app
->sock
,
567 counter
, counter_cpu
);
568 pthread_mutex_unlock(&app
->sock_lock
);
570 if (ret
!= -EPIPE
&& ret
!= -LTTNG_UST_ERR_EXITING
) {
571 ERR("Failed to send counter CPU data to application: application name = '%s', pid = %d, ret = %d",
572 app
->name
, app
->pid
, ret
);
573 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
575 DBG3("Failed to send counter CPU data to application: application name = '%s', pid = %d, ret = %d",
576 app
->name
, app
->pid
, ret
);
577 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
;
583 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
588 enum event_notifier_error_accounting_status
589 event_notifier_error_accounting_register_app(struct ust_app
*app
)
593 struct lttng_ust_abi_object_data
*new_counter
;
594 struct ust_error_accounting_entry
*entry
;
595 enum event_notifier_error_accounting_status status
;
596 struct lttng_ust_abi_object_data
**cpu_counters
;
598 if (!ust_app_supports_counters(app
)) {
599 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_UNSUPPORTED
;
604 * Check if we already have a error counter for the user id of this
605 * app. If not, create one.
608 entry
= ust_error_accounting_entry_find(error_counter_uid_ht
, app
);
611 * Take the event notifier counter lock before creating the new
612 * entry to ensure that no event notifier is registered between
613 * the the entry creation and event notifier count check.
615 pthread_mutex_lock(&the_event_notifier_counter
.lock
);
617 entry
= ust_error_accounting_entry_create(app
);
619 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
620 pthread_mutex_unlock(&the_event_notifier_counter
.lock
);
621 goto error_creating_entry
;
625 * We just created a new UID entry, If there are event
626 * notifiers already registered, take one reference on their
629 if (the_event_notifier_counter
.count
> 0) {
630 ust_error_accounting_entry_get(entry
);
633 pthread_mutex_unlock(&the_event_notifier_counter
.lock
);
636 /* Duplicate counter object data. */
637 ret
= lttng_ust_ctl_duplicate_ust_object_data(&new_counter
,
640 ERR("Failed to duplicate event notifier error accounting counter for application user: application uid = %d, pid = %d, application name = '%s'",
641 (int) app
->uid
, (int) app
->pid
, app
->name
);
642 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
643 goto error_duplicate_counter
;
646 status
= send_counter_data_to_ust(app
, new_counter
);
647 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
648 if (status
== EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
) {
649 goto error_send_counter_data
;
652 ERR("Failed to send counter data to application tracer: status = %s, application uid = %d, pid = %d, application name = '%s'",
653 error_accounting_status_str(status
),
654 (int) app
->uid
, (int) app
->pid
, app
->name
);
655 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
656 goto error_send_counter_data
;
659 cpu_counters
= calloc
<lttng_ust_abi_object_data
*>(entry
->nr_counter_cpu_fds
);
661 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",
662 (int) app
->uid
, app
->name
, (int) app
->pid
,
663 entry
->nr_counter_cpu_fds
* sizeof(**cpu_counters
));
664 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
665 goto error_allocate_cpu_counters
;
668 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
669 struct lttng_ust_abi_object_data
*new_counter_cpu
= NULL
;
671 ret
= lttng_ust_ctl_duplicate_ust_object_data(&new_counter_cpu
,
672 entry
->cpu_counters
[i
]);
674 ERR("Failed to duplicate userspace tracer counter cpu data for application user: uid = %d, pid = %d, application name = '%s'",
675 (int) app
->uid
, (int) app
->pid
,
677 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
678 goto error_duplicate_cpu_counter
;
681 cpu_counters
[i
] = new_counter_cpu
;
683 status
= send_counter_cpu_data_to_ust(app
, new_counter
,
685 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
686 if (status
== EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD
) {
687 goto error_send_cpu_counter_data
;
690 ERR("Failed to send counter cpu data to application tracer: status = %s, application uid = %d, pid = %d, application name = '%s'",
691 error_accounting_status_str(status
),
692 (int) app
->uid
, (int) app
->pid
,
694 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
695 goto error_send_cpu_counter_data
;
699 app
->event_notifier_group
.counter
= new_counter
;
701 app
->event_notifier_group
.nr_counter_cpu
= entry
->nr_counter_cpu_fds
;
702 app
->event_notifier_group
.counter_cpu
= cpu_counters
;
706 error_send_cpu_counter_data
:
707 error_duplicate_cpu_counter
:
708 /* Teardown any duplicated cpu counters. */
709 for (i
= 0; i
< entry
->nr_counter_cpu_fds
; i
++) {
710 if (!cpu_counters
[i
]) {
712 * Early-exit when error occurred before all cpu
713 * counters could be initialized.
718 lttng_ust_ctl_release_object(-1, cpu_counters
[i
]);
719 free(cpu_counters
[i
]);
724 error_allocate_cpu_counters
:
725 error_send_counter_data
:
726 lttng_ust_ctl_release_object(-1, new_counter
);
728 error_duplicate_counter
:
729 ust_error_accounting_entry_put(entry
);
730 error_creating_entry
:
731 app
->event_notifier_group
.counter
= NULL
;
738 enum event_notifier_error_accounting_status
739 event_notifier_error_accounting_unregister_app(struct ust_app
*app
)
741 enum event_notifier_error_accounting_status status
;
742 struct ust_error_accounting_entry
*entry
;
747 /* If an error occurred during app registration no entry was created. */
748 if (!app
->event_notifier_group
.counter
) {
749 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
753 entry
= ust_error_accounting_entry_find(error_counter_uid_ht
, app
);
755 ERR("Failed to find event notitifier error accounting entry on application teardown: pid = %d, application name = '%s'",
756 app
->pid
, app
->name
);
757 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
761 * Put the entry twice as we acquired a reference from the
762 * `ust_error_accounting_entry_find()` above.
764 ust_error_accounting_entry_put(entry
);
765 ust_error_accounting_entry_put(entry
);
768 for (i
= 0; i
< app
->event_notifier_group
.nr_counter_cpu
; i
++) {
769 lttng_ust_ctl_release_object(app
->sock
,
770 app
->event_notifier_group
.counter_cpu
[i
]);
771 free(app
->event_notifier_group
.counter_cpu
[i
]);
774 free(app
->event_notifier_group
.counter_cpu
);
776 lttng_ust_ctl_release_object(app
->sock
, app
->event_notifier_group
.counter
);
777 free(app
->event_notifier_group
.counter
);
779 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
786 enum event_notifier_error_accounting_status
787 event_notifier_error_accounting_ust_get_count(
788 const struct lttng_trigger
*trigger
, uint64_t *count
)
790 struct lttng_ht_iter iter
;
791 struct ust_error_accounting_entry
*uid_entry
;
792 uint64_t error_counter_index
, global_sum
= 0;
793 enum event_notifier_error_accounting_status status
;
794 size_t dimension_indexes
[1];
795 const uint64_t tracer_token
= lttng_trigger_get_tracer_token(trigger
);
796 uid_t trigger_owner_uid
;
797 const char *trigger_name
;
802 get_trigger_info_for_log(trigger
, &trigger_name
, &trigger_owner_uid
);
804 status
= get_error_counter_index_for_token(&ust_state
, tracer_token
,
805 &error_counter_index
);
806 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
808 ERR("Failed to retrieve index for tracer token: token = %" PRIu64
", trigger name = '%s', trigger owner uid = %d, status = %s",
809 tracer_token
, trigger_name
,
810 (int) trigger_owner_uid
,
811 error_accounting_status_str(status
));
815 dimension_indexes
[0] = error_counter_index
;
818 * Iterate over all the UID entries.
819 * We aggregate the value of all uid entries regardless of if the uid
820 * matches the trigger's uid because a user that is allowed to register
821 * a trigger to a given sessiond is also allowed to create an event
822 * notifier on all apps that this sessiond is aware of.
824 cds_lfht_for_each_entry(error_counter_uid_ht
->ht
, &iter
.iter
,
825 uid_entry
, node
.node
) {
827 int64_t local_value
= 0;
828 bool overflow
= false, underflow
= false;
830 ret
= lttng_ust_ctl_counter_aggregate(uid_entry
->daemon_counter
,
831 dimension_indexes
, &local_value
, &overflow
,
833 if (ret
|| local_value
< 0) {
835 ERR("Failed to aggregate event notifier error counter values of trigger: trigger name = '%s', trigger owner uid = %d",
837 (int) trigger_owner_uid
);
838 } else if (local_value
< 0) {
839 ERR("Negative event notifier error counter value encountered during aggregation: trigger name = '%s', trigger owner uid = %d, value = %" PRId64
,
841 (int) trigger_owner_uid
,
847 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
851 /* Cast is safe as negative values are checked-for above. */
852 global_sum
+= (uint64_t) local_value
;
856 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
864 enum event_notifier_error_accounting_status
event_notifier_error_accounting_ust_clear(
865 const struct lttng_trigger
*trigger
)
867 struct lttng_ht_iter iter
;
868 struct ust_error_accounting_entry
*uid_entry
;
869 uint64_t error_counter_index
;
870 enum event_notifier_error_accounting_status status
;
871 size_t dimension_index
;
872 const uint64_t tracer_token
= lttng_trigger_get_tracer_token(trigger
);
875 status
= get_error_counter_index_for_token(&ust_state
, tracer_token
,
876 &error_counter_index
);
877 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
878 uid_t trigger_owner_uid
;
879 const char *trigger_name
;
881 get_trigger_info_for_log(trigger
, &trigger_name
,
884 ERR("Failed to retrieve index for tracer token: token = %" PRIu64
", trigger name = '%s', trigger owner uid = %d, status = %s",
885 tracer_token
, trigger_name
,
886 (int) trigger_owner_uid
,
887 error_accounting_status_str(status
));
891 dimension_index
= error_counter_index
;
894 * Go over all error counters (ignoring uid) as a trigger (and trigger
895 * errors) can be generated from any applications that this session
896 * daemon is managing.
898 cds_lfht_for_each_entry(error_counter_uid_ht
->ht
, &iter
.iter
,
899 uid_entry
, node
.node
) {
900 const int ret
= lttng_ust_ctl_counter_clear(uid_entry
->daemon_counter
,
904 uid_t trigger_owner_uid
;
905 const char *trigger_name
;
907 get_trigger_info_for_log(trigger
, &trigger_name
,
909 ERR("Failed to clear event notifier counter value for trigger: counter uid = %d, trigger name = '%s', trigger owner uid = %d",
910 (int) uid_entry
->node
.key
, trigger_name
,
911 (int) trigger_owner_uid
);
912 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
917 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
922 #endif /* HAVE_LIBLTTNG_UST_CTL */
925 enum event_notifier_error_accounting_status
926 event_notifier_error_accounting_kernel_clear(
927 const struct lttng_trigger
*trigger
)
930 uint64_t error_counter_index
;
931 enum event_notifier_error_accounting_status status
;
932 struct lttng_kernel_abi_counter_clear counter_clear
= {};
934 status
= get_error_counter_index_for_token(&kernel_state
,
935 lttng_trigger_get_tracer_token(trigger
),
936 &error_counter_index
);
937 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
938 uid_t trigger_owner_uid
;
939 const char *trigger_name
;
941 get_trigger_info_for_log(
942 trigger
, &trigger_name
, &trigger_owner_uid
);
944 ERR("Failed to get event notifier error counter index: trigger owner uid = %d, trigger name = '%s', status = '%s'",
945 trigger_owner_uid
, trigger_name
,
946 error_accounting_status_str(status
));
950 counter_clear
.index
.number_dimensions
= 1;
951 counter_clear
.index
.dimension_indexes
[0] = error_counter_index
;
953 ret
= kernctl_counter_clear(
954 kernel_error_accounting_entry
.error_counter_fd
,
957 uid_t trigger_owner_uid
;
958 const char *trigger_name
;
960 get_trigger_info_for_log(
961 trigger
, &trigger_name
, &trigger_owner_uid
);
963 ERR("Failed to clear kernel event notifier error counter: trigger owner uid = %d, trigger name = '%s'",
964 trigger_owner_uid
, trigger_name
);
965 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
969 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
974 enum event_notifier_error_accounting_status
975 event_notifier_error_accounting_register_kernel(
976 int kernel_event_notifier_group_fd
)
978 int error_counter_fd
= -1, ret
;
979 enum event_notifier_error_accounting_status status
;
980 lttng_kernel_abi_counter_conf error_counter_conf
= {
981 .arithmetic
= LTTNG_KERNEL_ABI_COUNTER_ARITHMETIC_MODULAR
,
982 .bitness
= sizeof(void *) == sizeof(uint32_t) ?
983 LTTNG_KERNEL_ABI_COUNTER_BITNESS_32
:
984 LTTNG_KERNEL_ABI_COUNTER_BITNESS_64
,
985 .number_dimensions
= 1,
986 .global_sum_step
= 0,
991 error_counter_conf
.dimensions
[0].size
= kernel_state
.number_indices
;
992 error_counter_conf
.dimensions
[0].has_underflow
= false;
993 error_counter_conf
.dimensions
[0].has_overflow
= false;
995 ret
= kernctl_create_event_notifier_group_error_counter(
996 kernel_event_notifier_group_fd
, &error_counter_conf
);
998 PERROR("Failed to create event notifier group error counter through kernel ioctl: kernel_event_notifier_group_fd = %d",
999 kernel_event_notifier_group_fd
);
1000 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
1004 error_counter_fd
= ret
;
1006 /* Prevent fd duplication after execlp(). */
1007 ret
= fcntl(error_counter_fd
, F_SETFD
, FD_CLOEXEC
);
1009 PERROR("Failed to set FD_CLOEXEC flag on event notifier error counter file descriptor: error_counter_fd = %d",
1011 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
1015 DBG("Created kernel event notifier group error counter: fd = %d",
1018 kernel_error_accounting_entry
.error_counter_fd
=
1020 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1027 enum event_notifier_error_accounting_status
create_error_counter_index_for_token(
1028 struct error_accounting_state
*state
, uint64_t tracer_token
,
1029 uint64_t *error_counter_index
)
1031 struct index_ht_entry
*index_entry
;
1032 enum lttng_index_allocator_status index_alloc_status
;
1033 uint64_t local_error_counter_index
;
1034 enum event_notifier_error_accounting_status status
;
1036 LTTNG_ASSERT(state
);
1038 /* Allocate a new index for that counter. */
1039 index_alloc_status
= lttng_index_allocator_alloc(state
->index_allocator
,
1040 &local_error_counter_index
);
1041 switch (index_alloc_status
) {
1042 case LTTNG_INDEX_ALLOCATOR_STATUS_EMPTY
:
1043 DBG("No indices left in the configured event notifier error counter: "
1044 "number-of-indices = %" PRIu64
,
1045 lttng_index_allocator_get_index_count(
1046 state
->index_allocator
));
1047 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE
;
1049 case LTTNG_INDEX_ALLOCATOR_STATUS_OK
:
1052 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
1056 index_entry
= zmalloc
<index_ht_entry
>();
1057 if (index_entry
== NULL
) {
1058 PERROR("Failed to allocate event notifier error counter hash table entry");
1059 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM
;
1063 index_entry
->error_counter_index
= local_error_counter_index
;
1064 lttng_ht_node_init_u64(&index_entry
->node
, tracer_token
);
1065 lttng_ht_add_unique_u64(state
->indices_ht
, &index_entry
->node
);
1067 DBG("Allocated error counter index for tracer token: tracer token = %" PRIu64
", index = %" PRIu64
,
1068 tracer_token
, local_error_counter_index
);
1069 *error_counter_index
= local_error_counter_index
;
1070 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1075 enum event_notifier_error_accounting_status
1076 event_notifier_error_accounting_register_event_notifier(
1077 const struct lttng_trigger
*trigger
,
1078 uint64_t *error_counter_index
)
1080 enum event_notifier_error_accounting_status status
;
1081 uint64_t local_error_counter_index
;
1082 struct error_accounting_state
*state
;
1084 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1085 case LTTNG_DOMAIN_KERNEL
:
1086 state
= &kernel_state
;
1088 case LTTNG_DOMAIN_UST
:
1089 case LTTNG_DOMAIN_PYTHON
:
1090 case LTTNG_DOMAIN_JUL
:
1091 case LTTNG_DOMAIN_LOG4J
:
1099 * Check if this event notifier already has a error counter index
1102 status
= get_error_counter_index_for_token(state
,
1103 lttng_trigger_get_tracer_token(trigger
),
1104 &local_error_counter_index
);
1106 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND
:
1108 uid_t trigger_owner_uid
;
1109 const char *trigger_name
;
1111 get_trigger_info_for_log(
1112 trigger
, &trigger_name
, &trigger_owner_uid
);
1114 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
,
1115 trigger_name
, trigger_owner_uid
,
1116 lttng_trigger_get_tracer_token(trigger
));
1118 status
= create_error_counter_index_for_token(state
,
1119 lttng_trigger_get_tracer_token(trigger
),
1120 &local_error_counter_index
);
1121 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
1122 ERR("Error creating index for token: status = %s, trigger name = '%s', trigger owner uid = %d",
1123 error_accounting_status_str(status
),
1124 trigger_name
, trigger_owner_uid
);
1129 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
:
1130 *error_counter_index
= local_error_counter_index
;
1131 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1137 #ifdef HAVE_LIBLTTNG_UST_CTL
1138 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1139 case LTTNG_DOMAIN_UST
:
1140 case LTTNG_DOMAIN_PYTHON
:
1141 case LTTNG_DOMAIN_JUL
:
1142 case LTTNG_DOMAIN_LOG4J
:
1143 pthread_mutex_lock(&the_event_notifier_counter
.lock
);
1144 the_event_notifier_counter
.count
++;
1145 if (the_event_notifier_counter
.count
== 1) {
1147 * On the first event notifier, we get a reference to
1148 * every existing UID entries. This ensures that the
1149 * entries are kept around if there are still
1150 * registered event notifiers but no apps.
1152 get_ref_all_ust_error_accounting_entry();
1154 pthread_mutex_unlock(&the_event_notifier_counter
.lock
);
1159 #endif /* HAVE_LIBLTTNG_UST_CTL */
1167 enum event_notifier_error_accounting_status
1168 event_notifier_error_accounting_kernel_get_count(
1169 const struct lttng_trigger
*trigger
, uint64_t *count
)
1171 struct lttng_kernel_abi_counter_aggregate counter_aggregate
= {};
1172 enum event_notifier_error_accounting_status status
;
1173 uint64_t error_counter_index
;
1176 status
= get_error_counter_index_for_token(&kernel_state
,
1177 lttng_trigger_get_tracer_token(trigger
),
1178 &error_counter_index
);
1179 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
1180 ERR("Error getting index for token: status=%s",
1181 error_accounting_status_str(status
));
1185 counter_aggregate
.index
.number_dimensions
= 1;
1186 counter_aggregate
.index
.dimension_indexes
[0] = error_counter_index
;
1188 LTTNG_ASSERT(kernel_error_accounting_entry
.error_counter_fd
);
1190 ret
= kernctl_counter_get_aggregate_value(
1191 kernel_error_accounting_entry
.error_counter_fd
,
1192 &counter_aggregate
);
1193 if (ret
|| counter_aggregate
.value
.value
< 0) {
1194 uid_t trigger_owner_uid
;
1195 const char *trigger_name
;
1197 get_trigger_info_for_log(trigger
, &trigger_name
,
1198 &trigger_owner_uid
);
1200 if (counter_aggregate
.value
.value
< 0) {
1201 ERR("Invalid negative event notifier error counter value: trigger owner = %d, trigger name = '%s', value = %" PRId64
,
1202 trigger_owner_uid
, trigger_name
,
1203 counter_aggregate
.value
.value
);
1205 ERR("Failed to getting event notifier error count: trigger owner = %d, trigger name = '%s', ret = %d",
1206 trigger_owner_uid
, trigger_name
, ret
);
1209 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR
;
1213 /* Error count can't be negative. */
1214 LTTNG_ASSERT(counter_aggregate
.value
.value
>= 0);
1215 *count
= (uint64_t) counter_aggregate
.value
.value
;
1217 status
= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1223 enum event_notifier_error_accounting_status
1224 event_notifier_error_accounting_get_count(
1225 const struct lttng_trigger
*trigger
, uint64_t *count
)
1227 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1228 case LTTNG_DOMAIN_KERNEL
:
1229 return event_notifier_error_accounting_kernel_get_count(
1231 case LTTNG_DOMAIN_UST
:
1232 case LTTNG_DOMAIN_PYTHON
:
1233 case LTTNG_DOMAIN_JUL
:
1234 case LTTNG_DOMAIN_LOG4J
:
1235 #ifdef HAVE_LIBLTTNG_UST_CTL
1236 return event_notifier_error_accounting_ust_get_count(trigger
,
1240 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1241 #endif /* HAVE_LIBLTTNG_UST_CTL */
1248 enum event_notifier_error_accounting_status
1249 event_notifier_error_accounting_clear(const struct lttng_trigger
*trigger
)
1251 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1252 case LTTNG_DOMAIN_KERNEL
:
1253 return event_notifier_error_accounting_kernel_clear(trigger
);
1254 case LTTNG_DOMAIN_UST
:
1255 case LTTNG_DOMAIN_PYTHON
:
1256 case LTTNG_DOMAIN_JUL
:
1257 case LTTNG_DOMAIN_LOG4J
:
1258 #ifdef HAVE_LIBLTTNG_UST_CTL
1259 return event_notifier_error_accounting_ust_clear(trigger
);
1261 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
;
1262 #endif /* HAVE_LIBLTTNG_UST_CTL */
1268 static void free_index_ht_entry(struct rcu_head
*head
)
1270 struct index_ht_entry
*entry
= caa_container_of(head
,
1271 struct index_ht_entry
, rcu_head
);
1276 void event_notifier_error_accounting_unregister_event_notifier(
1277 const struct lttng_trigger
*trigger
)
1279 struct lttng_ht_iter iter
;
1280 struct lttng_ht_node_u64
*node
;
1281 const uint64_t tracer_token
= lttng_trigger_get_tracer_token(trigger
);
1282 enum event_notifier_error_accounting_status status
;
1283 struct error_accounting_state
*state
;
1285 status
= event_notifier_error_accounting_clear(trigger
);
1286 if (status
!= EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK
) {
1287 /* Trigger details already logged by callee on error. */
1288 ERR("Failed to clear event notifier error counter during unregistration of event notifier: status = '%s'",
1289 error_accounting_status_str(status
));
1295 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger
)) {
1296 case LTTNG_DOMAIN_KERNEL
:
1297 state
= &kernel_state
;
1299 #ifdef HAVE_LIBLTTNG_UST_CTL
1300 case LTTNG_DOMAIN_UST
:
1301 case LTTNG_DOMAIN_PYTHON
:
1302 case LTTNG_DOMAIN_JUL
:
1303 case LTTNG_DOMAIN_LOG4J
:
1306 pthread_mutex_lock(&the_event_notifier_counter
.lock
);
1307 the_event_notifier_counter
.count
--;
1308 if (the_event_notifier_counter
.count
== 0) {
1311 * When unregistering the last event notifier, put one
1312 * reference to every uid entries on the behalf of all
1315 put_ref_all_ust_error_accounting_entry();
1318 pthread_mutex_unlock(&the_event_notifier_counter
.lock
);
1321 #endif /* HAVE_LIBLTTNG_UST_CTL */
1326 lttng_ht_lookup(state
->indices_ht
, &tracer_token
, &iter
);
1327 node
= lttng_ht_iter_get_node_u64(&iter
);
1330 struct index_ht_entry
*index_entry
=
1331 lttng::utils::container_of(node
, &index_ht_entry::node
);
1332 enum lttng_index_allocator_status index_alloc_status
;
1334 index_alloc_status
= lttng_index_allocator_release(
1335 state
->index_allocator
,
1336 index_entry
->error_counter_index
);
1337 if (index_alloc_status
!= LTTNG_INDEX_ALLOCATOR_STATUS_OK
) {
1338 uid_t trigger_owner_uid
;
1339 const char *trigger_name
;
1341 get_trigger_info_for_log(trigger
, &trigger_name
,
1342 &trigger_owner_uid
);
1344 ERR("Failed to release event notifier error counter index: index = %" PRIu64
", trigger name = '%s', trigger owner uid = %d",
1345 index_entry
->error_counter_index
,
1346 trigger_name
, (int) trigger_owner_uid
);
1347 /* Don't exit, perform the rest of the clean-up. */
1350 del_ret
= lttng_ht_del(state
->indices_ht
, &iter
);
1351 LTTNG_ASSERT(!del_ret
);
1352 call_rcu(&index_entry
->rcu_head
, free_index_ht_entry
);
1359 void event_notifier_error_accounting_fini(void)
1361 if (kernel_error_accounting_entry
.error_counter_fd
) {
1362 const int ret
= close(kernel_error_accounting_entry
.error_counter_fd
);
1365 PERROR("Failed to close kernel event notifier error counter");
1369 lttng_ht_destroy(error_counter_uid_ht
);
1371 fini_error_accounting_state(&kernel_state
);
1372 fini_error_accounting_state(&ust_state
);