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