Replace explicit rcu_read_lock/unlock with lttng::urcu::read_lock_guard
[lttng-tools.git] / src / bin / lttng-sessiond / event-notifier-error-accounting.cpp
... / ...
CommitLineData
1/*
2 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8#include "event-notifier-error-accounting.hpp"
9#include "lttng-ust-error.hpp"
10#include "ust-app.hpp"
11
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>
18
19#include <lttng/trigger/trigger-internal.hpp>
20
21#include <fcntl.h>
22#include <pthread.h>
23#include <sys/mman.h>
24#include <sys/stat.h>
25#include <unistd.h>
26#include <urcu/compiler.h>
27
28#define ERROR_COUNTER_INDEX_HT_INITIAL_SIZE 16
29
30namespace {
31struct index_ht_entry {
32 struct lttng_ht_node_u64 node;
33 uint64_t error_counter_index;
34 struct rcu_head rcu_head;
35};
36
37struct ust_error_accounting_entry {
38 uid_t uid;
39 struct urcu_ref ref;
40 struct lttng_ht_node_u64 node;
41 struct rcu_head rcu_head;
42 struct lttng_ust_ctl_daemon_counter *daemon_counter;
43 /*
44 * Those `lttng_ust_abi_object_data` are anonymous handles to the
45 * counters objects.
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)`;
49 */
50 struct lttng_ust_abi_object_data *counter;
51 struct lttng_ust_abi_object_data **cpu_counters;
52 int nr_counter_cpu_fds;
53};
54
55struct kernel_error_accounting_entry {
56 int error_counter_fd;
57};
58
59struct kernel_error_accounting_entry kernel_error_accounting_entry;
60
61/* Hashtable mapping uid to error_account_entry. */
62struct lttng_ht *error_counter_uid_ht;
63
64struct 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;
69};
70
71struct error_accounting_state ust_state;
72struct error_accounting_state kernel_state;
73} /* namespace */
74
75static inline void get_trigger_info_for_log(const struct lttng_trigger *trigger,
76 const char **trigger_name,
77 uid_t *trigger_owner_uid)
78{
79 enum lttng_trigger_status trigger_status;
80
81 trigger_status = lttng_trigger_get_name(trigger, trigger_name);
82 switch (trigger_status) {
83 case LTTNG_TRIGGER_STATUS_OK:
84 break;
85 case LTTNG_TRIGGER_STATUS_UNSET:
86 *trigger_name = "(anonymous)";
87 break;
88 default:
89 abort();
90 }
91
92 trigger_status = lttng_trigger_get_owner_uid(trigger, trigger_owner_uid);
93 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
94}
95
96static inline const char *
97error_accounting_status_str(enum event_notifier_error_accounting_status status)
98{
99 switch (status) {
100 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK:
101 return "OK";
102 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR:
103 return "ERROR";
104 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND:
105 return "NOT_FOUND";
106 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM:
107 return "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:
111 return "APP_DEAD";
112 default:
113 abort();
114 }
115}
116
117#ifdef HAVE_LIBLTTNG_UST_CTL
118namespace {
119struct event_notifier_counter {
120 pthread_mutex_t lock;
121 long count;
122};
123
124struct event_notifier_counter the_event_notifier_counter;
125} /* namespace */
126
127static void free_ust_error_accounting_entry(struct rcu_head *head)
128{
129 int i;
130 struct ust_error_accounting_entry *entry =
131 lttng::utils::container_of(head, &ust_error_accounting_entry::rcu_head);
132
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]);
136 }
137
138 free(entry->cpu_counters);
139
140 lttng_ust_ctl_release_object(-1, entry->counter);
141 free(entry->counter);
142
143 lttng_ust_ctl_destroy_counter(entry->daemon_counter);
144
145 free(entry);
146}
147
148static bool ust_error_accounting_entry_get(struct ust_error_accounting_entry *entry)
149{
150 return urcu_ref_get_unless_zero(&entry->ref);
151}
152
153static void ust_error_accounting_entry_release(struct urcu_ref *entry_ref)
154{
155 struct ust_error_accounting_entry *entry =
156 lttng::utils::container_of(entry_ref, &ust_error_accounting_entry::ref);
157
158 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);
161}
162
163static void ust_error_accounting_entry_put(struct ust_error_accounting_entry *entry)
164{
165 if (!entry) {
166 return;
167 }
168
169 urcu_ref_put(&entry->ref, ust_error_accounting_entry_release);
170}
171
172/*
173 * Put one reference to every UID entries.
174 */
175static void put_ref_all_ust_error_accounting_entry()
176{
177 struct lttng_ht_iter iter;
178 struct ust_error_accounting_entry *uid_entry;
179
180 ASSERT_LOCKED(the_event_notifier_counter.lock);
181
182 {
183 lttng::urcu::read_lock_guard read_lock;
184
185 cds_lfht_for_each_entry (
186 error_counter_uid_ht->ht, &iter.iter, uid_entry, node.node) {
187 ust_error_accounting_entry_put(uid_entry);
188 }
189 }
190}
191
192/*
193 * Get one reference to every UID entries.
194 */
195static void get_ref_all_ust_error_accounting_entry()
196{
197 struct lttng_ht_iter iter;
198 struct ust_error_accounting_entry *uid_entry;
199
200 ASSERT_LOCKED(the_event_notifier_counter.lock);
201
202 {
203 lttng::urcu::read_lock_guard read_lock;
204
205 cds_lfht_for_each_entry (
206 error_counter_uid_ht->ht, &iter.iter, uid_entry, node.node) {
207 ust_error_accounting_entry_get(uid_entry);
208 }
209 }
210}
211
212#endif /* HAVE_LIBLTTNG_UST_CTL */
213
214static enum event_notifier_error_accounting_status
215init_error_accounting_state(struct error_accounting_state *state, uint64_t index_count)
216{
217 enum event_notifier_error_accounting_status status;
218
219 LTTNG_ASSERT(state);
220
221 state->number_indices = index_count;
222
223 state->index_allocator = lttng_index_allocator_create(index_count);
224 if (!state->index_allocator) {
225 ERR("Failed to allocate event notifier error counter index allocator");
226 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
227 goto end;
228 }
229
230 state->indices_ht = lttng_ht_new(ERROR_COUNTER_INDEX_HT_INITIAL_SIZE, LTTNG_HT_TYPE_U64);
231 if (!state->indices_ht) {
232 ERR("Failed to allocate error counter indices hash table");
233 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
234 goto error_indices_ht;
235 }
236
237 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
238 goto end;
239
240error_indices_ht:
241 lttng_index_allocator_destroy(state->index_allocator);
242 state->index_allocator = nullptr;
243end:
244 return status;
245}
246
247static void fini_error_accounting_state(struct error_accounting_state *state)
248{
249 LTTNG_ASSERT(state);
250
251 /*
252 * Will assert if some error counter indices were not released (an
253 * internal error).
254 */
255 lttng_ht_destroy(state->indices_ht);
256 lttng_index_allocator_destroy(state->index_allocator);
257}
258
259enum event_notifier_error_accounting_status
260event_notifier_error_accounting_init(uint64_t buffer_size_kernel, uint64_t buffer_size_ust)
261{
262 enum event_notifier_error_accounting_status status;
263
264 status = init_error_accounting_state(&kernel_state, buffer_size_kernel);
265 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
266 ERR("Failed to initialize kernel event notifier accounting state: status = %s",
267 error_accounting_status_str(status));
268 goto end;
269 }
270
271 status = init_error_accounting_state(&ust_state, buffer_size_ust);
272 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
273 ERR("Failed to initialize UST event notifier accounting state: status = %s",
274 error_accounting_status_str(status));
275 goto error_ust_state;
276 }
277
278 error_counter_uid_ht = lttng_ht_new(ERROR_COUNTER_INDEX_HT_INITIAL_SIZE, LTTNG_HT_TYPE_U64);
279 if (!error_counter_uid_ht) {
280 ERR("Failed to allocate UID to error counter accountant hash table");
281 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
282 goto error_uid_ht;
283 }
284
285 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
286 goto end;
287
288error_uid_ht:
289 fini_error_accounting_state(&ust_state);
290error_ust_state:
291 fini_error_accounting_state(&kernel_state);
292end:
293 return status;
294}
295
296/*
297 * Return the error counteur index associated to this event notifier tracer
298 * token. Returns _STATUS_OK if found and _STATUS_NOT_FOUND otherwise.
299 */
300static enum event_notifier_error_accounting_status get_error_counter_index_for_token(
301 struct error_accounting_state *state, uint64_t tracer_token, uint64_t *error_counter_index)
302{
303 struct lttng_ht_node_u64 *node;
304 struct lttng_ht_iter iter;
305 const struct index_ht_entry *index_entry;
306 enum event_notifier_error_accounting_status status;
307 lttng::urcu::read_lock_guard read_guard;
308
309 lttng_ht_lookup(state->indices_ht, &tracer_token, &iter);
310 node = lttng_ht_iter_get_node_u64(&iter);
311 if (node) {
312 index_entry = lttng::utils::container_of(node, &index_ht_entry::node);
313 *error_counter_index = index_entry->error_counter_index;
314 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
315 } else {
316 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND;
317 }
318
319 return status;
320}
321
322#ifdef HAVE_LIBLTTNG_UST_CTL
323/*
324 * Find the entry for this app's UID, the caller acquires a reference if the
325 * entry is found.
326 */
327static struct ust_error_accounting_entry *ust_error_accounting_entry_find(struct lttng_ht *uid_ht,
328 const struct ust_app *app)
329{
330 struct ust_error_accounting_entry *entry;
331 struct lttng_ht_node_u64 *node;
332 struct lttng_ht_iter iter;
333 uint64_t key = app->uid;
334
335 lttng_ht_lookup(uid_ht, &key, &iter);
336 node = lttng_ht_iter_get_node_u64(&iter);
337 if (node == nullptr) {
338 entry = nullptr;
339 } else {
340 bool got_ref;
341
342 entry = caa_container_of(node, struct ust_error_accounting_entry, node);
343
344 got_ref = ust_error_accounting_entry_get(entry);
345 if (!got_ref) {
346 entry = nullptr;
347 }
348 }
349
350 return entry;
351}
352
353/*
354 * Create the entry for this app's UID, the caller acquires a reference to the
355 * entry,
356 */
357static struct ust_error_accounting_entry *
358ust_error_accounting_entry_create(const struct ust_app *app)
359{
360 int i, ret, *cpu_counter_fds = nullptr;
361 struct lttng_ust_ctl_daemon_counter *daemon_counter;
362 struct lttng_ust_abi_object_data *counter, **cpu_counters;
363 struct ust_error_accounting_entry *entry = nullptr;
364 lttng_ust_ctl_counter_dimension dimension = {};
365
366 dimension.size = ust_state.number_indices;
367 dimension.has_underflow = false;
368 dimension.has_overflow = false;
369
370 if (!ust_app_supports_counters(app)) {
371 DBG("Refusing to create accounting entry for application (unsupported feature): app name = '%s', app ppid = %d",
372 app->name,
373 (int) app->ppid);
374 goto error;
375 }
376
377 entry = zmalloc<ust_error_accounting_entry>();
378 if (!entry) {
379 PERROR("Failed to allocate event notifier error acounting entry")
380 goto error;
381 }
382
383 urcu_ref_init(&entry->ref);
384 entry->uid = app->uid;
385 entry->nr_counter_cpu_fds = lttng_ust_ctl_get_nr_cpu_per_counter();
386
387 cpu_counter_fds = calloc<int>(entry->nr_counter_cpu_fds);
388 if (!cpu_counter_fds) {
389 PERROR("Failed to allocate event notifier error counter file descriptors array: application uid = %d, application name = '%s', pid = %d, allocation size = %zu",
390 (int) app->uid,
391 app->name,
392 (int) app->pid,
393 entry->nr_counter_cpu_fds * sizeof(*cpu_counter_fds));
394 goto error_counter_cpu_fds_alloc;
395 }
396
397 /* Initialize to an invalid fd value to closes fds in case of error. */
398 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
399 cpu_counter_fds[i] = -1;
400 }
401
402 cpu_counters = calloc<lttng_ust_abi_object_data *>(entry->nr_counter_cpu_fds);
403 if (!cpu_counters) {
404 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",
405 (int) app->uid,
406 app->name,
407 (int) app->pid,
408 entry->nr_counter_cpu_fds * sizeof(struct lttng_ust_abi_object_data *));
409 goto error_counter_cpus_alloc;
410 }
411
412 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
413 cpu_counter_fds[i] = shm_create_anonymous("event-notifier-error-accounting");
414 if (cpu_counter_fds[i] == -1) {
415 ERR("Failed to create event notifier error accounting shared memory for application user: application uid = %d, pid = %d, application name = '%s'",
416 (int) app->uid,
417 (int) app->pid,
418 app->name);
419 goto error_shm_alloc;
420 }
421 }
422
423 /*
424 * Ownership of the file descriptors transferred to the ustctl object.
425 */
426 daemon_counter = lttng_ust_ctl_create_counter(1,
427 &dimension,
428 0,
429 -1,
430 entry->nr_counter_cpu_fds,
431 cpu_counter_fds,
432 LTTNG_UST_CTL_COUNTER_BITNESS_32,
433 LTTNG_UST_CTL_COUNTER_ARITHMETIC_MODULAR,
434 LTTNG_UST_CTL_COUNTER_ALLOC_PER_CPU,
435 false);
436 if (!daemon_counter) {
437 goto error_create_daemon_counter;
438 }
439
440 ret = lttng_ust_ctl_create_counter_data(daemon_counter, &counter);
441 if (ret) {
442 ERR("Failed to create userspace tracer counter data for application user: uid = %d, pid = %d, application name = '%s'",
443 (int) app->uid,
444 (int) app->pid,
445 app->name);
446 goto error_create_counter_data;
447 }
448
449 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
450 ret = lttng_ust_ctl_create_counter_cpu_data(daemon_counter, i, &cpu_counters[i]);
451 if (ret) {
452 ERR("Failed to create userspace tracer counter cpu data for application user: uid = %d, pid = %d, application name = '%s'",
453 (int) app->uid,
454 (int) app->pid,
455 app->name);
456 goto error_create_counter_cpu_data;
457 }
458 }
459
460 entry->daemon_counter = daemon_counter;
461 entry->counter = counter;
462 entry->cpu_counters = cpu_counters;
463
464 lttng_ht_node_init_u64(&entry->node, entry->uid);
465 lttng_ht_add_unique_u64(error_counter_uid_ht, &entry->node);
466
467 goto end;
468
469error_create_counter_cpu_data:
470 /* Teardown any allocated cpu counters. */
471 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
472 if (!cpu_counters[i]) {
473 /*
474 * Early-exit when error occurred before all cpu
475 * counters could be initialized.
476 */
477 break;
478 }
479
480 lttng_ust_ctl_release_object(-1, cpu_counters[i]);
481 free(cpu_counters[i]);
482 }
483
484 lttng_ust_ctl_release_object(-1, entry->counter);
485 free(entry->counter);
486error_create_counter_data:
487 lttng_ust_ctl_destroy_counter(daemon_counter);
488error_create_daemon_counter:
489error_shm_alloc:
490 /* Error occurred before per-cpu SHMs were handed-off to ustctl. */
491 if (cpu_counter_fds) {
492 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
493 if (cpu_counter_fds[i] < 0) {
494 /*
495 * Early-exit when error occurred before all cpu
496 * counter shm fds could be initialized.
497 */
498 break;
499 }
500
501 ret = close(cpu_counter_fds[i]);
502 if (ret) {
503 PERROR("Failed to close error counter per-CPU shm file descriptor: fd = %d",
504 cpu_counter_fds[i]);
505 }
506 }
507 }
508
509 free(cpu_counters);
510error_counter_cpus_alloc:
511error_counter_cpu_fds_alloc:
512 free(entry);
513error:
514 entry = nullptr;
515end:
516 free(cpu_counter_fds);
517 return entry;
518}
519
520static enum event_notifier_error_accounting_status
521send_counter_data_to_ust(struct ust_app *app, struct lttng_ust_abi_object_data *new_counter)
522{
523 int ret;
524 enum event_notifier_error_accounting_status status;
525
526 /* Attach counter to trigger group. */
527 pthread_mutex_lock(&app->sock_lock);
528 ret = lttng_ust_ctl_send_counter_data_to_ust(
529 app->sock, app->event_notifier_group.object->handle, new_counter);
530 pthread_mutex_unlock(&app->sock_lock);
531 if (ret < 0) {
532 if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
533 ERR("Failed to send counter data to application: application name = '%s', pid = %d, ret = %d",
534 app->name,
535 app->pid,
536 ret);
537 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
538 } else {
539 DBG3("Failed to send counter data to application (application is dead): application name = '%s', pid = %d, ret = %d",
540 app->name,
541 app->pid,
542 ret);
543 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD;
544 }
545
546 goto end;
547 }
548
549 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
550end:
551 return status;
552}
553
554static enum event_notifier_error_accounting_status
555send_counter_cpu_data_to_ust(struct ust_app *app,
556 struct lttng_ust_abi_object_data *counter,
557 struct lttng_ust_abi_object_data *counter_cpu)
558{
559 int ret;
560 enum event_notifier_error_accounting_status status;
561
562 pthread_mutex_lock(&app->sock_lock);
563 ret = lttng_ust_ctl_send_counter_cpu_data_to_ust(app->sock, counter, counter_cpu);
564 pthread_mutex_unlock(&app->sock_lock);
565 if (ret < 0) {
566 if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
567 ERR("Failed to send counter CPU data to application: application name = '%s', pid = %d, ret = %d",
568 app->name,
569 app->pid,
570 ret);
571 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
572 } else {
573 DBG3("Failed to send counter CPU data to application: application name = '%s', pid = %d, ret = %d",
574 app->name,
575 app->pid,
576 ret);
577 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD;
578 }
579
580 goto end;
581 }
582
583 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
584end:
585 return status;
586}
587
588enum event_notifier_error_accounting_status
589event_notifier_error_accounting_register_app(struct ust_app *app)
590{
591 int ret;
592 uint64_t i;
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;
597 lttng::urcu::read_lock_guard read_lock;
598
599 if (!ust_app_supports_counters(app)) {
600 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_UNSUPPORTED;
601 goto end;
602 }
603
604 /*
605 * Check if we already have a error counter for the user id of this
606 * app. If not, create one.
607 */
608 entry = ust_error_accounting_entry_find(error_counter_uid_ht, app);
609 if (entry == nullptr) {
610 /*
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.
614 */
615 pthread_mutex_lock(&the_event_notifier_counter.lock);
616
617 entry = ust_error_accounting_entry_create(app);
618 if (!entry) {
619 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
620 pthread_mutex_unlock(&the_event_notifier_counter.lock);
621 goto error_creating_entry;
622 }
623
624 /*
625 * We just created a new UID entry, If there are event
626 * notifiers already registered, take one reference on their
627 * behalf.
628 */
629 if (the_event_notifier_counter.count > 0) {
630 ust_error_accounting_entry_get(entry);
631 }
632
633 pthread_mutex_unlock(&the_event_notifier_counter.lock);
634 }
635
636 /* Duplicate counter object data. */
637 ret = lttng_ust_ctl_duplicate_ust_object_data(&new_counter, entry->counter);
638 if (ret) {
639 ERR("Failed to duplicate event notifier error accounting counter for application user: application uid = %d, pid = %d, application name = '%s'",
640 (int) app->uid,
641 (int) app->pid,
642 app->name);
643 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
644 goto error_duplicate_counter;
645 }
646
647 status = send_counter_data_to_ust(app, new_counter);
648 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
649 if (status == EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD) {
650 goto error_send_counter_data;
651 }
652
653 ERR("Failed to send counter data to application tracer: status = %s, application uid = %d, pid = %d, application name = '%s'",
654 error_accounting_status_str(status),
655 (int) app->uid,
656 (int) app->pid,
657 app->name);
658 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
659 goto error_send_counter_data;
660 }
661
662 cpu_counters = calloc<lttng_ust_abi_object_data *>(entry->nr_counter_cpu_fds);
663 if (!cpu_counters) {
664 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",
665 (int) app->uid,
666 app->name,
667 (int) app->pid,
668 entry->nr_counter_cpu_fds * sizeof(**cpu_counters));
669 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
670 goto error_allocate_cpu_counters;
671 }
672
673 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
674 struct lttng_ust_abi_object_data *new_counter_cpu = nullptr;
675
676 ret = lttng_ust_ctl_duplicate_ust_object_data(&new_counter_cpu,
677 entry->cpu_counters[i]);
678 if (ret) {
679 ERR("Failed to duplicate userspace tracer counter cpu data for application user: uid = %d, pid = %d, application name = '%s'",
680 (int) app->uid,
681 (int) app->pid,
682 app->name);
683 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
684 goto error_duplicate_cpu_counter;
685 }
686
687 cpu_counters[i] = new_counter_cpu;
688
689 status = send_counter_cpu_data_to_ust(app, new_counter, new_counter_cpu);
690 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
691 if (status == EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD) {
692 goto error_send_cpu_counter_data;
693 }
694
695 ERR("Failed to send counter cpu data to application tracer: status = %s, application uid = %d, pid = %d, application name = '%s'",
696 error_accounting_status_str(status),
697 (int) app->uid,
698 (int) app->pid,
699 app->name);
700 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
701 goto error_send_cpu_counter_data;
702 }
703 }
704
705 app->event_notifier_group.counter = new_counter;
706 new_counter = nullptr;
707 app->event_notifier_group.nr_counter_cpu = entry->nr_counter_cpu_fds;
708 app->event_notifier_group.counter_cpu = cpu_counters;
709 cpu_counters = nullptr;
710 goto end;
711
712error_send_cpu_counter_data:
713error_duplicate_cpu_counter:
714 /* Teardown any duplicated cpu counters. */
715 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
716 if (!cpu_counters[i]) {
717 /*
718 * Early-exit when error occurred before all cpu
719 * counters could be initialized.
720 */
721 break;
722 }
723
724 lttng_ust_ctl_release_object(-1, cpu_counters[i]);
725 free(cpu_counters[i]);
726 }
727
728 free(cpu_counters);
729
730error_allocate_cpu_counters:
731error_send_counter_data:
732 lttng_ust_ctl_release_object(-1, new_counter);
733 free(new_counter);
734error_duplicate_counter:
735 ust_error_accounting_entry_put(entry);
736error_creating_entry:
737 app->event_notifier_group.counter = nullptr;
738end:
739 return status;
740}
741
742enum event_notifier_error_accounting_status
743event_notifier_error_accounting_unregister_app(struct ust_app *app)
744{
745 enum event_notifier_error_accounting_status status;
746 struct ust_error_accounting_entry *entry;
747 int i;
748
749 lttng::urcu::read_lock_guard read_lock;
750
751 /* If an error occurred during app registration no entry was created. */
752 if (!app->event_notifier_group.counter) {
753 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
754 goto end;
755 }
756
757 entry = ust_error_accounting_entry_find(error_counter_uid_ht, app);
758 if (entry == nullptr) {
759 ERR("Failed to find event notitifier error accounting entry on application teardown: pid = %d, application name = '%s'",
760 app->pid,
761 app->name);
762 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
763 goto end;
764 } else {
765 /*
766 * Put the entry twice as we acquired a reference from the
767 * `ust_error_accounting_entry_find()` above.
768 */
769 ust_error_accounting_entry_put(entry);
770 ust_error_accounting_entry_put(entry);
771 }
772
773 for (i = 0; i < app->event_notifier_group.nr_counter_cpu; i++) {
774 lttng_ust_ctl_release_object(app->sock, app->event_notifier_group.counter_cpu[i]);
775 free(app->event_notifier_group.counter_cpu[i]);
776 }
777
778 free(app->event_notifier_group.counter_cpu);
779
780 lttng_ust_ctl_release_object(app->sock, app->event_notifier_group.counter);
781 free(app->event_notifier_group.counter);
782
783 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
784end:
785 return status;
786}
787
788static enum event_notifier_error_accounting_status
789event_notifier_error_accounting_ust_get_count(const struct lttng_trigger *trigger, uint64_t *count)
790{
791 struct lttng_ht_iter iter;
792 struct ust_error_accounting_entry *uid_entry;
793 uint64_t error_counter_index, global_sum = 0;
794 enum event_notifier_error_accounting_status status;
795 size_t dimension_indexes[1];
796 const uint64_t tracer_token = lttng_trigger_get_tracer_token(trigger);
797 uid_t trigger_owner_uid;
798 const char *trigger_name;
799
800 lttng::urcu::read_lock_guard read_lock;
801
802 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
803
804 status = get_error_counter_index_for_token(&ust_state, tracer_token, &error_counter_index);
805 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
806 ERR("Failed to retrieve index for tracer token: token = %" PRIu64
807 ", trigger name = '%s', trigger owner uid = %d, status = %s",
808 tracer_token,
809 trigger_name,
810 (int) trigger_owner_uid,
811 error_accounting_status_str(status));
812 goto end;
813 }
814
815 dimension_indexes[0] = error_counter_index;
816
817 /*
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.
823 */
824 cds_lfht_for_each_entry (error_counter_uid_ht->ht, &iter.iter, uid_entry, node.node) {
825 int ret;
826 int64_t local_value = 0;
827 bool overflow = false, underflow = false;
828
829 ret = lttng_ust_ctl_counter_aggregate(uid_entry->daemon_counter,
830 dimension_indexes,
831 &local_value,
832 &overflow,
833 &underflow);
834 if (ret || local_value < 0) {
835 if (ret) {
836 ERR("Failed to aggregate event notifier error counter values of trigger: trigger name = '%s', trigger owner uid = %d",
837 trigger_name,
838 (int) trigger_owner_uid);
839 } else if (local_value < 0) {
840 ERR("Negative event notifier error counter value encountered during aggregation: trigger name = '%s', trigger owner uid = %d, value = %" PRId64,
841 trigger_name,
842 (int) trigger_owner_uid,
843 local_value);
844 } else {
845 abort();
846 }
847
848 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
849 goto end;
850 }
851
852 /* Cast is safe as negative values are checked-for above. */
853 global_sum += (uint64_t) local_value;
854 }
855
856 *count = global_sum;
857 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
858
859end:
860 return status;
861}
862
863static enum event_notifier_error_accounting_status
864event_notifier_error_accounting_ust_clear(const struct lttng_trigger *trigger)
865{
866 struct lttng_ht_iter iter;
867 struct ust_error_accounting_entry *uid_entry;
868 uint64_t error_counter_index;
869 enum event_notifier_error_accounting_status status;
870 size_t dimension_index;
871 const uint64_t tracer_token = lttng_trigger_get_tracer_token(trigger);
872
873 lttng::urcu::read_lock_guard read_lock;
874
875 status = get_error_counter_index_for_token(&ust_state, tracer_token, &error_counter_index);
876 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
877 uid_t trigger_owner_uid;
878 const char *trigger_name;
879
880 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
881
882 ERR("Failed to retrieve index for tracer token: token = %" PRIu64
883 ", trigger name = '%s', trigger owner uid = %d, status = %s",
884 tracer_token,
885 trigger_name,
886 (int) trigger_owner_uid,
887 error_accounting_status_str(status));
888 goto end;
889 }
890
891 dimension_index = error_counter_index;
892
893 /*
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.
897 */
898 cds_lfht_for_each_entry (error_counter_uid_ht->ht, &iter.iter, uid_entry, node.node) {
899 const int ret =
900 lttng_ust_ctl_counter_clear(uid_entry->daemon_counter, &dimension_index);
901
902 if (ret) {
903 uid_t trigger_owner_uid;
904 const char *trigger_name;
905
906 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
907 ERR("Failed to clear event notifier counter value for trigger: counter uid = %d, trigger name = '%s', trigger owner uid = %d",
908 (int) uid_entry->node.key,
909 trigger_name,
910 (int) trigger_owner_uid);
911 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
912 goto end;
913 }
914 }
915
916 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
917end:
918 return status;
919}
920#endif /* HAVE_LIBLTTNG_UST_CTL */
921
922static enum event_notifier_error_accounting_status
923event_notifier_error_accounting_kernel_clear(const struct lttng_trigger *trigger)
924{
925 int ret;
926 uint64_t error_counter_index;
927 enum event_notifier_error_accounting_status status;
928 struct lttng_kernel_abi_counter_clear counter_clear = {};
929
930 status = get_error_counter_index_for_token(
931 &kernel_state, lttng_trigger_get_tracer_token(trigger), &error_counter_index);
932 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
933 uid_t trigger_owner_uid;
934 const char *trigger_name;
935
936 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
937
938 ERR("Failed to get event notifier error counter index: trigger owner uid = %d, trigger name = '%s', status = '%s'",
939 trigger_owner_uid,
940 trigger_name,
941 error_accounting_status_str(status));
942 goto end;
943 }
944
945 counter_clear.index.number_dimensions = 1;
946 counter_clear.index.dimension_indexes[0] = error_counter_index;
947
948 ret = kernctl_counter_clear(kernel_error_accounting_entry.error_counter_fd, &counter_clear);
949 if (ret) {
950 uid_t trigger_owner_uid;
951 const char *trigger_name;
952
953 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
954
955 ERR("Failed to clear kernel event notifier error counter: trigger owner uid = %d, trigger name = '%s'",
956 trigger_owner_uid,
957 trigger_name);
958 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
959 goto end;
960 }
961
962 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
963end:
964 return status;
965}
966
967enum event_notifier_error_accounting_status
968event_notifier_error_accounting_register_kernel(int kernel_event_notifier_group_fd)
969{
970 int error_counter_fd = -1, ret;
971 enum event_notifier_error_accounting_status status;
972 lttng_kernel_abi_counter_conf error_counter_conf = {
973 .arithmetic = LTTNG_KERNEL_ABI_COUNTER_ARITHMETIC_MODULAR,
974 .bitness = sizeof(void *) == sizeof(uint32_t) ?
975 LTTNG_KERNEL_ABI_COUNTER_BITNESS_32 :
976 LTTNG_KERNEL_ABI_COUNTER_BITNESS_64,
977 .number_dimensions = 1,
978 .global_sum_step = 0,
979 .dimensions = {},
980 .coalesce_hits = 0,
981 .padding = {},
982 };
983 error_counter_conf.dimensions[0].size = kernel_state.number_indices;
984 error_counter_conf.dimensions[0].has_underflow = false;
985 error_counter_conf.dimensions[0].has_overflow = false;
986
987 ret = kernctl_create_event_notifier_group_error_counter(kernel_event_notifier_group_fd,
988 &error_counter_conf);
989 if (ret < 0) {
990 PERROR("Failed to create event notifier group error counter through kernel ioctl: kernel_event_notifier_group_fd = %d",
991 kernel_event_notifier_group_fd);
992 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
993 goto error;
994 }
995
996 error_counter_fd = ret;
997
998 /* Prevent fd duplication after execlp(). */
999 ret = fcntl(error_counter_fd, F_SETFD, FD_CLOEXEC);
1000 if (ret < 0) {
1001 PERROR("Failed to set FD_CLOEXEC flag on event notifier error counter file descriptor: error_counter_fd = %d",
1002 error_counter_fd);
1003 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
1004 goto error;
1005 }
1006
1007 DBG("Created kernel event notifier group error counter: fd = %d", error_counter_fd);
1008
1009 kernel_error_accounting_entry.error_counter_fd = error_counter_fd;
1010 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1011
1012error:
1013 return status;
1014}
1015
1016static enum event_notifier_error_accounting_status create_error_counter_index_for_token(
1017 struct error_accounting_state *state, uint64_t tracer_token, uint64_t *error_counter_index)
1018{
1019 struct index_ht_entry *index_entry;
1020 enum lttng_index_allocator_status index_alloc_status;
1021 uint64_t local_error_counter_index;
1022 enum event_notifier_error_accounting_status status;
1023
1024 LTTNG_ASSERT(state);
1025
1026 /* Allocate a new index for that counter. */
1027 index_alloc_status =
1028 lttng_index_allocator_alloc(state->index_allocator, &local_error_counter_index);
1029 switch (index_alloc_status) {
1030 case LTTNG_INDEX_ALLOCATOR_STATUS_EMPTY:
1031 DBG("No indices left in the configured event notifier error counter: "
1032 "number-of-indices = %" PRIu64,
1033 lttng_index_allocator_get_index_count(state->index_allocator));
1034 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE;
1035 goto end;
1036 case LTTNG_INDEX_ALLOCATOR_STATUS_OK:
1037 break;
1038 default:
1039 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
1040 goto end;
1041 }
1042
1043 index_entry = zmalloc<index_ht_entry>();
1044 if (index_entry == nullptr) {
1045 PERROR("Failed to allocate event notifier error counter hash table entry");
1046 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
1047 goto end;
1048 }
1049
1050 index_entry->error_counter_index = local_error_counter_index;
1051 lttng_ht_node_init_u64(&index_entry->node, tracer_token);
1052 lttng_ht_add_unique_u64(state->indices_ht, &index_entry->node);
1053
1054 DBG("Allocated error counter index for tracer token: tracer token = %" PRIu64
1055 ", index = %" PRIu64,
1056 tracer_token,
1057 local_error_counter_index);
1058 *error_counter_index = local_error_counter_index;
1059 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1060end:
1061 return status;
1062}
1063
1064enum event_notifier_error_accounting_status
1065event_notifier_error_accounting_register_event_notifier(const struct lttng_trigger *trigger,
1066 uint64_t *error_counter_index)
1067{
1068 enum event_notifier_error_accounting_status status;
1069 uint64_t local_error_counter_index;
1070 struct error_accounting_state *state;
1071
1072 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1073 case LTTNG_DOMAIN_KERNEL:
1074 state = &kernel_state;
1075 break;
1076 case LTTNG_DOMAIN_UST:
1077 case LTTNG_DOMAIN_PYTHON:
1078 case LTTNG_DOMAIN_JUL:
1079 case LTTNG_DOMAIN_LOG4J:
1080 state = &ust_state;
1081 break;
1082 default:
1083 abort();
1084 }
1085
1086 /*
1087 * Check if this event notifier already has a error counter index
1088 * assigned.
1089 */
1090 status = get_error_counter_index_for_token(
1091 state, lttng_trigger_get_tracer_token(trigger), &local_error_counter_index);
1092 switch (status) {
1093 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND:
1094 {
1095 uid_t trigger_owner_uid;
1096 const char *trigger_name;
1097
1098 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
1099
1100 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,
1101 trigger_name,
1102 trigger_owner_uid,
1103 lttng_trigger_get_tracer_token(trigger));
1104
1105 status = create_error_counter_index_for_token(
1106 state, lttng_trigger_get_tracer_token(trigger), &local_error_counter_index);
1107 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
1108 ERR("Error creating index for token: status = %s, trigger name = '%s', trigger owner uid = %d",
1109 error_accounting_status_str(status),
1110 trigger_name,
1111 trigger_owner_uid);
1112 goto end;
1113 }
1114 }
1115 /* fall-through. */
1116 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK:
1117 *error_counter_index = local_error_counter_index;
1118 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1119 break;
1120 default:
1121 break;
1122 }
1123
1124#ifdef HAVE_LIBLTTNG_UST_CTL
1125 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1126 case LTTNG_DOMAIN_UST:
1127 case LTTNG_DOMAIN_PYTHON:
1128 case LTTNG_DOMAIN_JUL:
1129 case LTTNG_DOMAIN_LOG4J:
1130 pthread_mutex_lock(&the_event_notifier_counter.lock);
1131 the_event_notifier_counter.count++;
1132 if (the_event_notifier_counter.count == 1) {
1133 /*
1134 * On the first event notifier, we get a reference to
1135 * every existing UID entries. This ensures that the
1136 * entries are kept around if there are still
1137 * registered event notifiers but no apps.
1138 */
1139 get_ref_all_ust_error_accounting_entry();
1140 }
1141 pthread_mutex_unlock(&the_event_notifier_counter.lock);
1142 break;
1143 default:
1144 break;
1145 }
1146#endif /* HAVE_LIBLTTNG_UST_CTL */
1147
1148end:
1149 return status;
1150}
1151
1152static enum event_notifier_error_accounting_status
1153event_notifier_error_accounting_kernel_get_count(const struct lttng_trigger *trigger,
1154 uint64_t *count)
1155{
1156 struct lttng_kernel_abi_counter_aggregate counter_aggregate = {};
1157 enum event_notifier_error_accounting_status status;
1158 uint64_t error_counter_index;
1159 int ret;
1160
1161 status = get_error_counter_index_for_token(
1162 &kernel_state, lttng_trigger_get_tracer_token(trigger), &error_counter_index);
1163 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
1164 ERR("Error getting index for token: status=%s",
1165 error_accounting_status_str(status));
1166 goto end;
1167 }
1168
1169 counter_aggregate.index.number_dimensions = 1;
1170 counter_aggregate.index.dimension_indexes[0] = error_counter_index;
1171
1172 LTTNG_ASSERT(kernel_error_accounting_entry.error_counter_fd);
1173
1174 ret = kernctl_counter_get_aggregate_value(kernel_error_accounting_entry.error_counter_fd,
1175 &counter_aggregate);
1176 if (ret || counter_aggregate.value.value < 0) {
1177 uid_t trigger_owner_uid;
1178 const char *trigger_name;
1179
1180 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
1181
1182 if (counter_aggregate.value.value < 0) {
1183 ERR("Invalid negative event notifier error counter value: trigger owner = %d, trigger name = '%s', value = %" PRId64,
1184 trigger_owner_uid,
1185 trigger_name,
1186 counter_aggregate.value.value);
1187 } else {
1188 ERR("Failed to getting event notifier error count: trigger owner = %d, trigger name = '%s', ret = %d",
1189 trigger_owner_uid,
1190 trigger_name,
1191 ret);
1192 }
1193
1194 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
1195 goto end;
1196 }
1197
1198 /* Error count can't be negative. */
1199 LTTNG_ASSERT(counter_aggregate.value.value >= 0);
1200 *count = (uint64_t) counter_aggregate.value.value;
1201
1202 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1203
1204end:
1205 return status;
1206}
1207
1208enum event_notifier_error_accounting_status
1209event_notifier_error_accounting_get_count(const struct lttng_trigger *trigger, uint64_t *count)
1210{
1211 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1212 case LTTNG_DOMAIN_KERNEL:
1213 return event_notifier_error_accounting_kernel_get_count(trigger, count);
1214 case LTTNG_DOMAIN_UST:
1215 case LTTNG_DOMAIN_PYTHON:
1216 case LTTNG_DOMAIN_JUL:
1217 case LTTNG_DOMAIN_LOG4J:
1218#ifdef HAVE_LIBLTTNG_UST_CTL
1219 return event_notifier_error_accounting_ust_get_count(trigger, count);
1220#else
1221 *count = 0;
1222 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1223#endif /* HAVE_LIBLTTNG_UST_CTL */
1224 default:
1225 abort();
1226 }
1227}
1228
1229static enum event_notifier_error_accounting_status
1230event_notifier_error_accounting_clear(const struct lttng_trigger *trigger)
1231{
1232 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1233 case LTTNG_DOMAIN_KERNEL:
1234 return event_notifier_error_accounting_kernel_clear(trigger);
1235 case LTTNG_DOMAIN_UST:
1236 case LTTNG_DOMAIN_PYTHON:
1237 case LTTNG_DOMAIN_JUL:
1238 case LTTNG_DOMAIN_LOG4J:
1239#ifdef HAVE_LIBLTTNG_UST_CTL
1240 return event_notifier_error_accounting_ust_clear(trigger);
1241#else
1242 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1243#endif /* HAVE_LIBLTTNG_UST_CTL */
1244 default:
1245 abort();
1246 }
1247}
1248
1249static void free_index_ht_entry(struct rcu_head *head)
1250{
1251 struct index_ht_entry *entry = caa_container_of(head, struct index_ht_entry, rcu_head);
1252
1253 free(entry);
1254}
1255
1256void event_notifier_error_accounting_unregister_event_notifier(const struct lttng_trigger *trigger)
1257{
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;
1263
1264 lttng::urcu::read_lock_guard read_lock;
1265
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));
1271 goto end;
1272 }
1273
1274 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1275 case LTTNG_DOMAIN_KERNEL:
1276 state = &kernel_state;
1277 break;
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 state = &ust_state;
1284
1285 pthread_mutex_lock(&the_event_notifier_counter.lock);
1286 the_event_notifier_counter.count--;
1287 if (the_event_notifier_counter.count == 0) {
1288 /*
1289 * When unregistering the last event notifier, put one
1290 * reference to every uid entries on the behalf of all
1291 * event notifiers.
1292 */
1293 put_ref_all_ust_error_accounting_entry();
1294 }
1295
1296 pthread_mutex_unlock(&the_event_notifier_counter.lock);
1297
1298 break;
1299#endif /* HAVE_LIBLTTNG_UST_CTL */
1300 default:
1301 abort();
1302 }
1303
1304 lttng_ht_lookup(state->indices_ht, &tracer_token, &iter);
1305 node = lttng_ht_iter_get_node_u64(&iter);
1306 if (node) {
1307 int del_ret;
1308 struct index_ht_entry *index_entry =
1309 lttng::utils::container_of(node, &index_ht_entry::node);
1310 enum lttng_index_allocator_status index_alloc_status;
1311
1312 index_alloc_status = lttng_index_allocator_release(
1313 state->index_allocator, index_entry->error_counter_index);
1314 if (index_alloc_status != LTTNG_INDEX_ALLOCATOR_STATUS_OK) {
1315 uid_t trigger_owner_uid;
1316 const char *trigger_name;
1317
1318 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
1319
1320 ERR("Failed to release event notifier error counter index: index = %" PRIu64
1321 ", trigger name = '%s', trigger owner uid = %d",
1322 index_entry->error_counter_index,
1323 trigger_name,
1324 (int) trigger_owner_uid);
1325 /* Don't exit, perform the rest of the clean-up. */
1326 }
1327
1328 del_ret = lttng_ht_del(state->indices_ht, &iter);
1329 LTTNG_ASSERT(!del_ret);
1330 call_rcu(&index_entry->rcu_head, free_index_ht_entry);
1331 }
1332end:
1333 return;
1334}
1335
1336void event_notifier_error_accounting_fini()
1337{
1338 if (kernel_error_accounting_entry.error_counter_fd) {
1339 const int ret = close(kernel_error_accounting_entry.error_counter_fd);
1340
1341 if (ret) {
1342 PERROR("Failed to close kernel event notifier error counter");
1343 }
1344 }
1345
1346 lttng_ht_destroy(error_counter_uid_ht);
1347
1348 fini_error_accounting_state(&kernel_state);
1349 fini_error_accounting_state(&ust_state);
1350}
This page took 0.027304 seconds and 4 git commands to generate.