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