xref: /linux/tools/verification/rv/src/in_kernel.c (revision 88221ac0d560700b50493aedc768f728aa585141)
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