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