xref: /linux/tools/verification/rv/src/in_kernel.c (revision 08904765bb941f98306ae6841c33cfd299343faf)
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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, sizeof(ikm->name) - 1);
219 	ikm->name[sizeof(ikm->name) - 1] = '\0';
220 	ikm->enabled = enabled;
221 	strncpy(ikm->desc, desc, sizeof(ikm->desc) - 1);
222 	ikm->desc[sizeof(ikm->desc) - 1] = '\0';
223 	free(desc);
224 
225 	return 0;
226 }
227 
228 /*
229  * ikm_write_reactor - switch the reactor to *reactor
230  *
231  * Return the number or characters written, -1 on error.
232  */
233 static int ikm_write_reactor(char *monitor_name, char *reactor)
234 {
235 	char path[MAX_PATH];
236 	int retval;
237 
238 	snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name);
239 	retval = tracefs_instance_file_write(NULL, path, reactor);
240 	debug_msg("ikm: write \"%s\" reactors: %d\n", reactor, retval);
241 
242 	return retval;
243 }
244 
245 /*
246  * ikm_read_reactor - read the reactors file
247  *
248  * Returns a dynamically allocated string with monitor's
249  * available reactors, or NULL on error.
250  */
251 static char *ikm_read_reactor(char *monitor_name)
252 {
253 	char path[MAX_PATH];
254 	char *reactors;
255 
256 	snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name);
257 	reactors = tracefs_instance_file_read(NULL, path, NULL);
258 	if (!reactors) {
259 		err_msg("ikm: fail reading monitor's %s reactors file\n", monitor_name);
260 		return NULL;
261 	}
262 
263 	return reactors;
264 }
265 
266 /*
267  * ikm_get_current_reactor - get the current enabled reactor
268  *
269  * Reads the reactors file and find the currently enabled
270  * [reactor].
271  *
272  * Returns a dynamically allocated memory with the current
273  * reactor. NULL otherwise.
274  */
275 static char *ikm_get_current_reactor(char *monitor_name)
276 {
277 	char *reactors = ikm_read_reactor(monitor_name);
278 	char *curr_reactor = NULL;
279 	char *start;
280 	char *end;
281 
282 	if (!reactors)
283 		return NULL;
284 
285 	start = strstr(reactors, "[");
286 	if (!start)
287 		goto out_free;
288 
289 	start++;
290 
291 	end = strstr(start, "]");
292 	if (!end)
293 		goto out_free;
294 
295 	*end = '\0';
296 
297 	curr_reactor = calloc(strlen(start) + 1, sizeof(char));
298 	if (!curr_reactor)
299 		goto out_free;
300 
301 	strncpy(curr_reactor, start, strlen(start));
302 	debug_msg("ikm: read current reactor %s\n", curr_reactor);
303 
304 out_free:
305 	free(reactors);
306 
307 	return curr_reactor;
308 }
309 
310 static int ikm_has_id(char *monitor_name)
311 {
312 	char path[MAX_PATH];
313 	char *format;
314 	int has_id;
315 
316 	snprintf(path, MAX_PATH, "events/rv/event_%s/format", monitor_name);
317 	format = tracefs_instance_file_read(NULL, path, NULL);
318 	if (!format) {
319 		err_msg("ikm: fail reading monitor's %s format event file\n", monitor_name);
320 		return -1;
321 	}
322 
323 	/* print fmt: "%d: %s x %s -> %s %s", REC->id, ... */
324 	has_id = !!strstr(format, "REC->id");
325 
326 	debug_msg("ikm: monitor %s has id: %s\n", monitor_name, has_id ? "yes" : "no");
327 
328 	free(format);
329 
330 	return has_id;
331 }
332 
333 /**
334  * ikm_list_monitors - list all available monitors
335  *
336  * Returns 0 on success, -1 otherwise.
337  */
338 int ikm_list_monitors(char *container)
339 {
340 	char *available_monitors;
341 	struct monitor ikm = {0};
342 	char *curr, *next;
343 	int retval, list_monitor = 0;
344 
345 	available_monitors = tracefs_instance_file_read(NULL, "rv/available_monitors", NULL);
346 
347 	if (!available_monitors) {
348 		err_msg("ikm: available monitors is not available, is CONFIG_RV enabled?\n");
349 		return -1;
350 	}
351 
352 	curr = available_monitors;
353 	do {
354 		next = strstr(curr, "\n");
355 		*next = '\0';
356 
357 		retval = ikm_fill_monitor_definition(curr, &ikm, container);
358 		if (retval < 0)
359 			err_msg("ikm: error reading %d in kernel monitor, skipping\n", curr);
360 
361 		if (!retval) {
362 			int indent = ikm.nested && !container;
363 
364 			list_monitor = 1;
365 			printf("%s%-*s %s %s\n", indent ? " - " : "",
366 			       indent ? MAX_DA_NAME_LEN - 3 : MAX_DA_NAME_LEN,
367 			       ikm.name, ikm.desc, ikm.enabled ? "[ON]" : "[OFF]");
368 		}
369 		curr = ++next;
370 
371 	} while (strlen(curr));
372 
373 	if (!list_monitor) {
374 		if (container)
375 			printf("-- No monitor found in container %s --\n", container);
376 		else
377 			printf("-- No monitor found --\n");
378 	}
379 
380 	free(available_monitors);
381 
382 	return 0;
383 }
384 
385 static void ikm_print_header(struct trace_seq *s)
386 {
387 	trace_seq_printf(s, "%16s-%-8s %5s %5s ", "<TASK>", "PID", "[CPU]", "TYPE");
388 	if (config_has_id)
389 		trace_seq_printf(s, "%8s ", "ID");
390 
391 	trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n",
392 			 "STATE",
393 			 "EVENT",
394 			 "NEXT_STATE",
395 			 "FINAL");
396 
397 	trace_seq_printf(s, "%16s %-8s %5s %5s ", " | ", " | ", " | ", " | ");
398 
399 	if (config_has_id)
400 		trace_seq_printf(s, "%8s ", " | ");
401 
402 	trace_seq_printf(s, "%24s   %-24s    %-24s %s\n",
403 			 " | ",
404 			 " | ",
405 			 " | ",
406 			 "|");
407 
408 }
409 
410 /*
411  * ikm_event_handler - callback to handle event events
412  *
413  * Called any time a rv:"monitor"_event events is generated.
414  * It parses and prints event.
415  */
416 static int
417 ikm_event_handler(struct trace_seq *s, struct tep_record *record,
418 		  struct tep_event *trace_event, void *context)
419 {
420 	/* if needed: struct trace_instance *inst = context; */
421 	char *state, *event, *next_state;
422 	unsigned long long final_state;
423 	unsigned long long pid;
424 	unsigned long long id;
425 	int val;
426 	bool missing_id;
427 
428 	if (config_has_id)
429 		missing_id = tep_get_field_val(s, trace_event, "id", record, &id, 1);
430 
431 	tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1);
432 
433 	if (config_has_id && (config_my_pid == id))
434 		return 0;
435 	else if (config_my_pid == pid)
436 		return 0;
437 
438 	tep_print_event(trace_event->tep, s, record, "%16s-%-8d [%.3d] ",
439 			TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU);
440 
441 	if (config_is_container)
442 		tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME);
443 	else
444 		trace_seq_printf(s, "event ");
445 
446 	if (config_has_id) {
447 		if (missing_id)
448 			/* placeholder if we are dealing with a mixed-type container*/
449 			trace_seq_printf(s, "        ");
450 		else
451 			trace_seq_printf(s, "%8llu ", id);
452 	}
453 
454 	state = tep_get_field_raw(s, trace_event, "state", record, &val, 0);
455 	event = tep_get_field_raw(s, trace_event, "event", record, &val, 0);
456 	next_state = tep_get_field_raw(s, trace_event, "next_state", record, &val, 0);
457 	tep_get_field_val(s, trace_event, "final_state", record, &final_state, 1);
458 
459 	trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n",
460 			 state,
461 			 event,
462 			 next_state,
463 			 final_state ? "Y" : "N");
464 
465 	trace_seq_do_printf(s);
466 	trace_seq_reset(s);
467 
468 	return 0;
469 }
470 
471 /*
472  * ikm_error_handler - callback to handle error events
473  *
474  * Called any time a rv:"monitor"_errors events is generated.
475  * It parses and prints event.
476  */
477 static int
478 ikm_error_handler(struct trace_seq *s, struct tep_record *record,
479 		  struct tep_event *trace_event, void *context)
480 {
481 	unsigned long long pid, id;
482 	int cpu = record->cpu;
483 	char *state, *event;
484 	int val;
485 	bool missing_id;
486 
487 	if (config_has_id)
488 		missing_id = tep_get_field_val(s, trace_event, "id", record, &id, 1);
489 
490 	tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1);
491 
492 	if (config_has_id && config_my_pid == id)
493 		return 0;
494 	else if (config_my_pid == pid)
495 		return 0;
496 
497 	trace_seq_printf(s, "%8lld [%03d] ", pid, cpu);
498 
499 	if (config_is_container)
500 		tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME);
501 	else
502 		trace_seq_printf(s, "error ");
503 
504 	if (config_has_id) {
505 		if (missing_id)
506 			/* placeholder if we are dealing with a mixed-type container*/
507 			trace_seq_printf(s, "        ");
508 		else
509 			trace_seq_printf(s, "%8llu ", id);
510 	}
511 
512 	state = tep_get_field_raw(s, trace_event, "state", record, &val, 0);
513 	event = tep_get_field_raw(s, trace_event, "event", record, &val, 0);
514 
515 	trace_seq_printf(s, "%24s x %s\n", state, event);
516 
517 	trace_seq_do_printf(s);
518 	trace_seq_reset(s);
519 
520 	return 0;
521 }
522 
523 static int ikm_enable_trace_events(char *monitor_name, struct trace_instance *inst)
524 {
525 	char event[MAX_DA_NAME_LEN + 7]; /* max(error_,event_) + '0' = 7 */
526 	int retval;
527 
528 	snprintf(event, sizeof(event), "event_%s", monitor_name);
529 	retval = tracefs_event_enable(inst->inst, "rv",  event);
530 	if (retval)
531 		return -1;
532 
533 	tep_register_event_handler(inst->tep, -1, "rv", event,
534 				   ikm_event_handler, NULL);
535 
536 	snprintf(event, sizeof(event), "error_%s", monitor_name);
537 	retval = tracefs_event_enable(inst->inst, "rv", event);
538 	if (retval)
539 		return -1;
540 
541 	tep_register_event_handler(inst->tep, -1, "rv", event,
542 				   ikm_error_handler, NULL);
543 
544 	/* set if at least 1 monitor has id in case of a container */
545 	config_has_id = ikm_has_id(monitor_name);
546 	if (config_has_id < 0)
547 		return -1;
548 
549 
550 	return 0;
551 }
552 
553 static int ikm_enable_trace_container(char *monitor_name,
554 				      struct trace_instance *inst)
555 {
556 	DIR *dp;
557 	char *abs_path, rv_path[MAX_PATH];
558 	struct dirent *ep;
559 	int retval = 0;
560 
561 	snprintf(rv_path, MAX_PATH, "rv/monitors/%s", monitor_name);
562 	abs_path = tracefs_instance_get_file(NULL, rv_path);
563 	if (!abs_path)
564 		return -1;
565 	dp = opendir(abs_path);
566 	if (!dp)
567 		goto out_free;
568 
569 	while (!retval && (ep = readdir(dp))) {
570 		if (ep->d_type != DT_DIR || ep->d_name[0] == '.')
571 			continue;
572 		retval = ikm_enable_trace_events(ep->d_name, inst);
573 	}
574 
575 	closedir(dp);
576 out_free:
577 	free(abs_path);
578 	return retval;
579 }
580 
581 /*
582  * ikm_setup_trace_instance - set up a tracing instance to collect data
583  *
584  * Create a trace instance, enable rv: events and enable the trace.
585  *
586  * Returns the trace_instance * with all set, NULL otherwise.
587  */
588 static struct trace_instance *ikm_setup_trace_instance(char *monitor_name)
589 {
590 	struct trace_instance *inst;
591 	int retval;
592 
593 	if (!config_trace)
594 		return NULL;
595 
596 	/* alloc data */
597 	inst = calloc(1, sizeof(*inst));
598 	if (!inst) {
599 		err_msg("ikm: failed to allocate trace instance");
600 		goto out_err;
601 	}
602 
603 	retval = trace_instance_init(inst, monitor_name);
604 	if (retval)
605 		goto out_free;
606 
607 	if (config_is_container)
608 		retval = ikm_enable_trace_container(monitor_name, inst);
609 	else
610 		retval = ikm_enable_trace_events(monitor_name, inst);
611 	if (retval)
612 		goto out_inst;
613 
614 	/* ready to enable */
615 	tracefs_trace_on(inst->inst);
616 
617 	return inst;
618 
619 out_inst:
620 	trace_instance_destroy(inst);
621 out_free:
622 	free(inst);
623 out_err:
624 	return NULL;
625 }
626 
627 /**
628  * ikm_destroy_trace_instance - destroy a previously created instance
629  */
630 static void ikm_destroy_trace_instance(struct trace_instance *inst)
631 {
632 	if (!inst)
633 		return;
634 
635 	trace_instance_destroy(inst);
636 	free(inst);
637 }
638 
639 /*
640  * ikm_usage_print_reactors - print all available reactors, one per line.
641  */
642 static void ikm_usage_print_reactors(void)
643 {
644 	char *reactors = tracefs_instance_file_read(NULL, "rv/available_reactors", NULL);
645 	char *start, *end;
646 
647 	if (!reactors)
648 		return;
649 
650 	fprintf(stderr, "  available reactors:");
651 
652 	start = reactors;
653 	end = strstr(start, "\n");
654 
655 	while (end) {
656 		*end = '\0';
657 
658 		fprintf(stderr, " %s", start);
659 
660 		start = ++end;
661 		end = strstr(start, "\n");
662 	}
663 
664 	fprintf(stderr, "\n");
665 }
666 /*
667  * ikm_usage - print usage
668  */
669 static void ikm_usage(int exit_val, char *monitor_name, const char *fmt, ...)
670 {
671 
672 	char message[1024];
673 	va_list ap;
674 	int i;
675 
676 	static const char *const usage[] = {
677 		"",
678 		"	-h/--help: print this menu and the reactor list",
679 		"	-r/--reactor 'reactor': enables the 'reactor'",
680 		"	-s/--self: when tracing (-t), also trace rv command",
681 		"	-t/--trace: trace monitor's event",
682 		"	-v/--verbose: print debug messages",
683 		"",
684 		NULL,
685 	};
686 
687 	va_start(ap, fmt);
688 	vsnprintf(message, sizeof(message), fmt, ap);
689 	va_end(ap);
690 
691 	fprintf(stderr, "  %s\n", message);
692 
693 	fprintf(stderr, "\n  usage: rv mon %s [-h] [-q] [-r reactor] [-s] [-v]", monitor_name);
694 
695 	for (i = 0; usage[i]; i++)
696 		fprintf(stderr, "%s\n", usage[i]);
697 
698 	ikm_usage_print_reactors();
699 	exit(exit_val);
700 }
701 
702 /*
703  * parse_arguments - parse arguments and set config
704  */
705 static int parse_arguments(char *monitor_name, int argc, char **argv)
706 {
707 	int c, retval;
708 
709 	config_my_pid = getpid();
710 
711 	while (1) {
712 		static struct option long_options[] = {
713 			{"help",		no_argument,		0, 'h'},
714 			{"reactor",		required_argument,	0, 'r'},
715 			{"self",		no_argument,		0, 's'},
716 			{"trace",		no_argument,		0, 't'},
717 			{"verbose",		no_argument,		0, 'v'},
718 			{0, 0, 0, 0}
719 		};
720 
721 		/* getopt_long stores the option index here. */
722 		int option_index = 0;
723 
724 		c = getopt_long(argc, argv, "hr:stv", long_options, &option_index);
725 
726 		/* detect the end of the options. */
727 		if (c == -1)
728 			break;
729 
730 		switch (c) {
731 		case 'h':
732 			ikm_usage(0, monitor_name, "help:");
733 			break;
734 		case 'r':
735 			config_reactor = optarg;
736 			break;
737 		case 's':
738 			config_my_pid = -1;
739 			break;
740 		case 't':
741 			config_trace = 1;
742 			break;
743 		case 'v':
744 			config_debug = 1;
745 			break;
746 		}
747 	}
748 
749 	if (config_reactor) {
750 		config_initial_reactor = ikm_get_current_reactor(monitor_name);
751 		if (!config_initial_reactor)
752 			ikm_usage(1, monitor_name,
753 				  "ikm: failed to read current reactor, are reactors enabled?");
754 
755 		retval = ikm_write_reactor(monitor_name, config_reactor);
756 		if (retval <= 0)
757 			ikm_usage(1, monitor_name,
758 				  "ikm: failed to set %s reactor, is it available?",
759 				  config_reactor);
760 	}
761 
762 	debug_msg("ikm: my pid is %d\n", config_my_pid);
763 
764 	return 0;
765 }
766 
767 /**
768  * ikm_run_monitor - apply configs and run the monitor
769  *
770  * Returns 1 if a monitor was found an executed, 0 if no
771  * monitors were found, or -1 on error.
772  */
773 int ikm_run_monitor(char *monitor_name, int argc, char **argv)
774 {
775 	struct trace_instance *inst = NULL;
776 	char *nested_name, full_name[2*MAX_DA_NAME_LEN];
777 	int retval;
778 
779 	nested_name = strstr(monitor_name, ":");
780 	if (nested_name)
781 		++nested_name;
782 	else
783 		nested_name = monitor_name;
784 
785 	retval = __ikm_find_monitor_name(monitor_name, full_name);
786 	if (!retval)
787 		return 0;
788 	if (retval < 0) {
789 		err_msg("ikm: error finding monitor %s\n", nested_name);
790 		return -1;
791 	}
792 
793 	retval = __ikm_read_enable(full_name);
794 	if (retval) {
795 		err_msg("ikm: monitor %s (in-kernel) is already enabled\n", nested_name);
796 		return -1;
797 	}
798 
799 	/* we should be good to go */
800 	retval = parse_arguments(full_name, argc, argv);
801 	if (retval)
802 		ikm_usage(1, nested_name, "ikm: failed parsing arguments");
803 
804 	if (config_trace) {
805 		inst = ikm_setup_trace_instance(nested_name);
806 		if (!inst)
807 			return -1;
808 	}
809 
810 	retval = ikm_enable(full_name);
811 	if (retval < 0)
812 		goto out_free_instance;
813 
814 	if (config_trace)
815 		ikm_print_header(inst->seq);
816 
817 	while (!should_stop()) {
818 		if (config_trace) {
819 			retval = tracefs_iterate_raw_events(inst->tep,
820 							    inst->inst,
821 							    NULL,
822 							    0,
823 							    collect_registered_events,
824 							    inst);
825 			if (retval) {
826 				err_msg("ikm: error reading trace buffer\n");
827 				break;
828 			}
829 		}
830 
831 		sleep(1);
832 	}
833 
834 	ikm_disable(full_name);
835 	ikm_destroy_trace_instance(inst);
836 
837 	if (config_reactor && config_initial_reactor)
838 		ikm_write_reactor(full_name, config_initial_reactor);
839 
840 	return 1;
841 
842 out_free_instance:
843 	ikm_destroy_trace_instance(inst);
844 	if (config_reactor && config_initial_reactor)
845 		ikm_write_reactor(full_name, config_initial_reactor);
846 	return -1;
847 }
848