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