Fix: tests: fix unused-but-set warning in test_fd_tracker.c
[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);
a0377dfe 90 LTTNG_ASSERT(trigger_status == LTTNG_TRIGGER_STATUS_OK);
533a90fb
FD
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
a0377dfe 222 LTTNG_ASSERT(state);
761ffce2
FD
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{
a0377dfe 254 LTTNG_ASSERT(state);
761ffce2
FD
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
783db316
MD
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
761ffce2 390 entry = zmalloc(sizeof(struct ust_error_accounting_entry));
533a90fb
FD
391 if (!entry) {
392 PERROR("Failed to allocate event notifier error acounting entry")
393 goto error;
394 }
395
a5a21280 396 urcu_ref_init(&entry->ref);
761ffce2 397 entry->uid = app->uid;
b623cb6a 398 entry->nr_counter_cpu_fds = lttng_ust_ctl_get_nr_cpu_per_counter();
761ffce2 399
533a90fb
FD
400 cpu_counter_fds = 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));
533a90fb
FD
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
74f286be 413 cpu_counters = zmalloc(entry->nr_counter_cpu_fds * sizeof(struct lttng_ust_abi_object_data *));
533a90fb
FD
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,
74f286be 417 entry->nr_counter_cpu_fds * sizeof(struct lttng_ust_abi_object_data *));
533a90fb
FD
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 */
b623cb6a 433 daemon_counter = lttng_ust_ctl_create_counter(1, &dimension, 0, -1,
533a90fb 434 entry->nr_counter_cpu_fds, cpu_counter_fds,
b623cb6a
MJ
435 LTTNG_UST_CTL_COUNTER_BITNESS_32,
436 LTTNG_UST_CTL_COUNTER_ARITHMETIC_MODULAR,
437 LTTNG_UST_CTL_COUNTER_ALLOC_PER_CPU,
533a90fb
FD
438 false);
439 if (!daemon_counter) {
440 goto error_create_daemon_counter;
441 }
442
b623cb6a 443 ret = lttng_ust_ctl_create_counter_data(daemon_counter, &counter);
533a90fb
FD
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++) {
b623cb6a 451 ret = lttng_ust_ctl_create_counter_cpu_data(daemon_counter, i,
533a90fb
FD
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
a5a21280 465 lttng_ht_node_init_u64(&entry->node, entry->uid);
533a90fb
FD
466 lttng_ht_add_unique_u64(error_counter_uid_ht, &entry->node);
467
468 goto end;
469
470error_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
b623cb6a 481 lttng_ust_ctl_release_object(-1, cpu_counters[i]);
533a90fb
FD
482 free(cpu_counters[i]);
483 }
484
b623cb6a 485 lttng_ust_ctl_release_object(-1, entry->counter);
533a90fb
FD
486 free(entry->counter);
487error_create_counter_data:
b623cb6a 488 lttng_ust_ctl_destroy_counter(daemon_counter);
533a90fb
FD
489error_create_daemon_counter:
490error_shm_alloc:
8f0646a0 491 /* Error occurred before per-cpu SHMs were handed-off to ustctl. */
533a90fb
FD
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) {
a5a21280
FD
504 PERROR("Failed to close error counter per-CPU shm file descriptor: fd = %d",
505 cpu_counter_fds[i]);
533a90fb
FD
506 }
507 }
508 }
509
510 free(cpu_counters);
511error_counter_cpus_alloc:
512error_counter_cpu_fds_alloc:
513 free(entry);
514error:
515 entry = NULL;
516end:
517 free(cpu_counter_fds);
518 return entry;
519}
520
521static
522enum 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);
b623cb6a 531 ret = lttng_ust_ctl_send_counter_data_to_ust(app->sock,
533a90fb
FD
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;
549end:
550 return status;
551}
552
553static
554enum 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);
b623cb6a 563 ret = lttng_ust_ctl_send_counter_cpu_data_to_ust(app->sock,
533a90fb
FD
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;
581end:
582 return status;
583}
584
585enum event_notifier_error_accounting_status
586event_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;
761ffce2 591 struct ust_error_accounting_entry *entry;
533a90fb
FD
592 enum event_notifier_error_accounting_status status;
593 struct lttng_ust_abi_object_data **cpu_counters;
594
783db316
MD
595 if (!ust_app_supports_counters(app)) {
596 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_UNSUPPORTED;
597 goto end;
598 }
599
533a90fb
FD
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();
a5a21280 605 entry = ust_error_accounting_entry_find(error_counter_uid_ht, app);
533a90fb 606 if (entry == NULL) {
a5a21280
FD
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(error_counter_uid_ht,
615 app);
533a90fb
FD
616 if (!entry) {
617 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
a5a21280
FD
618 pthread_mutex_unlock(&the_event_notifier_counter.lock);
619 goto error_creating_entry;
620 }
621
622 /*
623 * We just created a new UID entry, If there are event
624 * notifiers already registered, take one reference on their
625 * behalf.
626 */
627 if (the_event_notifier_counter.count > 0) {
628 ust_error_accounting_entry_get(entry);
533a90fb 629 }
a5a21280
FD
630
631 pthread_mutex_unlock(&the_event_notifier_counter.lock);
533a90fb
FD
632 }
633
634 /* Duplicate counter object data. */
b623cb6a 635 ret = lttng_ust_ctl_duplicate_ust_object_data(&new_counter,
533a90fb
FD
636 entry->counter);
637 if (ret) {
638 ERR("Failed to duplicate event notifier error accounting counter for application user: application uid = %d, pid = %d, application name = '%s'",
639 (int) app->uid, (int) app->pid, app->name);
640 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
a5a21280 641 goto error_duplicate_counter;
533a90fb
FD
642 }
643
644 status = send_counter_data_to_ust(app, new_counter);
645 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
cd9c532c
FD
646 if (status == EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD) {
647 goto error_send_counter_data;
648 }
649
533a90fb
FD
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, (int) app->pid, app->name);
653 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
654 goto error_send_counter_data;
655 }
656
477b83a4 657 cpu_counters = zmalloc(entry->nr_counter_cpu_fds * sizeof(struct lttng_ust_abi_object_data *));
533a90fb
FD
658 if (!cpu_counters) {
659 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",
660 (int) app->uid, app->name, (int) app->pid,
661 entry->nr_counter_cpu_fds * sizeof(**cpu_counters));
662 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
663 goto error_allocate_cpu_counters;
664 }
665
666 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
667 struct lttng_ust_abi_object_data *new_counter_cpu = NULL;
668
b623cb6a 669 ret = lttng_ust_ctl_duplicate_ust_object_data(&new_counter_cpu,
533a90fb
FD
670 entry->cpu_counters[i]);
671 if (ret) {
672 ERR("Failed to duplicate userspace tracer counter cpu data for application user: uid = %d, pid = %d, application name = '%s'",
673 (int) app->uid, (int) app->pid,
674 app->name);
675 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
676 goto error_duplicate_cpu_counter;
677 }
678
679 cpu_counters[i] = new_counter_cpu;
680
681 status = send_counter_cpu_data_to_ust(app, new_counter,
682 new_counter_cpu);
683 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
cd9c532c
FD
684 if (status == EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD) {
685 goto error_send_cpu_counter_data;
686 }
687
533a90fb
FD
688 ERR("Failed to send counter cpu data to application tracer: status = %s, application uid = %d, pid = %d, application name = '%s'",
689 error_accounting_status_str(status),
690 (int) app->uid, (int) app->pid,
691 app->name);
692 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
693 goto error_send_cpu_counter_data;
694 }
695 }
696
697 app->event_notifier_group.counter = new_counter;
698 new_counter = NULL;
699 app->event_notifier_group.nr_counter_cpu = entry->nr_counter_cpu_fds;
700 app->event_notifier_group.counter_cpu = cpu_counters;
701 cpu_counters = NULL;
783db316 702 goto end_unlock;
533a90fb 703
533a90fb
FD
704error_send_cpu_counter_data:
705error_duplicate_cpu_counter:
706 /* Teardown any duplicated cpu counters. */
707 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
708 if (!cpu_counters[i]) {
709 /*
710 * Early-exit when error occurred before all cpu
711 * counters could be initialized.
712 */
713 break;
714 }
715
b623cb6a 716 lttng_ust_ctl_release_object(-1, cpu_counters[i]);
533a90fb
FD
717 free(cpu_counters[i]);
718 }
719
a55f8ad1
JG
720 free(cpu_counters);
721
5d650dcd 722error_allocate_cpu_counters:
533a90fb 723error_send_counter_data:
b623cb6a 724 lttng_ust_ctl_release_object(-1, new_counter);
533a90fb 725 free(new_counter);
a5a21280
FD
726error_duplicate_counter:
727 ust_error_accounting_entry_put(entry);
728error_creating_entry:
729 app->event_notifier_group.counter = NULL;
783db316 730end_unlock:
533a90fb 731 rcu_read_unlock();
783db316 732end:
533a90fb
FD
733 return status;
734}
735
736enum event_notifier_error_accounting_status
737event_notifier_error_accounting_unregister_app(struct ust_app *app)
738{
739 enum event_notifier_error_accounting_status status;
761ffce2 740 struct ust_error_accounting_entry *entry;
533a90fb
FD
741 int i;
742
743 rcu_read_lock();
a5a21280
FD
744
745 /* If an error occurred during app registration no entry was created. */
746 if (!app->event_notifier_group.counter) {
747 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
748 goto end;
749 }
750
751 entry = ust_error_accounting_entry_find(error_counter_uid_ht, app);
533a90fb
FD
752 if (entry == NULL) {
753 ERR("Failed to find event notitifier error accounting entry on application teardown: pid = %d, application name = '%s'",
754 app->pid, app->name);
755 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
756 goto end;
a5a21280
FD
757 } else {
758 /*
759 * Put the entry twice as we acquired a reference from the
760 * `ust_error_accounting_entry_find()` above.
761 */
762 ust_error_accounting_entry_put(entry);
763 ust_error_accounting_entry_put(entry);
533a90fb
FD
764 }
765
766 for (i = 0; i < app->event_notifier_group.nr_counter_cpu; i++) {
b623cb6a 767 lttng_ust_ctl_release_object(app->sock,
533a90fb
FD
768 app->event_notifier_group.counter_cpu[i]);
769 free(app->event_notifier_group.counter_cpu[i]);
770 }
771
772 free(app->event_notifier_group.counter_cpu);
773
b623cb6a 774 lttng_ust_ctl_release_object(app->sock, app->event_notifier_group.counter);
533a90fb
FD
775 free(app->event_notifier_group.counter);
776
777 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
778end:
779 rcu_read_unlock();
780 return status;
781}
782
783static
784enum event_notifier_error_accounting_status
785event_notifier_error_accounting_ust_get_count(
786 const struct lttng_trigger *trigger, uint64_t *count)
787{
788 struct lttng_ht_iter iter;
761ffce2 789 struct ust_error_accounting_entry *uid_entry;
533a90fb
FD
790 uint64_t error_counter_index, global_sum = 0;
791 enum event_notifier_error_accounting_status status;
792 size_t dimension_indexes[1];
793 const uint64_t tracer_token = lttng_trigger_get_tracer_token(trigger);
761ffce2
FD
794 uid_t trigger_owner_uid;
795 const char *trigger_name;
533a90fb 796
533a90fb
FD
797
798 rcu_read_lock();
799
761ffce2
FD
800 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
801
a5a21280 802 status = get_error_counter_index_for_token(&ust_state, tracer_token,
533a90fb
FD
803 &error_counter_index);
804 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
533a90fb
FD
805
806 ERR("Failed to retrieve index for tracer token: token = %" PRIu64 ", trigger name = '%s', trigger owner uid = %d, status = %s",
807 tracer_token, trigger_name,
808 (int) trigger_owner_uid,
809 error_accounting_status_str(status));
810 goto end;
811 }
812
813 dimension_indexes[0] = error_counter_index;
814
761ffce2
FD
815 /*
816 * Iterate over all the UID entries.
817 * We aggregate the value of all uid entries regardless of if the uid
818 * matches the trigger's uid because a user that is allowed to register
819 * a trigger to a given sessiond is also allowed to create an event
820 * notifier on all apps that this sessiond is aware of.
821 */
533a90fb
FD
822 cds_lfht_for_each_entry(error_counter_uid_ht->ht, &iter.iter,
823 uid_entry, node.node) {
824 int ret;
825 int64_t local_value = 0;
826 bool overflow = false, underflow = false;
827
b623cb6a 828 ret = lttng_ust_ctl_counter_aggregate(uid_entry->daemon_counter,
533a90fb
FD
829 dimension_indexes, &local_value, &overflow,
830 &underflow);
831 if (ret || local_value < 0) {
533a90fb
FD
832 if (ret) {
833 ERR("Failed to aggregate event notifier error counter values of trigger: trigger name = '%s', trigger owner uid = %d",
834 trigger_name,
835 (int) trigger_owner_uid);
836 } else if (local_value < 0) {
837 ERR("Negative event notifier error counter value encountered during aggregation: trigger name = '%s', trigger owner uid = %d, value = %" PRId64,
838 trigger_name,
839 (int) trigger_owner_uid,
840 local_value);
841 } else {
842 abort();
843 }
844
845 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
846 goto end;
847 }
848
849 /* Cast is safe as negative values are checked-for above. */
850 global_sum += (uint64_t) local_value;
533a90fb
FD
851 }
852
853 *count = global_sum;
854 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
855
856end:
857 rcu_read_unlock();
858 return status;
859}
860
861static
862enum event_notifier_error_accounting_status event_notifier_error_accounting_ust_clear(
863 const struct lttng_trigger *trigger)
864{
865 struct lttng_ht_iter iter;
761ffce2 866 struct ust_error_accounting_entry *uid_entry;
533a90fb
FD
867 uint64_t error_counter_index;
868 enum event_notifier_error_accounting_status status;
869 size_t dimension_index;
870 const uint64_t tracer_token = lttng_trigger_get_tracer_token(trigger);
871
533a90fb 872 rcu_read_lock();
a5a21280 873 status = get_error_counter_index_for_token(&ust_state, tracer_token,
533a90fb
FD
874 &error_counter_index);
875 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
876 uid_t trigger_owner_uid;
877 const char *trigger_name;
878
879 get_trigger_info_for_log(trigger, &trigger_name,
880 &trigger_owner_uid);
881
882 ERR("Failed to retrieve index for tracer token: token = %" PRIu64 ", trigger name = '%s', trigger owner uid = %d, status = %s",
883 tracer_token, trigger_name,
884 (int) trigger_owner_uid,
885 error_accounting_status_str(status));
886 goto end;
887 }
888
889 dimension_index = error_counter_index;
890
a5a21280
FD
891 /*
892 * Go over all error counters (ignoring uid) as a trigger (and trigger
893 * errors) can be generated from any applications that this session
894 * daemon is managing.
895 */
533a90fb
FD
896 cds_lfht_for_each_entry(error_counter_uid_ht->ht, &iter.iter,
897 uid_entry, node.node) {
b623cb6a 898 const int ret = lttng_ust_ctl_counter_clear(uid_entry->daemon_counter,
533a90fb
FD
899 &dimension_index);
900
901 if (ret) {
902 uid_t trigger_owner_uid;
903 const char *trigger_name;
904
905 get_trigger_info_for_log(trigger, &trigger_name,
906 &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, trigger_name,
909 (int) trigger_owner_uid);
910 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
911 goto end;
912 }
913 }
914
915 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
916end:
917 rcu_read_unlock();
918 return status;
919}
920#endif /* HAVE_LIBLTTNG_UST_CTL */
921
90aa04a1
FD
922static
923enum event_notifier_error_accounting_status
924event_notifier_error_accounting_kernel_clear(
925 const struct lttng_trigger *trigger)
926{
927 int ret;
928 uint64_t error_counter_index;
929 enum event_notifier_error_accounting_status status;
b8e2fb80 930 struct lttng_kernel_abi_counter_clear counter_clear = {};
90aa04a1 931
a5a21280 932 status = get_error_counter_index_for_token(&kernel_state,
90aa04a1
FD
933 lttng_trigger_get_tracer_token(trigger),
934 &error_counter_index);
935 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
936 uid_t trigger_owner_uid;
937 const char *trigger_name;
90aa04a1 938
533a90fb
FD
939 get_trigger_info_for_log(
940 trigger, &trigger_name, &trigger_owner_uid);
941
942 ERR("Failed to get event notifier error counter index: trigger owner uid = %d, trigger name = '%s', status = '%s'",
943 trigger_owner_uid, trigger_name,
944 error_accounting_status_str(status));
90aa04a1
FD
945 goto end;
946 }
947
948 counter_clear.index.number_dimensions = 1;
949 counter_clear.index.dimension_indexes[0] = error_counter_index;
950
951 ret = kernctl_counter_clear(
a5a21280 952 kernel_error_accounting_entry.error_counter_fd,
90aa04a1
FD
953 &counter_clear);
954 if (ret) {
533a90fb
FD
955 uid_t trigger_owner_uid;
956 const char *trigger_name;
957
958 get_trigger_info_for_log(
959 trigger, &trigger_name, &trigger_owner_uid);
960
961 ERR("Failed to clear kernel event notifier error counter: trigger owner uid = %d, trigger name = '%s'",
962 trigger_owner_uid, trigger_name);
90aa04a1
FD
963 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
964 goto end;
965 }
966
967 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
968end:
969 return status;
970}
971
972enum event_notifier_error_accounting_status
973event_notifier_error_accounting_register_kernel(
974 int kernel_event_notifier_group_fd)
975{
976 int error_counter_fd = -1, ret;
977 enum event_notifier_error_accounting_status status;
b8e2fb80
FD
978 const struct lttng_kernel_abi_counter_conf error_counter_conf = {
979 .arithmetic = LTTNG_KERNEL_ABI_COUNTER_ARITHMETIC_MODULAR,
90aa04a1 980 .bitness = sizeof(void *) == sizeof(uint32_t) ?
b8e2fb80
FD
981 LTTNG_KERNEL_ABI_COUNTER_BITNESS_32 :
982 LTTNG_KERNEL_ABI_COUNTER_BITNESS_64,
90aa04a1
FD
983 .global_sum_step = 0,
984 .number_dimensions = 1,
761ffce2 985 .dimensions[0].size = kernel_state.number_indices,
90aa04a1
FD
986 .dimensions[0].has_underflow = false,
987 .dimensions[0].has_overflow = false,
988 };
989
990 ret = kernctl_create_event_notifier_group_error_counter(
991 kernel_event_notifier_group_fd, &error_counter_conf);
992 if (ret < 0) {
993 PERROR("Failed to create event notifier group error counter through kernel ioctl: kernel_event_notifier_group_fd = %d",
994 kernel_event_notifier_group_fd);
995 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
996 goto error;
997 }
998
999 error_counter_fd = ret;
1000
1001 /* Prevent fd duplication after execlp(). */
1002 ret = fcntl(error_counter_fd, F_SETFD, FD_CLOEXEC);
1003 if (ret < 0) {
1004 PERROR("Failed to set FD_CLOEXEC flag on event notifier error counter file descriptor: error_counter_fd = %d",
1005 error_counter_fd);
1006 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
1007 goto error;
1008 }
1009
1010 DBG("Created kernel event notifier group error counter: fd = %d",
1011 error_counter_fd);
1012
a5a21280 1013 kernel_error_accounting_entry.error_counter_fd =
90aa04a1
FD
1014 error_counter_fd;
1015 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1016
1017error:
1018 return status;
1019}
1020
1021static
1022enum event_notifier_error_accounting_status create_error_counter_index_for_token(
761ffce2
FD
1023 struct error_accounting_state *state, uint64_t tracer_token,
1024 uint64_t *error_counter_index)
90aa04a1
FD
1025{
1026 struct index_ht_entry *index_entry;
1027 enum lttng_index_allocator_status index_alloc_status;
1028 uint64_t local_error_counter_index;
1029 enum event_notifier_error_accounting_status status;
1030
a0377dfe 1031 LTTNG_ASSERT(state);
761ffce2 1032
90aa04a1 1033 /* Allocate a new index for that counter. */
761ffce2 1034 index_alloc_status = lttng_index_allocator_alloc(state->index_allocator,
90aa04a1
FD
1035 &local_error_counter_index);
1036 switch (index_alloc_status) {
1037 case LTTNG_INDEX_ALLOCATOR_STATUS_EMPTY:
1038 DBG("No indices left in the configured event notifier error counter: "
1039 "number-of-indices = %"PRIu64,
1040 lttng_index_allocator_get_index_count(
761ffce2 1041 state->index_allocator));
90aa04a1
FD
1042 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE;
1043 goto end;
1044 case LTTNG_INDEX_ALLOCATOR_STATUS_OK:
1045 break;
1046 default:
1047 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
1048 goto end;
1049 }
1050
1051 index_entry = zmalloc(sizeof(*index_entry));
1052 if (index_entry == NULL) {
1053 PERROR("Failed to allocate event notifier error counter hash table entry");
1054 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
1055 goto end;
1056 }
1057
1058 index_entry->error_counter_index = local_error_counter_index;
1059 lttng_ht_node_init_u64(&index_entry->node, tracer_token);
761ffce2 1060 lttng_ht_add_unique_u64(state->indices_ht, &index_entry->node);
90aa04a1
FD
1061
1062 DBG("Allocated error counter index for tracer token: tracer token = %" PRIu64 ", index = %" PRIu64,
1063 tracer_token, local_error_counter_index);
1064 *error_counter_index = local_error_counter_index;
1065 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1066end:
1067 return status;
1068}
1069
1070enum event_notifier_error_accounting_status
1071event_notifier_error_accounting_register_event_notifier(
1072 const struct lttng_trigger *trigger,
1073 uint64_t *error_counter_index)
1074{
1075 enum event_notifier_error_accounting_status status;
1076 uint64_t local_error_counter_index;
761ffce2
FD
1077 struct error_accounting_state *state;
1078
1079 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1080 case LTTNG_DOMAIN_KERNEL:
1081 state = &kernel_state;
1082 break;
1083 case LTTNG_DOMAIN_UST:
496fc78f
FD
1084 case LTTNG_DOMAIN_PYTHON:
1085 case LTTNG_DOMAIN_JUL:
1086 case LTTNG_DOMAIN_LOG4J:
761ffce2
FD
1087 state = &ust_state;
1088 break;
1089 default:
1090 abort();
1091 }
90aa04a1
FD
1092
1093 /*
1094 * Check if this event notifier already has a error counter index
1095 * assigned.
1096 */
761ffce2 1097 status = get_error_counter_index_for_token(state,
90aa04a1
FD
1098 lttng_trigger_get_tracer_token(trigger),
1099 &local_error_counter_index);
1100 switch (status) {
1101 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND:
1102 {
1103 uid_t trigger_owner_uid;
1104 const char *trigger_name;
90aa04a1 1105
533a90fb
FD
1106 get_trigger_info_for_log(
1107 trigger, &trigger_name, &trigger_owner_uid);
1108
1109 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,
1110 trigger_name, trigger_owner_uid,
90aa04a1 1111 lttng_trigger_get_tracer_token(trigger));
533a90fb 1112
761ffce2 1113 status = create_error_counter_index_for_token(state,
90aa04a1
FD
1114 lttng_trigger_get_tracer_token(trigger),
1115 &local_error_counter_index);
1116 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
533a90fb
FD
1117 ERR("Error creating index for token: status = %s, trigger name = '%s', trigger owner uid = %d",
1118 error_accounting_status_str(status),
1119 trigger_name, trigger_owner_uid);
90aa04a1
FD
1120 goto end;
1121 }
1122 /* fall-through. */
1123 }
1124 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK:
1125 *error_counter_index = local_error_counter_index;
1126 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1127 break;
1128 default:
1129 break;
1130 }
1131
a5a21280
FD
1132#ifdef HAVE_LIBLTTNG_UST_CTL
1133 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1134 case LTTNG_DOMAIN_UST:
496fc78f
FD
1135 case LTTNG_DOMAIN_PYTHON:
1136 case LTTNG_DOMAIN_JUL:
1137 case LTTNG_DOMAIN_LOG4J:
a5a21280
FD
1138 pthread_mutex_lock(&the_event_notifier_counter.lock);
1139 the_event_notifier_counter.count++;
1140 if (the_event_notifier_counter.count == 1) {
1141 /*
1142 * On the first event notifier, we get a reference to
1143 * every existing UID entries. This ensures that the
1144 * entries are kept around if there are still
1145 * registered event notifiers but no apps.
1146 */
1147 get_ref_all_ust_error_accounting_entry();
1148 }
1149 pthread_mutex_unlock(&the_event_notifier_counter.lock);
1150 break;
1151 default:
1152 break;
1153 }
1154#endif /* HAVE_LIBLTTNG_UST_CTL */
1155
1156
90aa04a1
FD
1157end:
1158 return status;
1159}
1160
1161static
1162enum event_notifier_error_accounting_status
1163event_notifier_error_accounting_kernel_get_count(
1164 const struct lttng_trigger *trigger, uint64_t *count)
1165{
b8e2fb80 1166 struct lttng_kernel_abi_counter_aggregate counter_aggregate = {};
90aa04a1
FD
1167 enum event_notifier_error_accounting_status status;
1168 uint64_t error_counter_index;
1169 int ret;
1170
a5a21280 1171 status = get_error_counter_index_for_token(&kernel_state,
761ffce2
FD
1172 lttng_trigger_get_tracer_token(trigger),
1173 &error_counter_index);
90aa04a1 1174 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
533a90fb
FD
1175 ERR("Error getting index for token: status=%s",
1176 error_accounting_status_str(status));
90aa04a1
FD
1177 goto end;
1178 }
1179
1180 counter_aggregate.index.number_dimensions = 1;
1181 counter_aggregate.index.dimension_indexes[0] = error_counter_index;
1182
a0377dfe 1183 LTTNG_ASSERT(kernel_error_accounting_entry.error_counter_fd);
90aa04a1
FD
1184
1185 ret = kernctl_counter_get_aggregate_value(
a5a21280 1186 kernel_error_accounting_entry.error_counter_fd,
90aa04a1
FD
1187 &counter_aggregate);
1188 if (ret || counter_aggregate.value.value < 0) {
1189 uid_t trigger_owner_uid;
1190 const char *trigger_name;
533a90fb
FD
1191
1192 get_trigger_info_for_log(trigger, &trigger_name,
1193 &trigger_owner_uid);
90aa04a1
FD
1194
1195 if (counter_aggregate.value.value < 0) {
1196 ERR("Invalid negative event notifier error counter value: trigger owner = %d, trigger name = '%s', value = %" PRId64,
1197 trigger_owner_uid, trigger_name,
1198 counter_aggregate.value.value);
1199 } else {
1200 ERR("Failed to getting event notifier error count: trigger owner = %d, trigger name = '%s', ret = %d",
1201 trigger_owner_uid, trigger_name, ret);
1202 }
1203
1204 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
1205 goto end;
1206 }
1207
1208 /* Error count can't be negative. */
a0377dfe 1209 LTTNG_ASSERT(counter_aggregate.value.value >= 0);
90aa04a1
FD
1210 *count = (uint64_t) counter_aggregate.value.value;
1211
1212 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1213
1214end:
1215 return status;
1216}
1217
1218enum event_notifier_error_accounting_status
1219event_notifier_error_accounting_get_count(
1220 const struct lttng_trigger *trigger, uint64_t *count)
1221{
1222 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1223 case LTTNG_DOMAIN_KERNEL:
1224 return event_notifier_error_accounting_kernel_get_count(
1225 trigger, count);
1226 case LTTNG_DOMAIN_UST:
496fc78f
FD
1227 case LTTNG_DOMAIN_PYTHON:
1228 case LTTNG_DOMAIN_JUL:
1229 case LTTNG_DOMAIN_LOG4J:
533a90fb 1230#ifdef HAVE_LIBLTTNG_UST_CTL
761ffce2
FD
1231 return event_notifier_error_accounting_ust_get_count(trigger,
1232 count);
533a90fb 1233#else
43cee6f9 1234 *count = 0;
90aa04a1 1235 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
533a90fb 1236#endif /* HAVE_LIBLTTNG_UST_CTL */
90aa04a1
FD
1237 default:
1238 abort();
1239 }
1240}
1241
1242static
1243enum event_notifier_error_accounting_status
1244event_notifier_error_accounting_clear(const struct lttng_trigger *trigger)
1245{
1246 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1247 case LTTNG_DOMAIN_KERNEL:
1248 return event_notifier_error_accounting_kernel_clear(trigger);
1249 case LTTNG_DOMAIN_UST:
496fc78f
FD
1250 case LTTNG_DOMAIN_PYTHON:
1251 case LTTNG_DOMAIN_JUL:
1252 case LTTNG_DOMAIN_LOG4J:
533a90fb
FD
1253#ifdef HAVE_LIBLTTNG_UST_CTL
1254 return event_notifier_error_accounting_ust_clear(trigger);
1255#else
90aa04a1 1256 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
533a90fb 1257#endif /* HAVE_LIBLTTNG_UST_CTL */
90aa04a1
FD
1258 default:
1259 abort();
1260 }
1261}
1262
1263static void free_index_ht_entry(struct rcu_head *head)
1264{
1265 struct index_ht_entry *entry = caa_container_of(head,
1266 struct index_ht_entry, rcu_head);
1267
1268 free(entry);
1269}
1270
1271void event_notifier_error_accounting_unregister_event_notifier(
1272 const struct lttng_trigger *trigger)
1273{
1274 struct lttng_ht_iter iter;
1275 struct lttng_ht_node_u64 *node;
533a90fb 1276 const uint64_t tracer_token = lttng_trigger_get_tracer_token(trigger);
90aa04a1 1277 enum event_notifier_error_accounting_status status;
761ffce2 1278 struct error_accounting_state *state;
90aa04a1
FD
1279
1280 status = event_notifier_error_accounting_clear(trigger);
1281 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
533a90fb
FD
1282 /* Trigger details already logged by callee on error. */
1283 ERR("Failed to clear event notifier error counter during unregistration of event notifier: status = '%s'",
1284 error_accounting_status_str(status));
a5a21280 1285 goto end;
90aa04a1
FD
1286 }
1287
a5a21280
FD
1288 rcu_read_lock();
1289
761ffce2
FD
1290 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1291 case LTTNG_DOMAIN_KERNEL:
1292 state = &kernel_state;
1293 break;
a5a21280 1294#ifdef HAVE_LIBLTTNG_UST_CTL
761ffce2 1295 case LTTNG_DOMAIN_UST:
496fc78f
FD
1296 case LTTNG_DOMAIN_PYTHON:
1297 case LTTNG_DOMAIN_JUL:
1298 case LTTNG_DOMAIN_LOG4J:
761ffce2 1299 state = &ust_state;
a5a21280
FD
1300
1301 pthread_mutex_lock(&the_event_notifier_counter.lock);
1302 the_event_notifier_counter.count--;
1303 if (the_event_notifier_counter.count == 0) {
1304
1305 /*
1306 * When unregistering the last event notifier, put one
1307 * reference to every uid entries on the behalf of all
1308 * event notifiers.
1309 */
1310 put_ref_all_ust_error_accounting_entry();
1311 }
1312
1313 pthread_mutex_unlock(&the_event_notifier_counter.lock);
1314
761ffce2 1315 break;
a5a21280 1316#endif /* HAVE_LIBLTTNG_UST_CTL */
761ffce2
FD
1317 default:
1318 abort();
1319 }
1320
761ffce2 1321 lttng_ht_lookup(state->indices_ht, &tracer_token, &iter);
90aa04a1 1322 node = lttng_ht_iter_get_node_u64(&iter);
533a90fb 1323 if (node) {
44d0e2f1 1324 int del_ret;
533a90fb
FD
1325 struct index_ht_entry *index_entry = caa_container_of(
1326 node, typeof(*index_entry), node);
1327 enum lttng_index_allocator_status index_alloc_status;
1328
90aa04a1 1329 index_alloc_status = lttng_index_allocator_release(
761ffce2 1330 state->index_allocator,
90aa04a1
FD
1331 index_entry->error_counter_index);
1332 if (index_alloc_status != LTTNG_INDEX_ALLOCATOR_STATUS_OK) {
533a90fb
FD
1333 uid_t trigger_owner_uid;
1334 const char *trigger_name;
1335
1336 get_trigger_info_for_log(trigger, &trigger_name,
1337 &trigger_owner_uid);
1338
1339 ERR("Failed to release event notifier error counter index: index = %" PRIu64 ", trigger name = '%s', trigger owner uid = %d",
1340 index_entry->error_counter_index,
1341 trigger_name, (int) trigger_owner_uid);
1342 /* Don't exit, perform the rest of the clean-up. */
90aa04a1
FD
1343 }
1344
761ffce2 1345 del_ret = lttng_ht_del(state->indices_ht, &iter);
a0377dfe 1346 LTTNG_ASSERT(!del_ret);
90aa04a1
FD
1347 call_rcu(&index_entry->rcu_head, free_index_ht_entry);
1348 }
1349
a5a21280 1350end:
90aa04a1
FD
1351 rcu_read_unlock();
1352}
1353
1354void event_notifier_error_accounting_fini(void)
1355{
a5a21280
FD
1356 if (kernel_error_accounting_entry.error_counter_fd) {
1357 const int ret = close(kernel_error_accounting_entry.error_counter_fd);
90aa04a1
FD
1358
1359 if (ret) {
1360 PERROR("Failed to close kernel event notifier error counter");
1361 }
1362 }
1363
533a90fb
FD
1364 lttng_ht_destroy(error_counter_uid_ht);
1365
761ffce2
FD
1366 fini_error_accounting_state(&kernel_state);
1367 fini_error_accounting_state(&ust_state);
90aa04a1 1368}
This page took 0.085973 seconds and 4 git commands to generate.