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