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