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