1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * in kernel monitor support: allows rv to control in-kernel monitors.
4 *
5 * Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
6 */
7 #include <getopt.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <unistd.h>
13 #include <dirent.h>
14
15 #include <trace.h>
16 #include <utils.h>
17 #include <rv.h>
18
19 static int config_has_id;
20 static int config_is_container;
21 static int config_my_pid;
22 static int config_trace;
23
24 static char *config_initial_reactor;
25 static char *config_reactor;
26
27 /*
28 * __ikm_read_enable - reads monitor's enable status
29 *
30 * __does not log errors.
31 *
32 * Returns the current status, or -1 if the monitor does not exist,
33 * __hence not logging errors.
34 */
__ikm_read_enable(char * monitor_name)35 static int __ikm_read_enable(char *monitor_name)
36 {
37 char path[MAX_PATH];
38 long long enabled;
39 int retval;
40
41 snprintf(path, MAX_PATH, "rv/monitors/%s/enable", monitor_name);
42
43 retval = tracefs_instance_file_read_number(NULL, path, &enabled);
44 if (retval < 0)
45 return -1;
46
47 return enabled;
48 }
49
50 /*
51 * __ikm_find_monitor - find the full name of a possibly nested module
52 *
53 * __does not log errors.
54 *
55 * Returns 1 if we found the monitor, -1 on error and 0 if it does not exist.
56 * The string out_name is populated with the full name, which can be
57 * equal to monitor_name or container/monitor_name if nested
58 */
__ikm_find_monitor_name(char * monitor_name,char * out_name)59 static int __ikm_find_monitor_name(char *monitor_name, char *out_name)
60 {
61 char *available_monitors, container[MAX_DA_NAME_LEN+1], *cursor, *end;
62 int retval = 1;
63
64 available_monitors = tracefs_instance_file_read(NULL, "rv/available_monitors", NULL);
65 if (!available_monitors)
66 return -1;
67
68 cursor = strstr(available_monitors, monitor_name);
69 if (!cursor) {
70 retval = 0;
71 goto out_free;
72 }
73
74 for (; cursor > available_monitors; cursor--)
75 if (*(cursor-1) == '\n')
76 break;
77 end = strstr(cursor, "\n");
78 memcpy(out_name, cursor, end-cursor);
79 out_name[end-cursor] = '\0';
80
81 cursor = strstr(out_name, ":");
82 if (cursor)
83 *cursor = '/';
84 else {
85 sprintf(container, "%s:", monitor_name);
86 if (strstr(available_monitors, container))
87 config_is_container = 1;
88 }
89
90 out_free:
91 free(available_monitors);
92 return retval;
93 }
94
95 /*
96 * ikm_read_enable - reads monitor's enable status
97 *
98 * Returns the current status, or -1 on error.
99 */
ikm_read_enable(char * monitor_name)100 static int ikm_read_enable(char *monitor_name)
101 {
102 int enabled;
103
104 enabled = __ikm_read_enable(monitor_name);
105 if (enabled < 0) {
106 err_msg("ikm: fail read enabled: %d\n", enabled);
107 return -1;
108 }
109
110 debug_msg("ikm: read enabled: %d\n", enabled);
111
112 return enabled;
113 }
114
115 /*
116 * ikm_write_enable - write to the monitor's enable file
117 *
118 * Return the number of bytes written, -1 on error.
119 */
ikm_write_enable(char * monitor_name,char * enable_disable)120 static int ikm_write_enable(char *monitor_name, char *enable_disable)
121 {
122 char path[MAX_PATH];
123 int retval;
124
125 debug_msg("ikm: writing enabled: %s\n", enable_disable);
126
127 snprintf(path, MAX_PATH, "rv/monitors/%s/enable", monitor_name);
128 retval = tracefs_instance_file_write(NULL, path, enable_disable);
129 if (retval < strlen(enable_disable)) {
130 err_msg("ikm: writing enabled: %s\n", enable_disable);
131 return -1;
132 }
133
134 return retval;
135 }
136
137 /*
138 * ikm_enable - enable a monitor
139 *
140 * Returns -1 on failure. Success otherwise.
141 */
ikm_enable(char * monitor_name)142 static int ikm_enable(char *monitor_name)
143 {
144 return ikm_write_enable(monitor_name, "1");
145 }
146
147 /*
148 * ikm_disable - disable a monitor
149 *
150 * Returns -1 on failure. Success otherwise.
151 */
ikm_disable(char * monitor_name)152 static int ikm_disable(char *monitor_name)
153 {
154 return ikm_write_enable(monitor_name, "0");
155 }
156
157 /*
158 * ikm_read_desc - read monitors' description
159 *
160 * Return a dynamically allocated string with the monitor's
161 * description, NULL otherwise.
162 */
ikm_read_desc(char * monitor_name)163 static char *ikm_read_desc(char *monitor_name)
164 {
165 char path[MAX_PATH];
166 char *desc;
167
168 snprintf(path, MAX_PATH, "rv/monitors/%s/desc", monitor_name);
169 desc = tracefs_instance_file_read(NULL, path, NULL);
170 if (!desc) {
171 err_msg("ikm: error reading monitor %s desc\n", monitor_name);
172 return NULL;
173 }
174
175 *strstr(desc, "\n") = '\0';
176
177 return desc;
178 }
179
180 /*
181 * ikm_fill_monitor_definition - fill monitor's definition
182 *
183 * Returns -1 on error, 1 if the monitor does not belong in the container, 0 otherwise.
184 * container can be NULL
185 */
ikm_fill_monitor_definition(char * name,struct monitor * ikm,char * container)186 static int ikm_fill_monitor_definition(char *name, struct monitor *ikm, char *container)
187 {
188 int enabled;
189 char *desc, *nested_name;
190
191 nested_name = strstr(name, ":");
192 if (nested_name) {
193 /* it belongs in container if it starts with "container:" */
194 if (container && strstr(name, container) != name)
195 return 1;
196 *nested_name = '/';
197 ++nested_name;
198 ikm->nested = 1;
199 } else {
200 if (container)
201 return 1;
202 nested_name = name;
203 ikm->nested = 0;
204 }
205
206 enabled = ikm_read_enable(name);
207 if (enabled < 0) {
208 err_msg("ikm: monitor %s fail to read enable file, bug?\n", name);
209 return -1;
210 }
211
212 desc = ikm_read_desc(name);
213 if (!desc) {
214 err_msg("ikm: monitor %s does not have desc file, bug?\n", name);
215 return -1;
216 }
217
218 strncpy(ikm->name, nested_name, MAX_DA_NAME_LEN);
219 ikm->enabled = enabled;
220 strncpy(ikm->desc, desc, MAX_DESCRIPTION);
221
222 free(desc);
223
224 return 0;
225 }
226
227 /*
228 * ikm_write_reactor - switch the reactor to *reactor
229 *
230 * Return the number or characters written, -1 on error.
231 */
ikm_write_reactor(char * monitor_name,char * reactor)232 static int ikm_write_reactor(char *monitor_name, char *reactor)
233 {
234 char path[MAX_PATH];
235 int retval;
236
237 snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name);
238 retval = tracefs_instance_file_write(NULL, path, reactor);
239 debug_msg("ikm: write \"%s\" reactors: %d\n", reactor, retval);
240
241 return retval;
242 }
243
244 /*
245 * ikm_read_reactor - read the reactors file
246 *
247 * Returns a dynamically allocated string with monitor's
248 * available reactors, or NULL on error.
249 */
ikm_read_reactor(char * monitor_name)250 static char *ikm_read_reactor(char *monitor_name)
251 {
252 char path[MAX_PATH];
253 char *reactors;
254
255 snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name);
256 reactors = tracefs_instance_file_read(NULL, path, NULL);
257 if (!reactors) {
258 err_msg("ikm: fail reading monitor's %s reactors file\n", monitor_name);
259 return NULL;
260 }
261
262 return reactors;
263 }
264
265 /*
266 * ikm_get_current_reactor - get the current enabled reactor
267 *
268 * Reads the reactors file and find the currently enabled
269 * [reactor].
270 *
271 * Returns a dynamically allocated memory with the current
272 * reactor. NULL otherwise.
273 */
ikm_get_current_reactor(char * monitor_name)274 static char *ikm_get_current_reactor(char *monitor_name)
275 {
276 char *reactors = ikm_read_reactor(monitor_name);
277 char *curr_reactor = NULL;
278 char *start;
279 char *end;
280
281 if (!reactors)
282 return NULL;
283
284 start = strstr(reactors, "[");
285 if (!start)
286 goto out_free;
287
288 start++;
289
290 end = strstr(start, "]");
291 if (!end)
292 goto out_free;
293
294 *end = '\0';
295
296 curr_reactor = calloc(strlen(start) + 1, sizeof(char));
297 if (!curr_reactor)
298 goto out_free;
299
300 strncpy(curr_reactor, start, strlen(start));
301 debug_msg("ikm: read current reactor %s\n", curr_reactor);
302
303 out_free:
304 free(reactors);
305
306 return curr_reactor;
307 }
308
ikm_has_id(char * monitor_name)309 static int ikm_has_id(char *monitor_name)
310 {
311 char path[MAX_PATH];
312 char *format;
313 int has_id;
314
315 snprintf(path, MAX_PATH, "events/rv/event_%s/format", monitor_name);
316 format = tracefs_instance_file_read(NULL, path, NULL);
317 if (!format) {
318 err_msg("ikm: fail reading monitor's %s format event file\n", monitor_name);
319 return -1;
320 }
321
322 /* print fmt: "%d: %s x %s -> %s %s", REC->id, ... */
323 has_id = !!strstr(format, "REC->id");
324
325 debug_msg("ikm: monitor %s has id: %s\n", monitor_name, has_id ? "yes" : "no");
326
327 free(format);
328
329 return has_id;
330 }
331
332 /**
333 * ikm_list_monitors - list all available monitors
334 *
335 * Returns 0 on success, -1 otherwise.
336 */
ikm_list_monitors(char * container)337 int ikm_list_monitors(char *container)
338 {
339 char *available_monitors;
340 struct monitor ikm = {0};
341 char *curr, *next;
342 int retval, list_monitor = 0;
343
344 available_monitors = tracefs_instance_file_read(NULL, "rv/available_monitors", NULL);
345
346 if (!available_monitors) {
347 err_msg("ikm: available monitors is not available, is CONFIG_RV enabled?\n");
348 return -1;
349 }
350
351 curr = available_monitors;
352 do {
353 next = strstr(curr, "\n");
354 *next = '\0';
355
356 retval = ikm_fill_monitor_definition(curr, &ikm, container);
357 if (retval < 0)
358 err_msg("ikm: error reading %d in kernel monitor, skipping\n", curr);
359
360 if (!retval) {
361 int indent = ikm.nested && !container;
362
363 list_monitor = 1;
364 printf("%s%-*s %s %s\n", indent ? " - " : "",
365 indent ? MAX_DA_NAME_LEN - 3 : MAX_DA_NAME_LEN,
366 ikm.name, ikm.desc, ikm.enabled ? "[ON]" : "[OFF]");
367 }
368 curr = ++next;
369
370 } while (strlen(curr));
371
372 if (!list_monitor) {
373 if (container)
374 printf("-- No monitor found in container %s --\n", container);
375 else
376 printf("-- No monitor found --\n");
377 }
378
379 free(available_monitors);
380
381 return 0;
382 }
383
ikm_print_header(struct trace_seq * s)384 static void ikm_print_header(struct trace_seq *s)
385 {
386 trace_seq_printf(s, "%16s-%-8s %5s %5s ", "<TASK>", "PID", "[CPU]", "TYPE");
387 if (config_has_id)
388 trace_seq_printf(s, "%8s ", "ID");
389
390 trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n",
391 "STATE",
392 "EVENT",
393 "NEXT_STATE",
394 "FINAL");
395
396 trace_seq_printf(s, "%16s %-8s %5s %5s ", " | ", " | ", " | ", " | ");
397
398 if (config_has_id)
399 trace_seq_printf(s, "%8s ", " | ");
400
401 trace_seq_printf(s, "%24s %-24s %-24s %s\n",
402 " | ",
403 " | ",
404 " | ",
405 "|");
406
407 }
408
409 /*
410 * ikm_event_handler - callback to handle event events
411 *
412 * Called any time a rv:"monitor"_event events is generated.
413 * It parses and prints event.
414 */
415 static int
ikm_event_handler(struct trace_seq * s,struct tep_record * record,struct tep_event * trace_event,void * context)416 ikm_event_handler(struct trace_seq *s, struct tep_record *record,
417 struct tep_event *trace_event, void *context)
418 {
419 /* if needed: struct trace_instance *inst = context; */
420 char *state, *event, *next_state;
421 unsigned long long final_state;
422 unsigned long long pid;
423 unsigned long long id;
424 int val;
425 bool missing_id;
426
427 if (config_has_id)
428 missing_id = tep_get_field_val(s, trace_event, "id", record, &id, 1);
429
430 tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1);
431
432 if (config_has_id && (config_my_pid == id))
433 return 0;
434 else if (config_my_pid && (config_my_pid == pid))
435 return 0;
436
437 tep_print_event(trace_event->tep, s, record, "%16s-%-8d [%.3d] ",
438 TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU);
439
440 if (config_is_container)
441 tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME);
442 else
443 trace_seq_printf(s, "event ");
444
445 if (config_has_id) {
446 if (missing_id)
447 /* placeholder if we are dealing with a mixed-type container*/
448 trace_seq_printf(s, " ");
449 else
450 trace_seq_printf(s, "%8llu ", id);
451 }
452
453 state = tep_get_field_raw(s, trace_event, "state", record, &val, 0);
454 event = tep_get_field_raw(s, trace_event, "event", record, &val, 0);
455 next_state = tep_get_field_raw(s, trace_event, "next_state", record, &val, 0);
456 tep_get_field_val(s, trace_event, "final_state", record, &final_state, 1);
457
458 trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n",
459 state,
460 event,
461 next_state,
462 final_state ? "Y" : "N");
463
464 trace_seq_do_printf(s);
465 trace_seq_reset(s);
466
467 return 0;
468 }
469
470 /*
471 * ikm_error_handler - callback to handle error events
472 *
473 * Called any time a rv:"monitor"_errors events is generated.
474 * It parses and prints event.
475 */
476 static int
ikm_error_handler(struct trace_seq * s,struct tep_record * record,struct tep_event * trace_event,void * context)477 ikm_error_handler(struct trace_seq *s, struct tep_record *record,
478 struct tep_event *trace_event, void *context)
479 {
480 unsigned long long pid, id;
481 int cpu = record->cpu;
482 char *state, *event;
483 int val;
484 bool missing_id;
485
486 if (config_has_id)
487 missing_id = tep_get_field_val(s, trace_event, "id", record, &id, 1);
488
489 tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1);
490
491 if (config_has_id && config_my_pid == id)
492 return 0;
493 else if (config_my_pid == pid)
494 return 0;
495
496 trace_seq_printf(s, "%8lld [%03d] ", pid, cpu);
497
498 if (config_is_container)
499 tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME);
500 else
501 trace_seq_printf(s, "error ");
502
503 if (config_has_id) {
504 if (missing_id)
505 /* placeholder if we are dealing with a mixed-type container*/
506 trace_seq_printf(s, " ");
507 else
508 trace_seq_printf(s, "%8llu ", id);
509 }
510
511 state = tep_get_field_raw(s, trace_event, "state", record, &val, 0);
512 event = tep_get_field_raw(s, trace_event, "event", record, &val, 0);
513
514 trace_seq_printf(s, "%24s x %s\n", state, event);
515
516 trace_seq_do_printf(s);
517 trace_seq_reset(s);
518
519 return 0;
520 }
521
ikm_enable_trace_events(char * monitor_name,struct trace_instance * inst)522 static int ikm_enable_trace_events(char *monitor_name, struct trace_instance *inst)
523 {
524 char event[MAX_DA_NAME_LEN + 7]; /* max(error_,event_) + '0' = 7 */
525 int retval;
526
527 snprintf(event, sizeof(event), "event_%s", monitor_name);
528 retval = tracefs_event_enable(inst->inst, "rv", event);
529 if (retval)
530 return -1;
531
532 tep_register_event_handler(inst->tep, -1, "rv", event,
533 ikm_event_handler, NULL);
534
535 snprintf(event, sizeof(event), "error_%s", monitor_name);
536 retval = tracefs_event_enable(inst->inst, "rv", event);
537 if (retval)
538 return -1;
539
540 tep_register_event_handler(inst->tep, -1, "rv", event,
541 ikm_error_handler, NULL);
542
543 /* set if at least 1 monitor has id in case of a container */
544 config_has_id = ikm_has_id(monitor_name);
545 if (config_has_id < 0)
546 return -1;
547
548
549 return 0;
550 }
551
ikm_enable_trace_container(char * monitor_name,struct trace_instance * inst)552 static int ikm_enable_trace_container(char *monitor_name,
553 struct trace_instance *inst)
554 {
555 DIR *dp;
556 char *abs_path, rv_path[MAX_PATH];
557 struct dirent *ep;
558 int retval = 0;
559
560 snprintf(rv_path, MAX_PATH, "rv/monitors/%s", monitor_name);
561 abs_path = tracefs_instance_get_file(NULL, rv_path);
562 if (!abs_path)
563 return -1;
564 dp = opendir(abs_path);
565 if (!dp)
566 goto out_free;
567
568 while (!retval && (ep = readdir(dp))) {
569 if (ep->d_type != DT_DIR || ep->d_name[0] == '.')
570 continue;
571 retval = ikm_enable_trace_events(ep->d_name, inst);
572 }
573
574 closedir(dp);
575 out_free:
576 free(abs_path);
577 return retval;
578 }
579
580 /*
581 * ikm_setup_trace_instance - set up a tracing instance to collect data
582 *
583 * Create a trace instance, enable rv: events and enable the trace.
584 *
585 * Returns the trace_instance * with all set, NULL otherwise.
586 */
ikm_setup_trace_instance(char * monitor_name)587 static struct trace_instance *ikm_setup_trace_instance(char *monitor_name)
588 {
589 struct trace_instance *inst;
590 int retval;
591
592 if (!config_trace)
593 return NULL;
594
595 /* alloc data */
596 inst = calloc(1, sizeof(*inst));
597 if (!inst) {
598 err_msg("ikm: failed to allocate trace instance");
599 goto out_err;
600 }
601
602 retval = trace_instance_init(inst, monitor_name);
603 if (retval)
604 goto out_free;
605
606 if (config_is_container)
607 retval = ikm_enable_trace_container(monitor_name, inst);
608 else
609 retval = ikm_enable_trace_events(monitor_name, inst);
610 if (retval)
611 goto out_inst;
612
613 /* ready to enable */
614 tracefs_trace_on(inst->inst);
615
616 return inst;
617
618 out_inst:
619 trace_instance_destroy(inst);
620 out_free:
621 free(inst);
622 out_err:
623 return NULL;
624 }
625
626 /**
627 * ikm_destroy_trace_instance - destroy a previously created instance
628 */
ikm_destroy_trace_instance(struct trace_instance * inst)629 static void ikm_destroy_trace_instance(struct trace_instance *inst)
630 {
631 if (!inst)
632 return;
633
634 trace_instance_destroy(inst);
635 free(inst);
636 }
637
638 /*
639 * ikm_usage_print_reactors - print all available reactors, one per line.
640 */
ikm_usage_print_reactors(void)641 static void ikm_usage_print_reactors(void)
642 {
643 char *reactors = tracefs_instance_file_read(NULL, "rv/available_reactors", NULL);
644 char *start, *end;
645
646 if (!reactors)
647 return;
648
649 fprintf(stderr, " available reactors:");
650
651 start = reactors;
652 end = strstr(start, "\n");
653
654 while (end) {
655 *end = '\0';
656
657 fprintf(stderr, " %s", start);
658
659 start = ++end;
660 end = strstr(start, "\n");
661 }
662
663 fprintf(stderr, "\n");
664 }
665 /*
666 * ikm_usage - print usage
667 */
ikm_usage(int exit_val,char * monitor_name,const char * fmt,...)668 static void ikm_usage(int exit_val, char *monitor_name, const char *fmt, ...)
669 {
670
671 char message[1024];
672 va_list ap;
673 int i;
674
675 static const char *const usage[] = {
676 "",
677 " -h/--help: print this menu and the reactor list",
678 " -r/--reactor 'reactor': enables the 'reactor'",
679 " -s/--self: when tracing (-t), also trace rv command",
680 " -t/--trace: trace monitor's event",
681 " -v/--verbose: print debug messages",
682 "",
683 NULL,
684 };
685
686 va_start(ap, fmt);
687 vsnprintf(message, sizeof(message), fmt, ap);
688 va_end(ap);
689
690 fprintf(stderr, " %s\n", message);
691
692 fprintf(stderr, "\n usage: rv mon %s [-h] [-q] [-r reactor] [-s] [-v]", monitor_name);
693
694 for (i = 0; usage[i]; i++)
695 fprintf(stderr, "%s\n", usage[i]);
696
697 ikm_usage_print_reactors();
698 exit(exit_val);
699 }
700
701 /*
702 * parse_arguments - parse arguments and set config
703 */
parse_arguments(char * monitor_name,int argc,char ** argv)704 static int parse_arguments(char *monitor_name, int argc, char **argv)
705 {
706 int c, retval;
707
708 config_my_pid = getpid();
709
710 while (1) {
711 static struct option long_options[] = {
712 {"help", no_argument, 0, 'h'},
713 {"reactor", required_argument, 0, 'r'},
714 {"self", no_argument, 0, 's'},
715 {"trace", no_argument, 0, 't'},
716 {"verbose", no_argument, 0, 'v'},
717 {0, 0, 0, 0}
718 };
719
720 /* getopt_long stores the option index here. */
721 int option_index = 0;
722
723 c = getopt_long(argc, argv, "hr:stv", long_options, &option_index);
724
725 /* detect the end of the options. */
726 if (c == -1)
727 break;
728
729 switch (c) {
730 case 'h':
731 ikm_usage(0, monitor_name, "help:");
732 break;
733 case 'r':
734 config_reactor = optarg;
735 break;
736 case 's':
737 config_my_pid = 0;
738 break;
739 case 't':
740 config_trace = 1;
741 break;
742 case 'v':
743 config_debug = 1;
744 break;
745 }
746 }
747
748 if (config_reactor) {
749 config_initial_reactor = ikm_get_current_reactor(monitor_name);
750 if (!config_initial_reactor)
751 ikm_usage(1, monitor_name,
752 "ikm: failed to read current reactor, are reactors enabled?");
753
754 retval = ikm_write_reactor(monitor_name, config_reactor);
755 if (retval <= 0)
756 ikm_usage(1, monitor_name,
757 "ikm: failed to set %s reactor, is it available?",
758 config_reactor);
759 }
760
761 debug_msg("ikm: my pid is %d\n", config_my_pid);
762
763 return 0;
764 }
765
766 /**
767 * ikm_run_monitor - apply configs and run the monitor
768 *
769 * Returns 1 if a monitor was found an executed, 0 if no
770 * monitors were found, or -1 on error.
771 */
ikm_run_monitor(char * monitor_name,int argc,char ** argv)772 int ikm_run_monitor(char *monitor_name, int argc, char **argv)
773 {
774 struct trace_instance *inst = NULL;
775 char *nested_name, full_name[2*MAX_DA_NAME_LEN];
776 int retval;
777
778 nested_name = strstr(monitor_name, ":");
779 if (nested_name)
780 ++nested_name;
781 else
782 nested_name = monitor_name;
783
784 retval = __ikm_find_monitor_name(monitor_name, full_name);
785 if (!retval)
786 return 0;
787 if (retval < 0) {
788 err_msg("ikm: error finding monitor %s\n", nested_name);
789 return -1;
790 }
791
792 retval = __ikm_read_enable(full_name);
793 if (retval) {
794 err_msg("ikm: monitor %s (in-kernel) is already enabled\n", nested_name);
795 return -1;
796 }
797
798 /* we should be good to go */
799 retval = parse_arguments(full_name, argc, argv);
800 if (retval)
801 ikm_usage(1, nested_name, "ikm: failed parsing arguments");
802
803 if (config_trace) {
804 inst = ikm_setup_trace_instance(nested_name);
805 if (!inst)
806 return -1;
807 }
808
809 retval = ikm_enable(full_name);
810 if (retval < 0)
811 goto out_free_instance;
812
813 if (config_trace)
814 ikm_print_header(inst->seq);
815
816 while (!should_stop()) {
817 if (config_trace) {
818 retval = tracefs_iterate_raw_events(inst->tep,
819 inst->inst,
820 NULL,
821 0,
822 collect_registered_events,
823 inst);
824 if (retval) {
825 err_msg("ikm: error reading trace buffer\n");
826 break;
827 }
828 }
829
830 sleep(1);
831 }
832
833 ikm_disable(full_name);
834 ikm_destroy_trace_instance(inst);
835
836 if (config_reactor && config_initial_reactor)
837 ikm_write_reactor(full_name, config_initial_reactor);
838
839 return 1;
840
841 out_free_instance:
842 ikm_destroy_trace_instance(inst);
843 if (config_reactor && config_initial_reactor)
844 ikm_write_reactor(full_name, config_initial_reactor);
845 return -1;
846 }
847