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