vscode: Add configurations to run the executables under the debugger
[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
56047f5a 158 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
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
56047f5a
JG
182 {
183 lttng::urcu::read_lock_guard read_lock;
a5a21280 184
56047f5a
JG
185 cds_lfht_for_each_entry (
186 error_counter_uid_ht->ht, &iter.iter, uid_entry, node.node) {
187 ust_error_accounting_entry_put(uid_entry);
188 }
189 }
a5a21280
FD
190}
191
192/*
193 * Get one reference to every UID entries.
194 */
cd9adb8b 195static void get_ref_all_ust_error_accounting_entry()
a5a21280
FD
196{
197 struct lttng_ht_iter iter;
198 struct ust_error_accounting_entry *uid_entry;
199
200 ASSERT_LOCKED(the_event_notifier_counter.lock);
201
56047f5a
JG
202 {
203 lttng::urcu::read_lock_guard read_lock;
a5a21280 204
56047f5a
JG
205 cds_lfht_for_each_entry (
206 error_counter_uid_ht->ht, &iter.iter, uid_entry, node.node) {
207 ust_error_accounting_entry_get(uid_entry);
208 }
209 }
a5a21280
FD
210}
211
212#endif /* HAVE_LIBLTTNG_UST_CTL */
213
28ab034a
JG
214static enum event_notifier_error_accounting_status
215init_error_accounting_state(struct error_accounting_state *state, uint64_t index_count)
90aa04a1
FD
216{
217 enum event_notifier_error_accounting_status status;
218
a0377dfe 219 LTTNG_ASSERT(state);
761ffce2
FD
220
221 state->number_indices = index_count;
222
223 state->index_allocator = lttng_index_allocator_create(index_count);
224 if (!state->index_allocator) {
225 ERR("Failed to allocate event notifier error counter index allocator");
90aa04a1 226 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
761ffce2 227 goto end;
90aa04a1
FD
228 }
229
28ab034a 230 state->indices_ht = lttng_ht_new(ERROR_COUNTER_INDEX_HT_INITIAL_SIZE, LTTNG_HT_TYPE_U64);
761ffce2 231 if (!state->indices_ht) {
533a90fb
FD
232 ERR("Failed to allocate error counter indices hash table");
233 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
761ffce2
FD
234 goto error_indices_ht;
235 }
236
237 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
238 goto end;
239
240error_indices_ht:
241 lttng_index_allocator_destroy(state->index_allocator);
cd9adb8b 242 state->index_allocator = nullptr;
761ffce2
FD
243end:
244 return status;
245}
246
28ab034a 247static void fini_error_accounting_state(struct error_accounting_state *state)
761ffce2 248{
a0377dfe 249 LTTNG_ASSERT(state);
761ffce2
FD
250
251 /*
252 * Will assert if some error counter indices were not released (an
253 * internal error).
254 */
255 lttng_ht_destroy(state->indices_ht);
256 lttng_index_allocator_destroy(state->index_allocator);
257}
258
259enum event_notifier_error_accounting_status
28ab034a 260event_notifier_error_accounting_init(uint64_t buffer_size_kernel, uint64_t buffer_size_ust)
761ffce2
FD
261{
262 enum event_notifier_error_accounting_status status;
263
264 status = init_error_accounting_state(&kernel_state, buffer_size_kernel);
265 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
266 ERR("Failed to initialize kernel event notifier accounting state: status = %s",
28ab034a 267 error_accounting_status_str(status));
761ffce2
FD
268 goto end;
269 }
270
271 status = init_error_accounting_state(&ust_state, buffer_size_ust);
272 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
273 ERR("Failed to initialize UST event notifier accounting state: status = %s",
28ab034a 274 error_accounting_status_str(status));
761ffce2 275 goto error_ust_state;
533a90fb
FD
276 }
277
28ab034a 278 error_counter_uid_ht = lttng_ht_new(ERROR_COUNTER_INDEX_HT_INITIAL_SIZE, LTTNG_HT_TYPE_U64);
533a90fb
FD
279 if (!error_counter_uid_ht) {
280 ERR("Failed to allocate UID to error counter accountant hash table");
90aa04a1 281 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
761ffce2 282 goto error_uid_ht;
90aa04a1
FD
283 }
284
90aa04a1 285 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
761ffce2 286 goto end;
90aa04a1 287
761ffce2
FD
288error_uid_ht:
289 fini_error_accounting_state(&ust_state);
290error_ust_state:
291 fini_error_accounting_state(&kernel_state);
292end:
90aa04a1
FD
293 return status;
294}
295
a5a21280
FD
296/*
297 * Return the error counteur index associated to this event notifier tracer
298 * token. Returns _STATUS_OK if found and _STATUS_NOT_FOUND otherwise.
299 */
28ab034a
JG
300static enum event_notifier_error_accounting_status get_error_counter_index_for_token(
301 struct error_accounting_state *state, uint64_t tracer_token, uint64_t *error_counter_index)
90aa04a1
FD
302{
303 struct lttng_ht_node_u64 *node;
304 struct lttng_ht_iter iter;
305 const struct index_ht_entry *index_entry;
306 enum event_notifier_error_accounting_status status;
56047f5a 307 lttng::urcu::read_lock_guard read_guard;
90aa04a1 308
761ffce2 309 lttng_ht_lookup(state->indices_ht, &tracer_token, &iter);
90aa04a1
FD
310 node = lttng_ht_iter_get_node_u64(&iter);
311 if (node) {
0114db0e 312 index_entry = lttng::utils::container_of(node, &index_ht_entry::node);
90aa04a1
FD
313 *error_counter_index = index_entry->error_counter_index;
314 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
315 } else {
316 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND;
317 }
318
90aa04a1
FD
319 return status;
320}
321
533a90fb 322#ifdef HAVE_LIBLTTNG_UST_CTL
a5a21280
FD
323/*
324 * Find the entry for this app's UID, the caller acquires a reference if the
325 * entry is found.
326 */
28ab034a
JG
327static struct ust_error_accounting_entry *ust_error_accounting_entry_find(struct lttng_ht *uid_ht,
328 const struct ust_app *app)
533a90fb 329{
761ffce2 330 struct ust_error_accounting_entry *entry;
533a90fb
FD
331 struct lttng_ht_node_u64 *node;
332 struct lttng_ht_iter iter;
333 uint64_t key = app->uid;
334
a5a21280 335 lttng_ht_lookup(uid_ht, &key, &iter);
533a90fb 336 node = lttng_ht_iter_get_node_u64(&iter);
cd9adb8b
JG
337 if (node == nullptr) {
338 entry = nullptr;
533a90fb 339 } else {
a5a21280
FD
340 bool got_ref;
341
28ab034a 342 entry = caa_container_of(node, struct ust_error_accounting_entry, node);
a5a21280
FD
343
344 got_ref = ust_error_accounting_entry_get(entry);
345 if (!got_ref) {
cd9adb8b 346 entry = nullptr;
a5a21280 347 }
533a90fb
FD
348 }
349
350 return entry;
351}
352
a5a21280
FD
353/*
354 * Create the entry for this app's UID, the caller acquires a reference to the
355 * entry,
356 */
28ab034a
JG
357static struct ust_error_accounting_entry *
358ust_error_accounting_entry_create(const struct ust_app *app)
533a90fb 359{
cd9adb8b 360 int i, ret, *cpu_counter_fds = nullptr;
b623cb6a 361 struct lttng_ust_ctl_daemon_counter *daemon_counter;
533a90fb 362 struct lttng_ust_abi_object_data *counter, **cpu_counters;
cd9adb8b 363 struct ust_error_accounting_entry *entry = nullptr;
5728ab7d 364 lttng_ust_ctl_counter_dimension dimension = {};
7966af57
SM
365
366 dimension.size = ust_state.number_indices;
367 dimension.has_underflow = false;
368 dimension.has_overflow = false;
533a90fb 369
783db316
MD
370 if (!ust_app_supports_counters(app)) {
371 DBG("Refusing to create accounting entry for application (unsupported feature): app name = '%s', app ppid = %d",
28ab034a
JG
372 app->name,
373 (int) app->ppid);
783db316
MD
374 goto error;
375 }
376
64803277 377 entry = zmalloc<ust_error_accounting_entry>();
533a90fb
FD
378 if (!entry) {
379 PERROR("Failed to allocate event notifier error acounting entry")
380 goto error;
381 }
382
a5a21280 383 urcu_ref_init(&entry->ref);
761ffce2 384 entry->uid = app->uid;
b623cb6a 385 entry->nr_counter_cpu_fds = lttng_ust_ctl_get_nr_cpu_per_counter();
761ffce2 386
64803277 387 cpu_counter_fds = calloc<int>(entry->nr_counter_cpu_fds);
533a90fb
FD
388 if (!cpu_counter_fds) {
389 PERROR("Failed to allocate event notifier error counter file descriptors array: application uid = %d, application name = '%s', pid = %d, allocation size = %zu",
28ab034a
JG
390 (int) app->uid,
391 app->name,
392 (int) app->pid,
393 entry->nr_counter_cpu_fds * sizeof(*cpu_counter_fds));
533a90fb
FD
394 goto error_counter_cpu_fds_alloc;
395 }
396
397 /* Initialize to an invalid fd value to closes fds in case of error. */
398 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
399 cpu_counter_fds[i] = -1;
400 }
401
64803277 402 cpu_counters = calloc<lttng_ust_abi_object_data *>(entry->nr_counter_cpu_fds);
533a90fb
FD
403 if (!cpu_counters) {
404 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
405 (int) app->uid,
406 app->name,
407 (int) app->pid,
408 entry->nr_counter_cpu_fds * sizeof(struct lttng_ust_abi_object_data *));
533a90fb
FD
409 goto error_counter_cpus_alloc;
410 }
411
412 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
413 cpu_counter_fds[i] = shm_create_anonymous("event-notifier-error-accounting");
414 if (cpu_counter_fds[i] == -1) {
415 ERR("Failed to create event notifier error accounting shared memory for application user: application uid = %d, pid = %d, application name = '%s'",
28ab034a
JG
416 (int) app->uid,
417 (int) app->pid,
418 app->name);
533a90fb
FD
419 goto error_shm_alloc;
420 }
421 }
422
423 /*
424 * Ownership of the file descriptors transferred to the ustctl object.
425 */
28ab034a
JG
426 daemon_counter = lttng_ust_ctl_create_counter(1,
427 &dimension,
428 0,
429 -1,
430 entry->nr_counter_cpu_fds,
431 cpu_counter_fds,
432 LTTNG_UST_CTL_COUNTER_BITNESS_32,
433 LTTNG_UST_CTL_COUNTER_ARITHMETIC_MODULAR,
434 LTTNG_UST_CTL_COUNTER_ALLOC_PER_CPU,
435 false);
533a90fb
FD
436 if (!daemon_counter) {
437 goto error_create_daemon_counter;
438 }
439
b623cb6a 440 ret = lttng_ust_ctl_create_counter_data(daemon_counter, &counter);
533a90fb
FD
441 if (ret) {
442 ERR("Failed to create userspace tracer counter data for application user: uid = %d, pid = %d, application name = '%s'",
28ab034a
JG
443 (int) app->uid,
444 (int) app->pid,
445 app->name);
533a90fb
FD
446 goto error_create_counter_data;
447 }
448
449 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
28ab034a 450 ret = lttng_ust_ctl_create_counter_cpu_data(daemon_counter, i, &cpu_counters[i]);
533a90fb
FD
451 if (ret) {
452 ERR("Failed to create userspace tracer counter cpu data for application user: uid = %d, pid = %d, application name = '%s'",
28ab034a
JG
453 (int) app->uid,
454 (int) app->pid,
455 app->name);
533a90fb
FD
456 goto error_create_counter_cpu_data;
457 }
458 }
459
460 entry->daemon_counter = daemon_counter;
461 entry->counter = counter;
462 entry->cpu_counters = cpu_counters;
463
a5a21280 464 lttng_ht_node_init_u64(&entry->node, entry->uid);
533a90fb
FD
465 lttng_ht_add_unique_u64(error_counter_uid_ht, &entry->node);
466
467 goto end;
468
469error_create_counter_cpu_data:
470 /* Teardown any allocated cpu counters. */
471 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
472 if (!cpu_counters[i]) {
473 /*
474 * Early-exit when error occurred before all cpu
475 * counters could be initialized.
476 */
477 break;
478 }
479
b623cb6a 480 lttng_ust_ctl_release_object(-1, cpu_counters[i]);
533a90fb
FD
481 free(cpu_counters[i]);
482 }
483
b623cb6a 484 lttng_ust_ctl_release_object(-1, entry->counter);
533a90fb
FD
485 free(entry->counter);
486error_create_counter_data:
b623cb6a 487 lttng_ust_ctl_destroy_counter(daemon_counter);
533a90fb
FD
488error_create_daemon_counter:
489error_shm_alloc:
8f0646a0 490 /* Error occurred before per-cpu SHMs were handed-off to ustctl. */
533a90fb
FD
491 if (cpu_counter_fds) {
492 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
493 if (cpu_counter_fds[i] < 0) {
494 /*
495 * Early-exit when error occurred before all cpu
496 * counter shm fds could be initialized.
497 */
498 break;
499 }
500
501 ret = close(cpu_counter_fds[i]);
502 if (ret) {
a5a21280 503 PERROR("Failed to close error counter per-CPU shm file descriptor: fd = %d",
28ab034a 504 cpu_counter_fds[i]);
533a90fb
FD
505 }
506 }
507 }
508
509 free(cpu_counters);
510error_counter_cpus_alloc:
511error_counter_cpu_fds_alloc:
512 free(entry);
513error:
cd9adb8b 514 entry = nullptr;
533a90fb
FD
515end:
516 free(cpu_counter_fds);
517 return entry;
518}
519
28ab034a
JG
520static enum event_notifier_error_accounting_status
521send_counter_data_to_ust(struct ust_app *app, struct lttng_ust_abi_object_data *new_counter)
533a90fb
FD
522{
523 int ret;
524 enum event_notifier_error_accounting_status status;
525
526 /* Attach counter to trigger group. */
527 pthread_mutex_lock(&app->sock_lock);
28ab034a
JG
528 ret = lttng_ust_ctl_send_counter_data_to_ust(
529 app->sock, app->event_notifier_group.object->handle, new_counter);
533a90fb
FD
530 pthread_mutex_unlock(&app->sock_lock);
531 if (ret < 0) {
532 if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
533 ERR("Failed to send counter data to application: application name = '%s', pid = %d, ret = %d",
28ab034a
JG
534 app->name,
535 app->pid,
536 ret);
533a90fb
FD
537 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
538 } else {
539 DBG3("Failed to send counter data to application (application is dead): application name = '%s', pid = %d, ret = %d",
28ab034a
JG
540 app->name,
541 app->pid,
542 ret);
533a90fb
FD
543 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD;
544 }
545
546 goto end;
547 }
548
549 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
550end:
551 return status;
552}
553
28ab034a
JG
554static enum event_notifier_error_accounting_status
555send_counter_cpu_data_to_ust(struct ust_app *app,
556 struct lttng_ust_abi_object_data *counter,
557 struct lttng_ust_abi_object_data *counter_cpu)
533a90fb
FD
558{
559 int ret;
560 enum event_notifier_error_accounting_status status;
561
562 pthread_mutex_lock(&app->sock_lock);
28ab034a 563 ret = lttng_ust_ctl_send_counter_cpu_data_to_ust(app->sock, counter, counter_cpu);
533a90fb
FD
564 pthread_mutex_unlock(&app->sock_lock);
565 if (ret < 0) {
566 if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
567 ERR("Failed to send counter CPU data to application: application name = '%s', pid = %d, ret = %d",
28ab034a
JG
568 app->name,
569 app->pid,
570 ret);
533a90fb
FD
571 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
572 } else {
573 DBG3("Failed to send counter CPU data to application: application name = '%s', pid = %d, ret = %d",
28ab034a
JG
574 app->name,
575 app->pid,
576 ret);
533a90fb
FD
577 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD;
578 }
579
580 goto end;
581 }
582
583 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
584end:
585 return status;
586}
587
588enum event_notifier_error_accounting_status
589event_notifier_error_accounting_register_app(struct ust_app *app)
590{
591 int ret;
592 uint64_t i;
593 struct lttng_ust_abi_object_data *new_counter;
761ffce2 594 struct ust_error_accounting_entry *entry;
533a90fb
FD
595 enum event_notifier_error_accounting_status status;
596 struct lttng_ust_abi_object_data **cpu_counters;
56047f5a 597 lttng::urcu::read_lock_guard read_lock;
533a90fb 598
783db316
MD
599 if (!ust_app_supports_counters(app)) {
600 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_UNSUPPORTED;
601 goto end;
602 }
603
533a90fb
FD
604 /*
605 * Check if we already have a error counter for the user id of this
606 * app. If not, create one.
607 */
a5a21280 608 entry = ust_error_accounting_entry_find(error_counter_uid_ht, app);
cd9adb8b 609 if (entry == nullptr) {
a5a21280
FD
610 /*
611 * Take the event notifier counter lock before creating the new
612 * entry to ensure that no event notifier is registered between
613 * the the entry creation and event notifier count check.
614 */
615 pthread_mutex_lock(&the_event_notifier_counter.lock);
616
f46376a1 617 entry = ust_error_accounting_entry_create(app);
533a90fb
FD
618 if (!entry) {
619 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
a5a21280
FD
620 pthread_mutex_unlock(&the_event_notifier_counter.lock);
621 goto error_creating_entry;
622 }
623
624 /*
625 * We just created a new UID entry, If there are event
626 * notifiers already registered, take one reference on their
627 * behalf.
628 */
629 if (the_event_notifier_counter.count > 0) {
630 ust_error_accounting_entry_get(entry);
533a90fb 631 }
a5a21280
FD
632
633 pthread_mutex_unlock(&the_event_notifier_counter.lock);
533a90fb
FD
634 }
635
636 /* Duplicate counter object data. */
28ab034a 637 ret = lttng_ust_ctl_duplicate_ust_object_data(&new_counter, entry->counter);
533a90fb
FD
638 if (ret) {
639 ERR("Failed to duplicate event notifier error accounting counter for application user: application uid = %d, pid = %d, application name = '%s'",
28ab034a
JG
640 (int) app->uid,
641 (int) app->pid,
642 app->name);
533a90fb 643 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
a5a21280 644 goto error_duplicate_counter;
533a90fb
FD
645 }
646
647 status = send_counter_data_to_ust(app, new_counter);
648 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
cd9c532c
FD
649 if (status == EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD) {
650 goto error_send_counter_data;
651 }
652
533a90fb 653 ERR("Failed to send counter data to application tracer: status = %s, application uid = %d, pid = %d, application name = '%s'",
28ab034a
JG
654 error_accounting_status_str(status),
655 (int) app->uid,
656 (int) app->pid,
657 app->name);
533a90fb
FD
658 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
659 goto error_send_counter_data;
660 }
661
64803277 662 cpu_counters = calloc<lttng_ust_abi_object_data *>(entry->nr_counter_cpu_fds);
533a90fb
FD
663 if (!cpu_counters) {
664 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
665 (int) app->uid,
666 app->name,
667 (int) app->pid,
668 entry->nr_counter_cpu_fds * sizeof(**cpu_counters));
533a90fb
FD
669 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
670 goto error_allocate_cpu_counters;
671 }
672
673 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
cd9adb8b 674 struct lttng_ust_abi_object_data *new_counter_cpu = nullptr;
533a90fb 675
b623cb6a 676 ret = lttng_ust_ctl_duplicate_ust_object_data(&new_counter_cpu,
28ab034a 677 entry->cpu_counters[i]);
533a90fb
FD
678 if (ret) {
679 ERR("Failed to duplicate userspace tracer counter cpu data for application user: uid = %d, pid = %d, application name = '%s'",
28ab034a
JG
680 (int) app->uid,
681 (int) app->pid,
682 app->name);
533a90fb
FD
683 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
684 goto error_duplicate_cpu_counter;
685 }
686
687 cpu_counters[i] = new_counter_cpu;
688
28ab034a 689 status = send_counter_cpu_data_to_ust(app, new_counter, new_counter_cpu);
533a90fb 690 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
cd9c532c
FD
691 if (status == EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD) {
692 goto error_send_cpu_counter_data;
693 }
694
533a90fb 695 ERR("Failed to send counter cpu data to application tracer: status = %s, application uid = %d, pid = %d, application name = '%s'",
28ab034a
JG
696 error_accounting_status_str(status),
697 (int) app->uid,
698 (int) app->pid,
699 app->name);
533a90fb
FD
700 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
701 goto error_send_cpu_counter_data;
702 }
703 }
704
705 app->event_notifier_group.counter = new_counter;
cd9adb8b 706 new_counter = nullptr;
533a90fb
FD
707 app->event_notifier_group.nr_counter_cpu = entry->nr_counter_cpu_fds;
708 app->event_notifier_group.counter_cpu = cpu_counters;
cd9adb8b 709 cpu_counters = nullptr;
56047f5a 710 goto end;
533a90fb 711
533a90fb
FD
712error_send_cpu_counter_data:
713error_duplicate_cpu_counter:
714 /* Teardown any duplicated cpu counters. */
715 for (i = 0; i < entry->nr_counter_cpu_fds; i++) {
716 if (!cpu_counters[i]) {
717 /*
718 * Early-exit when error occurred before all cpu
719 * counters could be initialized.
720 */
721 break;
722 }
723
b623cb6a 724 lttng_ust_ctl_release_object(-1, cpu_counters[i]);
533a90fb
FD
725 free(cpu_counters[i]);
726 }
727
a55f8ad1
JG
728 free(cpu_counters);
729
5d650dcd 730error_allocate_cpu_counters:
533a90fb 731error_send_counter_data:
b623cb6a 732 lttng_ust_ctl_release_object(-1, new_counter);
533a90fb 733 free(new_counter);
a5a21280
FD
734error_duplicate_counter:
735 ust_error_accounting_entry_put(entry);
736error_creating_entry:
cd9adb8b 737 app->event_notifier_group.counter = nullptr;
783db316 738end:
533a90fb
FD
739 return status;
740}
741
742enum event_notifier_error_accounting_status
743event_notifier_error_accounting_unregister_app(struct ust_app *app)
744{
745 enum event_notifier_error_accounting_status status;
761ffce2 746 struct ust_error_accounting_entry *entry;
533a90fb
FD
747 int i;
748
56047f5a 749 lttng::urcu::read_lock_guard read_lock;
a5a21280
FD
750
751 /* If an error occurred during app registration no entry was created. */
752 if (!app->event_notifier_group.counter) {
753 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
754 goto end;
755 }
756
757 entry = ust_error_accounting_entry_find(error_counter_uid_ht, app);
cd9adb8b 758 if (entry == nullptr) {
533a90fb 759 ERR("Failed to find event notitifier error accounting entry on application teardown: pid = %d, application name = '%s'",
28ab034a
JG
760 app->pid,
761 app->name);
533a90fb
FD
762 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
763 goto end;
a5a21280
FD
764 } else {
765 /*
766 * Put the entry twice as we acquired a reference from the
767 * `ust_error_accounting_entry_find()` above.
768 */
769 ust_error_accounting_entry_put(entry);
770 ust_error_accounting_entry_put(entry);
533a90fb
FD
771 }
772
773 for (i = 0; i < app->event_notifier_group.nr_counter_cpu; i++) {
28ab034a 774 lttng_ust_ctl_release_object(app->sock, app->event_notifier_group.counter_cpu[i]);
533a90fb
FD
775 free(app->event_notifier_group.counter_cpu[i]);
776 }
777
778 free(app->event_notifier_group.counter_cpu);
779
b623cb6a 780 lttng_ust_ctl_release_object(app->sock, app->event_notifier_group.counter);
533a90fb
FD
781 free(app->event_notifier_group.counter);
782
783 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
784end:
533a90fb
FD
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
56047f5a 800 lttng::urcu::read_lock_guard read_lock;
533a90fb 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:
533a90fb
FD
860 return status;
861}
862
28ab034a
JG
863static enum event_notifier_error_accounting_status
864event_notifier_error_accounting_ust_clear(const struct lttng_trigger *trigger)
533a90fb
FD
865{
866 struct lttng_ht_iter iter;
761ffce2 867 struct ust_error_accounting_entry *uid_entry;
533a90fb
FD
868 uint64_t error_counter_index;
869 enum event_notifier_error_accounting_status status;
870 size_t dimension_index;
871 const uint64_t tracer_token = lttng_trigger_get_tracer_token(trigger);
872
56047f5a
JG
873 lttng::urcu::read_lock_guard read_lock;
874
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:
533a90fb
FD
918 return status;
919}
920#endif /* HAVE_LIBLTTNG_UST_CTL */
921
28ab034a
JG
922static enum event_notifier_error_accounting_status
923event_notifier_error_accounting_kernel_clear(const struct lttng_trigger *trigger)
90aa04a1
FD
924{
925 int ret;
926 uint64_t error_counter_index;
927 enum event_notifier_error_accounting_status status;
b8e2fb80 928 struct lttng_kernel_abi_counter_clear counter_clear = {};
90aa04a1 929
28ab034a
JG
930 status = get_error_counter_index_for_token(
931 &kernel_state, lttng_trigger_get_tracer_token(trigger), &error_counter_index);
90aa04a1
FD
932 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
933 uid_t trigger_owner_uid;
934 const char *trigger_name;
90aa04a1 935
28ab034a 936 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
533a90fb
FD
937
938 ERR("Failed to get event notifier error counter index: trigger owner uid = %d, trigger name = '%s', status = '%s'",
28ab034a
JG
939 trigger_owner_uid,
940 trigger_name,
941 error_accounting_status_str(status));
90aa04a1
FD
942 goto end;
943 }
944
945 counter_clear.index.number_dimensions = 1;
946 counter_clear.index.dimension_indexes[0] = error_counter_index;
947
28ab034a 948 ret = kernctl_counter_clear(kernel_error_accounting_entry.error_counter_fd, &counter_clear);
90aa04a1 949 if (ret) {
533a90fb
FD
950 uid_t trigger_owner_uid;
951 const char *trigger_name;
952
28ab034a 953 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
533a90fb
FD
954
955 ERR("Failed to clear kernel event notifier error counter: trigger owner uid = %d, trigger name = '%s'",
28ab034a
JG
956 trigger_owner_uid,
957 trigger_name);
90aa04a1
FD
958 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
959 goto end;
960 }
961
962 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
963end:
964 return status;
965}
966
967enum event_notifier_error_accounting_status
28ab034a 968event_notifier_error_accounting_register_kernel(int kernel_event_notifier_group_fd)
90aa04a1
FD
969{
970 int error_counter_fd = -1, ret;
971 enum event_notifier_error_accounting_status status;
7966af57 972 lttng_kernel_abi_counter_conf error_counter_conf = {
b8e2fb80 973 .arithmetic = LTTNG_KERNEL_ABI_COUNTER_ARITHMETIC_MODULAR,
90aa04a1 974 .bitness = sizeof(void *) == sizeof(uint32_t) ?
28ab034a
JG
975 LTTNG_KERNEL_ABI_COUNTER_BITNESS_32 :
976 LTTNG_KERNEL_ABI_COUNTER_BITNESS_64,
90aa04a1 977 .number_dimensions = 1,
7966af57 978 .global_sum_step = 0,
1c9a0b0e
MJ
979 .dimensions = {},
980 .coalesce_hits = 0,
981 .padding = {},
90aa04a1 982 };
7966af57
SM
983 error_counter_conf.dimensions[0].size = kernel_state.number_indices;
984 error_counter_conf.dimensions[0].has_underflow = false;
985 error_counter_conf.dimensions[0].has_overflow = false;
90aa04a1 986
28ab034a
JG
987 ret = kernctl_create_event_notifier_group_error_counter(kernel_event_notifier_group_fd,
988 &error_counter_conf);
90aa04a1
FD
989 if (ret < 0) {
990 PERROR("Failed to create event notifier group error counter through kernel ioctl: kernel_event_notifier_group_fd = %d",
28ab034a 991 kernel_event_notifier_group_fd);
90aa04a1
FD
992 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
993 goto error;
994 }
995
996 error_counter_fd = ret;
997
998 /* Prevent fd duplication after execlp(). */
999 ret = fcntl(error_counter_fd, F_SETFD, FD_CLOEXEC);
1000 if (ret < 0) {
1001 PERROR("Failed to set FD_CLOEXEC flag on event notifier error counter file descriptor: error_counter_fd = %d",
28ab034a 1002 error_counter_fd);
90aa04a1
FD
1003 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
1004 goto error;
1005 }
1006
28ab034a 1007 DBG("Created kernel event notifier group error counter: fd = %d", error_counter_fd);
90aa04a1 1008
28ab034a 1009 kernel_error_accounting_entry.error_counter_fd = error_counter_fd;
90aa04a1
FD
1010 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1011
1012error:
1013 return status;
1014}
1015
28ab034a
JG
1016static enum event_notifier_error_accounting_status create_error_counter_index_for_token(
1017 struct error_accounting_state *state, uint64_t tracer_token, uint64_t *error_counter_index)
90aa04a1
FD
1018{
1019 struct index_ht_entry *index_entry;
1020 enum lttng_index_allocator_status index_alloc_status;
1021 uint64_t local_error_counter_index;
1022 enum event_notifier_error_accounting_status status;
1023
a0377dfe 1024 LTTNG_ASSERT(state);
761ffce2 1025
90aa04a1 1026 /* Allocate a new index for that counter. */
28ab034a
JG
1027 index_alloc_status =
1028 lttng_index_allocator_alloc(state->index_allocator, &local_error_counter_index);
90aa04a1
FD
1029 switch (index_alloc_status) {
1030 case LTTNG_INDEX_ALLOCATOR_STATUS_EMPTY:
1031 DBG("No indices left in the configured event notifier error counter: "
28ab034a
JG
1032 "number-of-indices = %" PRIu64,
1033 lttng_index_allocator_get_index_count(state->index_allocator));
90aa04a1
FD
1034 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE;
1035 goto end;
1036 case LTTNG_INDEX_ALLOCATOR_STATUS_OK:
1037 break;
1038 default:
1039 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
1040 goto end;
1041 }
1042
64803277 1043 index_entry = zmalloc<index_ht_entry>();
cd9adb8b 1044 if (index_entry == nullptr) {
90aa04a1
FD
1045 PERROR("Failed to allocate event notifier error counter hash table entry");
1046 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOMEM;
1047 goto end;
1048 }
1049
1050 index_entry->error_counter_index = local_error_counter_index;
1051 lttng_ht_node_init_u64(&index_entry->node, tracer_token);
761ffce2 1052 lttng_ht_add_unique_u64(state->indices_ht, &index_entry->node);
90aa04a1 1053
28ab034a
JG
1054 DBG("Allocated error counter index for tracer token: tracer token = %" PRIu64
1055 ", index = %" PRIu64,
1056 tracer_token,
1057 local_error_counter_index);
90aa04a1
FD
1058 *error_counter_index = local_error_counter_index;
1059 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1060end:
1061 return status;
1062}
1063
1064enum event_notifier_error_accounting_status
28ab034a
JG
1065event_notifier_error_accounting_register_event_notifier(const struct lttng_trigger *trigger,
1066 uint64_t *error_counter_index)
90aa04a1
FD
1067{
1068 enum event_notifier_error_accounting_status status;
1069 uint64_t local_error_counter_index;
761ffce2
FD
1070 struct error_accounting_state *state;
1071
1072 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1073 case LTTNG_DOMAIN_KERNEL:
1074 state = &kernel_state;
1075 break;
1076 case LTTNG_DOMAIN_UST:
496fc78f
FD
1077 case LTTNG_DOMAIN_PYTHON:
1078 case LTTNG_DOMAIN_JUL:
1079 case LTTNG_DOMAIN_LOG4J:
761ffce2
FD
1080 state = &ust_state;
1081 break;
1082 default:
1083 abort();
1084 }
90aa04a1
FD
1085
1086 /*
1087 * Check if this event notifier already has a error counter index
1088 * assigned.
1089 */
28ab034a
JG
1090 status = get_error_counter_index_for_token(
1091 state, lttng_trigger_get_tracer_token(trigger), &local_error_counter_index);
90aa04a1
FD
1092 switch (status) {
1093 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NOT_FOUND:
1094 {
1095 uid_t trigger_owner_uid;
1096 const char *trigger_name;
90aa04a1 1097
28ab034a 1098 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
533a90fb
FD
1099
1100 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
1101 trigger_name,
1102 trigger_owner_uid,
1103 lttng_trigger_get_tracer_token(trigger));
533a90fb 1104
28ab034a
JG
1105 status = create_error_counter_index_for_token(
1106 state, lttng_trigger_get_tracer_token(trigger), &local_error_counter_index);
90aa04a1 1107 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
533a90fb 1108 ERR("Error creating index for token: status = %s, trigger name = '%s', trigger owner uid = %d",
28ab034a
JG
1109 error_accounting_status_str(status),
1110 trigger_name,
1111 trigger_owner_uid);
90aa04a1
FD
1112 goto end;
1113 }
90aa04a1 1114 }
30eb3927 1115 /* fall-through. */
90aa04a1
FD
1116 case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK:
1117 *error_counter_index = local_error_counter_index;
1118 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1119 break;
1120 default:
1121 break;
1122 }
1123
a5a21280
FD
1124#ifdef HAVE_LIBLTTNG_UST_CTL
1125 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1126 case LTTNG_DOMAIN_UST:
496fc78f
FD
1127 case LTTNG_DOMAIN_PYTHON:
1128 case LTTNG_DOMAIN_JUL:
1129 case LTTNG_DOMAIN_LOG4J:
a5a21280
FD
1130 pthread_mutex_lock(&the_event_notifier_counter.lock);
1131 the_event_notifier_counter.count++;
1132 if (the_event_notifier_counter.count == 1) {
1133 /*
1134 * On the first event notifier, we get a reference to
1135 * every existing UID entries. This ensures that the
1136 * entries are kept around if there are still
1137 * registered event notifiers but no apps.
1138 */
1139 get_ref_all_ust_error_accounting_entry();
1140 }
1141 pthread_mutex_unlock(&the_event_notifier_counter.lock);
1142 break;
1143 default:
1144 break;
1145 }
1146#endif /* HAVE_LIBLTTNG_UST_CTL */
1147
90aa04a1
FD
1148end:
1149 return status;
1150}
1151
28ab034a
JG
1152static enum event_notifier_error_accounting_status
1153event_notifier_error_accounting_kernel_get_count(const struct lttng_trigger *trigger,
1154 uint64_t *count)
90aa04a1 1155{
b8e2fb80 1156 struct lttng_kernel_abi_counter_aggregate counter_aggregate = {};
90aa04a1
FD
1157 enum event_notifier_error_accounting_status status;
1158 uint64_t error_counter_index;
1159 int ret;
1160
28ab034a
JG
1161 status = get_error_counter_index_for_token(
1162 &kernel_state, lttng_trigger_get_tracer_token(trigger), &error_counter_index);
90aa04a1 1163 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
533a90fb 1164 ERR("Error getting index for token: status=%s",
28ab034a 1165 error_accounting_status_str(status));
90aa04a1
FD
1166 goto end;
1167 }
1168
1169 counter_aggregate.index.number_dimensions = 1;
1170 counter_aggregate.index.dimension_indexes[0] = error_counter_index;
1171
a0377dfe 1172 LTTNG_ASSERT(kernel_error_accounting_entry.error_counter_fd);
90aa04a1 1173
28ab034a
JG
1174 ret = kernctl_counter_get_aggregate_value(kernel_error_accounting_entry.error_counter_fd,
1175 &counter_aggregate);
90aa04a1
FD
1176 if (ret || counter_aggregate.value.value < 0) {
1177 uid_t trigger_owner_uid;
1178 const char *trigger_name;
533a90fb 1179
28ab034a 1180 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
90aa04a1
FD
1181
1182 if (counter_aggregate.value.value < 0) {
1183 ERR("Invalid negative event notifier error counter value: trigger owner = %d, trigger name = '%s', value = %" PRId64,
28ab034a
JG
1184 trigger_owner_uid,
1185 trigger_name,
1186 counter_aggregate.value.value);
90aa04a1
FD
1187 } else {
1188 ERR("Failed to getting event notifier error count: trigger owner = %d, trigger name = '%s', ret = %d",
28ab034a
JG
1189 trigger_owner_uid,
1190 trigger_name,
1191 ret);
90aa04a1
FD
1192 }
1193
1194 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_ERR;
1195 goto end;
1196 }
1197
1198 /* Error count can't be negative. */
a0377dfe 1199 LTTNG_ASSERT(counter_aggregate.value.value >= 0);
90aa04a1
FD
1200 *count = (uint64_t) counter_aggregate.value.value;
1201
1202 status = EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
1203
1204end:
1205 return status;
1206}
1207
1208enum event_notifier_error_accounting_status
28ab034a 1209event_notifier_error_accounting_get_count(const struct lttng_trigger *trigger, uint64_t *count)
90aa04a1
FD
1210{
1211 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1212 case LTTNG_DOMAIN_KERNEL:
28ab034a 1213 return event_notifier_error_accounting_kernel_get_count(trigger, count);
90aa04a1 1214 case LTTNG_DOMAIN_UST:
496fc78f
FD
1215 case LTTNG_DOMAIN_PYTHON:
1216 case LTTNG_DOMAIN_JUL:
1217 case LTTNG_DOMAIN_LOG4J:
533a90fb 1218#ifdef HAVE_LIBLTTNG_UST_CTL
28ab034a 1219 return event_notifier_error_accounting_ust_get_count(trigger, count);
533a90fb 1220#else
43cee6f9 1221 *count = 0;
90aa04a1 1222 return EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK;
533a90fb 1223#endif /* HAVE_LIBLTTNG_UST_CTL */
90aa04a1
FD
1224 default:
1225 abort();
1226 }
1227}
1228
28ab034a 1229static enum event_notifier_error_accounting_status
90aa04a1
FD
1230event_notifier_error_accounting_clear(const struct lttng_trigger *trigger)
1231{
1232 switch (lttng_trigger_get_underlying_domain_type_restriction(trigger)) {
1233 case LTTNG_DOMAIN_KERNEL:
1234 return event_notifier_error_accounting_kernel_clear(trigger);
1235 case LTTNG_DOMAIN_UST:
496fc78f
FD
1236 case LTTNG_DOMAIN_PYTHON:
1237 case LTTNG_DOMAIN_JUL:
1238 case LTTNG_DOMAIN_LOG4J:
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{
28ab034a 1251 struct index_ht_entry *entry = caa_container_of(head, struct 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
56047f5a
JG
1264 lttng::urcu::read_lock_guard read_lock;
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:
761ffce2 1283 state = &ust_state;
a5a21280
FD
1284
1285 pthread_mutex_lock(&the_event_notifier_counter.lock);
1286 the_event_notifier_counter.count--;
1287 if (the_event_notifier_counter.count == 0) {
a5a21280
FD
1288 /*
1289 * When unregistering the last event notifier, put one
1290 * reference to every uid entries on the behalf of all
1291 * event notifiers.
1292 */
1293 put_ref_all_ust_error_accounting_entry();
1294 }
1295
1296 pthread_mutex_unlock(&the_event_notifier_counter.lock);
1297
761ffce2 1298 break;
a5a21280 1299#endif /* HAVE_LIBLTTNG_UST_CTL */
761ffce2
FD
1300 default:
1301 abort();
1302 }
1303
761ffce2 1304 lttng_ht_lookup(state->indices_ht, &tracer_token, &iter);
90aa04a1 1305 node = lttng_ht_iter_get_node_u64(&iter);
533a90fb 1306 if (node) {
44d0e2f1 1307 int del_ret;
0114db0e 1308 struct index_ht_entry *index_entry =
28ab034a 1309 lttng::utils::container_of(node, &index_ht_entry::node);
533a90fb
FD
1310 enum lttng_index_allocator_status index_alloc_status;
1311
90aa04a1 1312 index_alloc_status = lttng_index_allocator_release(
28ab034a 1313 state->index_allocator, index_entry->error_counter_index);
90aa04a1 1314 if (index_alloc_status != LTTNG_INDEX_ALLOCATOR_STATUS_OK) {
533a90fb
FD
1315 uid_t trigger_owner_uid;
1316 const char *trigger_name;
1317
28ab034a 1318 get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
533a90fb 1319
28ab034a
JG
1320 ERR("Failed to release event notifier error counter index: index = %" PRIu64
1321 ", trigger name = '%s', trigger owner uid = %d",
1322 index_entry->error_counter_index,
1323 trigger_name,
1324 (int) trigger_owner_uid);
533a90fb 1325 /* Don't exit, perform the rest of the clean-up. */
90aa04a1
FD
1326 }
1327
761ffce2 1328 del_ret = lttng_ht_del(state->indices_ht, &iter);
a0377dfe 1329 LTTNG_ASSERT(!del_ret);
90aa04a1
FD
1330 call_rcu(&index_entry->rcu_head, free_index_ht_entry);
1331 }
a5a21280 1332end:
56047f5a 1333 return;
90aa04a1
FD
1334}
1335
cd9adb8b 1336void event_notifier_error_accounting_fini()
90aa04a1 1337{
a5a21280
FD
1338 if (kernel_error_accounting_entry.error_counter_fd) {
1339 const int ret = close(kernel_error_accounting_entry.error_counter_fd);
90aa04a1
FD
1340
1341 if (ret) {
1342 PERROR("Failed to close kernel event notifier error counter");
1343 }
1344 }
1345
533a90fb
FD
1346 lttng_ht_destroy(error_counter_uid_ht);
1347
761ffce2
FD
1348 fini_error_accounting_state(&kernel_state);
1349 fini_error_accounting_state(&ust_state);
90aa04a1 1350}
This page took 0.1222 seconds and 4 git commands to generate.