16d60f896SDaniel Bristot de Oliveira // SPDX-License-Identifier: GPL-2.0
26d60f896SDaniel Bristot de Oliveira /*
36d60f896SDaniel Bristot de Oliveira * in kernel monitor support: allows rv to control in-kernel monitors.
46d60f896SDaniel Bristot de Oliveira *
56d60f896SDaniel Bristot de Oliveira * Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <[email protected]>
66d60f896SDaniel Bristot de Oliveira */
76d60f896SDaniel Bristot de Oliveira #include <getopt.h>
86d60f896SDaniel Bristot de Oliveira #include <stdlib.h>
9eba321a1SGabriele Monaco #include <stdio.h>
106d60f896SDaniel Bristot de Oliveira #include <string.h>
116d60f896SDaniel Bristot de Oliveira #include <errno.h>
126d60f896SDaniel Bristot de Oliveira #include <unistd.h>
13eba321a1SGabriele Monaco #include <dirent.h>
146d60f896SDaniel Bristot de Oliveira
156d60f896SDaniel Bristot de Oliveira #include <trace.h>
166d60f896SDaniel Bristot de Oliveira #include <utils.h>
176d60f896SDaniel Bristot de Oliveira #include <rv.h>
186d60f896SDaniel Bristot de Oliveira
196d60f896SDaniel Bristot de Oliveira static int config_has_id;
20eba321a1SGabriele Monaco static int config_is_container;
216d60f896SDaniel Bristot de Oliveira static int config_my_pid;
226d60f896SDaniel Bristot de Oliveira static int config_trace;
236d60f896SDaniel Bristot de Oliveira
246d60f896SDaniel Bristot de Oliveira static char *config_initial_reactor;
256d60f896SDaniel Bristot de Oliveira static char *config_reactor;
266d60f896SDaniel Bristot de Oliveira
276d60f896SDaniel Bristot de Oliveira /*
286d60f896SDaniel Bristot de Oliveira * __ikm_read_enable - reads monitor's enable status
296d60f896SDaniel Bristot de Oliveira *
306d60f896SDaniel Bristot de Oliveira * __does not log errors.
316d60f896SDaniel Bristot de Oliveira *
326d60f896SDaniel Bristot de Oliveira * Returns the current status, or -1 if the monitor does not exist,
336d60f896SDaniel Bristot de Oliveira * __hence not logging errors.
346d60f896SDaniel Bristot de Oliveira */
__ikm_read_enable(char * monitor_name)356d60f896SDaniel Bristot de Oliveira static int __ikm_read_enable(char *monitor_name)
366d60f896SDaniel Bristot de Oliveira {
376d60f896SDaniel Bristot de Oliveira char path[MAX_PATH];
386d60f896SDaniel Bristot de Oliveira long long enabled;
396d60f896SDaniel Bristot de Oliveira int retval;
406d60f896SDaniel Bristot de Oliveira
416d60f896SDaniel Bristot de Oliveira snprintf(path, MAX_PATH, "rv/monitors/%s/enable", monitor_name);
426d60f896SDaniel Bristot de Oliveira
436d60f896SDaniel Bristot de Oliveira retval = tracefs_instance_file_read_number(NULL, path, &enabled);
446d60f896SDaniel Bristot de Oliveira if (retval < 0)
456d60f896SDaniel Bristot de Oliveira return -1;
466d60f896SDaniel Bristot de Oliveira
476d60f896SDaniel Bristot de Oliveira return enabled;
486d60f896SDaniel Bristot de Oliveira }
496d60f896SDaniel Bristot de Oliveira
506d60f896SDaniel Bristot de Oliveira /*
51eba321a1SGabriele Monaco * __ikm_find_monitor - find the full name of a possibly nested module
52eba321a1SGabriele Monaco *
53eba321a1SGabriele Monaco * __does not log errors.
54eba321a1SGabriele Monaco *
55eba321a1SGabriele Monaco * Returns 1 if we found the monitor, -1 on error and 0 if it does not exist.
56eba321a1SGabriele Monaco * The string out_name is populated with the full name, which can be
57eba321a1SGabriele Monaco * equal to monitor_name or container/monitor_name if nested
58eba321a1SGabriele Monaco */
__ikm_find_monitor_name(char * monitor_name,char * out_name)59eba321a1SGabriele Monaco static int __ikm_find_monitor_name(char *monitor_name, char *out_name)
60eba321a1SGabriele Monaco {
61eba321a1SGabriele Monaco char *available_monitors, container[MAX_DA_NAME_LEN+1], *cursor, *end;
62eba321a1SGabriele Monaco int retval = 1;
63eba321a1SGabriele Monaco
64eba321a1SGabriele Monaco available_monitors = tracefs_instance_file_read(NULL, "rv/available_monitors", NULL);
65eba321a1SGabriele Monaco if (!available_monitors)
66eba321a1SGabriele Monaco return -1;
67eba321a1SGabriele Monaco
68eba321a1SGabriele Monaco cursor = strstr(available_monitors, monitor_name);
69eba321a1SGabriele Monaco if (!cursor) {
70eba321a1SGabriele Monaco retval = 0;
71eba321a1SGabriele Monaco goto out_free;
72eba321a1SGabriele Monaco }
73eba321a1SGabriele Monaco
74eba321a1SGabriele Monaco for (; cursor > available_monitors; cursor--)
75eba321a1SGabriele Monaco if (*(cursor-1) == '\n')
76eba321a1SGabriele Monaco break;
77eba321a1SGabriele Monaco end = strstr(cursor, "\n");
78eba321a1SGabriele Monaco memcpy(out_name, cursor, end-cursor);
79eba321a1SGabriele Monaco out_name[end-cursor] = '\0';
80eba321a1SGabriele Monaco
81eba321a1SGabriele Monaco cursor = strstr(out_name, ":");
82eba321a1SGabriele Monaco if (cursor)
83eba321a1SGabriele Monaco *cursor = '/';
84eba321a1SGabriele Monaco else {
85eba321a1SGabriele Monaco sprintf(container, "%s:", monitor_name);
86eba321a1SGabriele Monaco if (strstr(available_monitors, container))
87eba321a1SGabriele Monaco config_is_container = 1;
88eba321a1SGabriele Monaco }
89eba321a1SGabriele Monaco
90eba321a1SGabriele Monaco out_free:
91eba321a1SGabriele Monaco free(available_monitors);
92eba321a1SGabriele Monaco return retval;
93eba321a1SGabriele Monaco }
94eba321a1SGabriele Monaco
95eba321a1SGabriele Monaco /*
966d60f896SDaniel Bristot de Oliveira * ikm_read_enable - reads monitor's enable status
976d60f896SDaniel Bristot de Oliveira *
986d60f896SDaniel Bristot de Oliveira * Returns the current status, or -1 on error.
996d60f896SDaniel Bristot de Oliveira */
ikm_read_enable(char * monitor_name)1006d60f896SDaniel Bristot de Oliveira static int ikm_read_enable(char *monitor_name)
1016d60f896SDaniel Bristot de Oliveira {
1026d60f896SDaniel Bristot de Oliveira int enabled;
1036d60f896SDaniel Bristot de Oliveira
1046d60f896SDaniel Bristot de Oliveira enabled = __ikm_read_enable(monitor_name);
1056d60f896SDaniel Bristot de Oliveira if (enabled < 0) {
1066d60f896SDaniel Bristot de Oliveira err_msg("ikm: fail read enabled: %d\n", enabled);
1076d60f896SDaniel Bristot de Oliveira return -1;
1086d60f896SDaniel Bristot de Oliveira }
1096d60f896SDaniel Bristot de Oliveira
1106d60f896SDaniel Bristot de Oliveira debug_msg("ikm: read enabled: %d\n", enabled);
1116d60f896SDaniel Bristot de Oliveira
1126d60f896SDaniel Bristot de Oliveira return enabled;
1136d60f896SDaniel Bristot de Oliveira }
1146d60f896SDaniel Bristot de Oliveira
1156d60f896SDaniel Bristot de Oliveira /*
1166d60f896SDaniel Bristot de Oliveira * ikm_write_enable - write to the monitor's enable file
1176d60f896SDaniel Bristot de Oliveira *
1186d60f896SDaniel Bristot de Oliveira * Return the number of bytes written, -1 on error.
1196d60f896SDaniel Bristot de Oliveira */
ikm_write_enable(char * monitor_name,char * enable_disable)1206d60f896SDaniel Bristot de Oliveira static int ikm_write_enable(char *monitor_name, char *enable_disable)
1216d60f896SDaniel Bristot de Oliveira {
1226d60f896SDaniel Bristot de Oliveira char path[MAX_PATH];
1236d60f896SDaniel Bristot de Oliveira int retval;
1246d60f896SDaniel Bristot de Oliveira
1256d60f896SDaniel Bristot de Oliveira debug_msg("ikm: writing enabled: %s\n", enable_disable);
1266d60f896SDaniel Bristot de Oliveira
1276d60f896SDaniel Bristot de Oliveira snprintf(path, MAX_PATH, "rv/monitors/%s/enable", monitor_name);
1286d60f896SDaniel Bristot de Oliveira retval = tracefs_instance_file_write(NULL, path, enable_disable);
1296d60f896SDaniel Bristot de Oliveira if (retval < strlen(enable_disable)) {
1306d60f896SDaniel Bristot de Oliveira err_msg("ikm: writing enabled: %s\n", enable_disable);
1316d60f896SDaniel Bristot de Oliveira return -1;
1326d60f896SDaniel Bristot de Oliveira }
1336d60f896SDaniel Bristot de Oliveira
1346d60f896SDaniel Bristot de Oliveira return retval;
1356d60f896SDaniel Bristot de Oliveira }
1366d60f896SDaniel Bristot de Oliveira
1376d60f896SDaniel Bristot de Oliveira /*
1386d60f896SDaniel Bristot de Oliveira * ikm_enable - enable a monitor
1396d60f896SDaniel Bristot de Oliveira *
1406d60f896SDaniel Bristot de Oliveira * Returns -1 on failure. Success otherwise.
1416d60f896SDaniel Bristot de Oliveira */
ikm_enable(char * monitor_name)1426d60f896SDaniel Bristot de Oliveira static int ikm_enable(char *monitor_name)
1436d60f896SDaniel Bristot de Oliveira {
1446d60f896SDaniel Bristot de Oliveira return ikm_write_enable(monitor_name, "1");
1456d60f896SDaniel Bristot de Oliveira }
1466d60f896SDaniel Bristot de Oliveira
1476d60f896SDaniel Bristot de Oliveira /*
1486d60f896SDaniel Bristot de Oliveira * ikm_disable - disable a monitor
1496d60f896SDaniel Bristot de Oliveira *
1506d60f896SDaniel Bristot de Oliveira * Returns -1 on failure. Success otherwise.
1516d60f896SDaniel Bristot de Oliveira */
ikm_disable(char * monitor_name)1526d60f896SDaniel Bristot de Oliveira static int ikm_disable(char *monitor_name)
1536d60f896SDaniel Bristot de Oliveira {
1546d60f896SDaniel Bristot de Oliveira return ikm_write_enable(monitor_name, "0");
1556d60f896SDaniel Bristot de Oliveira }
1566d60f896SDaniel Bristot de Oliveira
1576d60f896SDaniel Bristot de Oliveira /*
1586d60f896SDaniel Bristot de Oliveira * ikm_read_desc - read monitors' description
1596d60f896SDaniel Bristot de Oliveira *
1606d60f896SDaniel Bristot de Oliveira * Return a dynamically allocated string with the monitor's
1616d60f896SDaniel Bristot de Oliveira * description, NULL otherwise.
1626d60f896SDaniel Bristot de Oliveira */
ikm_read_desc(char * monitor_name)1636d60f896SDaniel Bristot de Oliveira static char *ikm_read_desc(char *monitor_name)
1646d60f896SDaniel Bristot de Oliveira {
1656d60f896SDaniel Bristot de Oliveira char path[MAX_PATH];
1666d60f896SDaniel Bristot de Oliveira char *desc;
1676d60f896SDaniel Bristot de Oliveira
1686d60f896SDaniel Bristot de Oliveira snprintf(path, MAX_PATH, "rv/monitors/%s/desc", monitor_name);
1696d60f896SDaniel Bristot de Oliveira desc = tracefs_instance_file_read(NULL, path, NULL);
1706d60f896SDaniel Bristot de Oliveira if (!desc) {
1716d60f896SDaniel Bristot de Oliveira err_msg("ikm: error reading monitor %s desc\n", monitor_name);
1726d60f896SDaniel Bristot de Oliveira return NULL;
1736d60f896SDaniel Bristot de Oliveira }
1746d60f896SDaniel Bristot de Oliveira
1756d60f896SDaniel Bristot de Oliveira *strstr(desc, "\n") = '\0';
1766d60f896SDaniel Bristot de Oliveira
1776d60f896SDaniel Bristot de Oliveira return desc;
1786d60f896SDaniel Bristot de Oliveira }
1796d60f896SDaniel Bristot de Oliveira
1806d60f896SDaniel Bristot de Oliveira /*
1816d60f896SDaniel Bristot de Oliveira * ikm_fill_monitor_definition - fill monitor's definition
1826d60f896SDaniel Bristot de Oliveira *
183*4ffef957SGabriele Monaco * Returns -1 on error, 1 if the monitor does not belong in the container, 0 otherwise.
184*4ffef957SGabriele Monaco * container can be NULL
1856d60f896SDaniel Bristot de Oliveira */
ikm_fill_monitor_definition(char * name,struct monitor * ikm,char * container)186*4ffef957SGabriele Monaco static int ikm_fill_monitor_definition(char *name, struct monitor *ikm, char *container)
1876d60f896SDaniel Bristot de Oliveira {
1886d60f896SDaniel Bristot de Oliveira int enabled;
189eba321a1SGabriele Monaco char *desc, *nested_name;
190eba321a1SGabriele Monaco
191eba321a1SGabriele Monaco nested_name = strstr(name, ":");
192eba321a1SGabriele Monaco if (nested_name) {
193*4ffef957SGabriele Monaco /* it belongs in container if it starts with "container:" */
194*4ffef957SGabriele Monaco if (container && strstr(name, container) != name)
195*4ffef957SGabriele Monaco return 1;
196eba321a1SGabriele Monaco *nested_name = '/';
197eba321a1SGabriele Monaco ++nested_name;
198eba321a1SGabriele Monaco ikm->nested = 1;
199eba321a1SGabriele Monaco } else {
200*4ffef957SGabriele Monaco if (container)
201*4ffef957SGabriele Monaco return 1;
202eba321a1SGabriele Monaco nested_name = name;
203eba321a1SGabriele Monaco ikm->nested = 0;
204eba321a1SGabriele Monaco }
2056d60f896SDaniel Bristot de Oliveira
2066d60f896SDaniel Bristot de Oliveira enabled = ikm_read_enable(name);
2076d60f896SDaniel Bristot de Oliveira if (enabled < 0) {
2086d60f896SDaniel Bristot de Oliveira err_msg("ikm: monitor %s fail to read enable file, bug?\n", name);
2096d60f896SDaniel Bristot de Oliveira return -1;
2106d60f896SDaniel Bristot de Oliveira }
2116d60f896SDaniel Bristot de Oliveira
2126d60f896SDaniel Bristot de Oliveira desc = ikm_read_desc(name);
2136d60f896SDaniel Bristot de Oliveira if (!desc) {
2146d60f896SDaniel Bristot de Oliveira err_msg("ikm: monitor %s does not have desc file, bug?\n", name);
2156d60f896SDaniel Bristot de Oliveira return -1;
2166d60f896SDaniel Bristot de Oliveira }
2176d60f896SDaniel Bristot de Oliveira
218eba321a1SGabriele Monaco strncpy(ikm->name, nested_name, MAX_DA_NAME_LEN);
2196d60f896SDaniel Bristot de Oliveira ikm->enabled = enabled;
2206d60f896SDaniel Bristot de Oliveira strncpy(ikm->desc, desc, MAX_DESCRIPTION);
2216d60f896SDaniel Bristot de Oliveira
2226d60f896SDaniel Bristot de Oliveira free(desc);
2236d60f896SDaniel Bristot de Oliveira
2246d60f896SDaniel Bristot de Oliveira return 0;
2256d60f896SDaniel Bristot de Oliveira }
2266d60f896SDaniel Bristot de Oliveira
2276d60f896SDaniel Bristot de Oliveira /*
2286d60f896SDaniel Bristot de Oliveira * ikm_write_reactor - switch the reactor to *reactor
2296d60f896SDaniel Bristot de Oliveira *
2306d60f896SDaniel Bristot de Oliveira * Return the number or characters written, -1 on error.
2316d60f896SDaniel Bristot de Oliveira */
ikm_write_reactor(char * monitor_name,char * reactor)2326d60f896SDaniel Bristot de Oliveira static int ikm_write_reactor(char *monitor_name, char *reactor)
2336d60f896SDaniel Bristot de Oliveira {
2346d60f896SDaniel Bristot de Oliveira char path[MAX_PATH];
2356d60f896SDaniel Bristot de Oliveira int retval;
2366d60f896SDaniel Bristot de Oliveira
2376d60f896SDaniel Bristot de Oliveira snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name);
2386d60f896SDaniel Bristot de Oliveira retval = tracefs_instance_file_write(NULL, path, reactor);
2396d60f896SDaniel Bristot de Oliveira debug_msg("ikm: write \"%s\" reactors: %d\n", reactor, retval);
2406d60f896SDaniel Bristot de Oliveira
2416d60f896SDaniel Bristot de Oliveira return retval;
2426d60f896SDaniel Bristot de Oliveira }
2436d60f896SDaniel Bristot de Oliveira
2446d60f896SDaniel Bristot de Oliveira /*
2456d60f896SDaniel Bristot de Oliveira * ikm_read_reactor - read the reactors file
2466d60f896SDaniel Bristot de Oliveira *
2476d60f896SDaniel Bristot de Oliveira * Returns a dynamically allocated string with monitor's
2486d60f896SDaniel Bristot de Oliveira * available reactors, or NULL on error.
2496d60f896SDaniel Bristot de Oliveira */
ikm_read_reactor(char * monitor_name)2506d60f896SDaniel Bristot de Oliveira static char *ikm_read_reactor(char *monitor_name)
2516d60f896SDaniel Bristot de Oliveira {
2526d60f896SDaniel Bristot de Oliveira char path[MAX_PATH];
2536d60f896SDaniel Bristot de Oliveira char *reactors;
2546d60f896SDaniel Bristot de Oliveira
2556d60f896SDaniel Bristot de Oliveira snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name);
2566d60f896SDaniel Bristot de Oliveira reactors = tracefs_instance_file_read(NULL, path, NULL);
2576d60f896SDaniel Bristot de Oliveira if (!reactors) {
2586d60f896SDaniel Bristot de Oliveira err_msg("ikm: fail reading monitor's %s reactors file\n", monitor_name);
2596d60f896SDaniel Bristot de Oliveira return NULL;
2606d60f896SDaniel Bristot de Oliveira }
2616d60f896SDaniel Bristot de Oliveira
2626d60f896SDaniel Bristot de Oliveira return reactors;
2636d60f896SDaniel Bristot de Oliveira }
2646d60f896SDaniel Bristot de Oliveira
2656d60f896SDaniel Bristot de Oliveira /*
2666d60f896SDaniel Bristot de Oliveira * ikm_get_current_reactor - get the current enabled reactor
2676d60f896SDaniel Bristot de Oliveira *
2686d60f896SDaniel Bristot de Oliveira * Reads the reactors file and find the currently enabled
2696d60f896SDaniel Bristot de Oliveira * [reactor].
2706d60f896SDaniel Bristot de Oliveira *
2716d60f896SDaniel Bristot de Oliveira * Returns a dynamically allocated memory with the current
2726d60f896SDaniel Bristot de Oliveira * reactor. NULL otherwise.
2736d60f896SDaniel Bristot de Oliveira */
ikm_get_current_reactor(char * monitor_name)2746d60f896SDaniel Bristot de Oliveira static char *ikm_get_current_reactor(char *monitor_name)
2756d60f896SDaniel Bristot de Oliveira {
2766d60f896SDaniel Bristot de Oliveira char *reactors = ikm_read_reactor(monitor_name);
27761ec586bSDaniel Bristot de Oliveira char *curr_reactor = NULL;
2786d60f896SDaniel Bristot de Oliveira char *start;
2796d60f896SDaniel Bristot de Oliveira char *end;
2806d60f896SDaniel Bristot de Oliveira
2816d60f896SDaniel Bristot de Oliveira if (!reactors)
2826d60f896SDaniel Bristot de Oliveira return NULL;
2836d60f896SDaniel Bristot de Oliveira
2846d60f896SDaniel Bristot de Oliveira start = strstr(reactors, "[");
2856d60f896SDaniel Bristot de Oliveira if (!start)
2866d60f896SDaniel Bristot de Oliveira goto out_free;
2876d60f896SDaniel Bristot de Oliveira
2886d60f896SDaniel Bristot de Oliveira start++;
2896d60f896SDaniel Bristot de Oliveira
2906d60f896SDaniel Bristot de Oliveira end = strstr(start, "]");
2916d60f896SDaniel Bristot de Oliveira if (!end)
2926d60f896SDaniel Bristot de Oliveira goto out_free;
2936d60f896SDaniel Bristot de Oliveira
2946d60f896SDaniel Bristot de Oliveira *end = '\0';
2956d60f896SDaniel Bristot de Oliveira
2966d60f896SDaniel Bristot de Oliveira curr_reactor = calloc(strlen(start) + 1, sizeof(char));
2976d60f896SDaniel Bristot de Oliveira if (!curr_reactor)
2986d60f896SDaniel Bristot de Oliveira goto out_free;
2996d60f896SDaniel Bristot de Oliveira
3006d60f896SDaniel Bristot de Oliveira strncpy(curr_reactor, start, strlen(start));
3016d60f896SDaniel Bristot de Oliveira debug_msg("ikm: read current reactor %s\n", curr_reactor);
3026d60f896SDaniel Bristot de Oliveira
3036d60f896SDaniel Bristot de Oliveira out_free:
3046d60f896SDaniel Bristot de Oliveira free(reactors);
3056d60f896SDaniel Bristot de Oliveira
3066d60f896SDaniel Bristot de Oliveira return curr_reactor;
3076d60f896SDaniel Bristot de Oliveira }
3086d60f896SDaniel Bristot de Oliveira
ikm_has_id(char * monitor_name)3096d60f896SDaniel Bristot de Oliveira static int ikm_has_id(char *monitor_name)
3106d60f896SDaniel Bristot de Oliveira {
3116d60f896SDaniel Bristot de Oliveira char path[MAX_PATH];
3126d60f896SDaniel Bristot de Oliveira char *format;
3136d60f896SDaniel Bristot de Oliveira int has_id;
3146d60f896SDaniel Bristot de Oliveira
3156d60f896SDaniel Bristot de Oliveira snprintf(path, MAX_PATH, "events/rv/event_%s/format", monitor_name);
3166d60f896SDaniel Bristot de Oliveira format = tracefs_instance_file_read(NULL, path, NULL);
3176d60f896SDaniel Bristot de Oliveira if (!format) {
3186d60f896SDaniel Bristot de Oliveira err_msg("ikm: fail reading monitor's %s format event file\n", monitor_name);
3196d60f896SDaniel Bristot de Oliveira return -1;
3206d60f896SDaniel Bristot de Oliveira }
3216d60f896SDaniel Bristot de Oliveira
3226d60f896SDaniel Bristot de Oliveira /* print fmt: "%d: %s x %s -> %s %s", REC->id, ... */
3236d60f896SDaniel Bristot de Oliveira has_id = !!strstr(format, "REC->id");
3246d60f896SDaniel Bristot de Oliveira
3256d60f896SDaniel Bristot de Oliveira debug_msg("ikm: monitor %s has id: %s\n", monitor_name, has_id ? "yes" : "no");
3266d60f896SDaniel Bristot de Oliveira
3276d60f896SDaniel Bristot de Oliveira free(format);
3286d60f896SDaniel Bristot de Oliveira
3296d60f896SDaniel Bristot de Oliveira return has_id;
3306d60f896SDaniel Bristot de Oliveira }
3316d60f896SDaniel Bristot de Oliveira
3326d60f896SDaniel Bristot de Oliveira /**
3336d60f896SDaniel Bristot de Oliveira * ikm_list_monitors - list all available monitors
3346d60f896SDaniel Bristot de Oliveira *
3356d60f896SDaniel Bristot de Oliveira * Returns 0 on success, -1 otherwise.
3366d60f896SDaniel Bristot de Oliveira */
ikm_list_monitors(char * container)337*4ffef957SGabriele Monaco int ikm_list_monitors(char *container)
3386d60f896SDaniel Bristot de Oliveira {
3396d60f896SDaniel Bristot de Oliveira char *available_monitors;
340eba321a1SGabriele Monaco struct monitor ikm = {0};
3416d60f896SDaniel Bristot de Oliveira char *curr, *next;
342*4ffef957SGabriele Monaco int retval, list_monitor = 0;
3436d60f896SDaniel Bristot de Oliveira
3446d60f896SDaniel Bristot de Oliveira available_monitors = tracefs_instance_file_read(NULL, "rv/available_monitors", NULL);
3456d60f896SDaniel Bristot de Oliveira
3466d60f896SDaniel Bristot de Oliveira if (!available_monitors) {
3476d60f896SDaniel Bristot de Oliveira err_msg("ikm: available monitors is not available, is CONFIG_RV enabled?\n");
3486d60f896SDaniel Bristot de Oliveira return -1;
3496d60f896SDaniel Bristot de Oliveira }
3506d60f896SDaniel Bristot de Oliveira
3516d60f896SDaniel Bristot de Oliveira curr = available_monitors;
3526d60f896SDaniel Bristot de Oliveira do {
3536d60f896SDaniel Bristot de Oliveira next = strstr(curr, "\n");
3546d60f896SDaniel Bristot de Oliveira *next = '\0';
3556d60f896SDaniel Bristot de Oliveira
356*4ffef957SGabriele Monaco retval = ikm_fill_monitor_definition(curr, &ikm, container);
357*4ffef957SGabriele Monaco if (retval < 0)
3586d60f896SDaniel Bristot de Oliveira err_msg("ikm: error reading %d in kernel monitor, skipping\n", curr);
3596d60f896SDaniel Bristot de Oliveira
360*4ffef957SGabriele Monaco if (!retval) {
361*4ffef957SGabriele Monaco int indent = ikm.nested && !container;
362*4ffef957SGabriele Monaco
363*4ffef957SGabriele Monaco list_monitor = 1;
364*4ffef957SGabriele Monaco printf("%s%-*s %s %s\n", indent ? " - " : "",
365*4ffef957SGabriele Monaco indent ? MAX_DA_NAME_LEN - 3 : MAX_DA_NAME_LEN,
366eba321a1SGabriele Monaco ikm.name, ikm.desc, ikm.enabled ? "[ON]" : "[OFF]");
367*4ffef957SGabriele Monaco }
3686d60f896SDaniel Bristot de Oliveira curr = ++next;
3696d60f896SDaniel Bristot de Oliveira
3706d60f896SDaniel Bristot de Oliveira } while (strlen(curr));
3716d60f896SDaniel Bristot de Oliveira
372*4ffef957SGabriele Monaco if (!list_monitor) {
373*4ffef957SGabriele Monaco if (container)
374*4ffef957SGabriele Monaco printf("-- No monitor found in container %s --\n", container);
375*4ffef957SGabriele Monaco else
376*4ffef957SGabriele Monaco printf("-- No monitor found --\n");
377*4ffef957SGabriele Monaco }
378*4ffef957SGabriele Monaco
3796d60f896SDaniel Bristot de Oliveira free(available_monitors);
3806d60f896SDaniel Bristot de Oliveira
3816d60f896SDaniel Bristot de Oliveira return 0;
3826d60f896SDaniel Bristot de Oliveira }
3836d60f896SDaniel Bristot de Oliveira
ikm_print_header(struct trace_seq * s)3846d60f896SDaniel Bristot de Oliveira static void ikm_print_header(struct trace_seq *s)
3856d60f896SDaniel Bristot de Oliveira {
3866d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%16s-%-8s %5s %5s ", "<TASK>", "PID", "[CPU]", "TYPE");
3876d60f896SDaniel Bristot de Oliveira if (config_has_id)
3886d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%8s ", "ID");
3896d60f896SDaniel Bristot de Oliveira
3906d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n",
3916d60f896SDaniel Bristot de Oliveira "STATE",
3926d60f896SDaniel Bristot de Oliveira "EVENT",
3936d60f896SDaniel Bristot de Oliveira "NEXT_STATE",
3946d60f896SDaniel Bristot de Oliveira "FINAL");
3956d60f896SDaniel Bristot de Oliveira
3966d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%16s %-8s %5s %5s ", " | ", " | ", " | ", " | ");
3976d60f896SDaniel Bristot de Oliveira
3986d60f896SDaniel Bristot de Oliveira if (config_has_id)
3996d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%8s ", " | ");
4006d60f896SDaniel Bristot de Oliveira
4016d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%24s %-24s %-24s %s\n",
4026d60f896SDaniel Bristot de Oliveira " | ",
4036d60f896SDaniel Bristot de Oliveira " | ",
4046d60f896SDaniel Bristot de Oliveira " | ",
4056d60f896SDaniel Bristot de Oliveira "|");
4066d60f896SDaniel Bristot de Oliveira
4076d60f896SDaniel Bristot de Oliveira }
4086d60f896SDaniel Bristot de Oliveira
4096d60f896SDaniel Bristot de Oliveira /*
4106d60f896SDaniel Bristot de Oliveira * ikm_event_handler - callback to handle event events
4116d60f896SDaniel Bristot de Oliveira *
4126d60f896SDaniel Bristot de Oliveira * Called any time a rv:"monitor"_event events is generated.
413f88b8871SBa Jing * It parses and prints event.
4146d60f896SDaniel Bristot de Oliveira */
4156d60f896SDaniel Bristot de Oliveira static int
ikm_event_handler(struct trace_seq * s,struct tep_record * record,struct tep_event * trace_event,void * context)4166d60f896SDaniel Bristot de Oliveira ikm_event_handler(struct trace_seq *s, struct tep_record *record,
4176d60f896SDaniel Bristot de Oliveira struct tep_event *trace_event, void *context)
4186d60f896SDaniel Bristot de Oliveira {
4196d60f896SDaniel Bristot de Oliveira /* if needed: struct trace_instance *inst = context; */
4206d60f896SDaniel Bristot de Oliveira char *state, *event, *next_state;
4216d60f896SDaniel Bristot de Oliveira unsigned long long final_state;
4226d60f896SDaniel Bristot de Oliveira unsigned long long pid;
4236d60f896SDaniel Bristot de Oliveira unsigned long long id;
4246d60f896SDaniel Bristot de Oliveira int val;
425eba321a1SGabriele Monaco bool missing_id;
4266d60f896SDaniel Bristot de Oliveira
4276d60f896SDaniel Bristot de Oliveira if (config_has_id)
428eba321a1SGabriele Monaco missing_id = tep_get_field_val(s, trace_event, "id", record, &id, 1);
4296d60f896SDaniel Bristot de Oliveira
4306d60f896SDaniel Bristot de Oliveira tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1);
4316d60f896SDaniel Bristot de Oliveira
4326d60f896SDaniel Bristot de Oliveira if (config_has_id && (config_my_pid == id))
4336d60f896SDaniel Bristot de Oliveira return 0;
4346d60f896SDaniel Bristot de Oliveira else if (config_my_pid && (config_my_pid == pid))
4356d60f896SDaniel Bristot de Oliveira return 0;
4366d60f896SDaniel Bristot de Oliveira
437eba321a1SGabriele Monaco tep_print_event(trace_event->tep, s, record, "%16s-%-8d [%.3d] ",
438eba321a1SGabriele Monaco TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU);
4396d60f896SDaniel Bristot de Oliveira
440eba321a1SGabriele Monaco if (config_is_container)
441eba321a1SGabriele Monaco tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME);
442eba321a1SGabriele Monaco else
443eba321a1SGabriele Monaco trace_seq_printf(s, "event ");
4446d60f896SDaniel Bristot de Oliveira
445eba321a1SGabriele Monaco if (config_has_id) {
446eba321a1SGabriele Monaco if (missing_id)
447eba321a1SGabriele Monaco /* placeholder if we are dealing with a mixed-type container*/
448eba321a1SGabriele Monaco trace_seq_printf(s, " ");
449eba321a1SGabriele Monaco else
4506d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%8llu ", id);
451eba321a1SGabriele Monaco }
4526d60f896SDaniel Bristot de Oliveira
4536d60f896SDaniel Bristot de Oliveira state = tep_get_field_raw(s, trace_event, "state", record, &val, 0);
4546d60f896SDaniel Bristot de Oliveira event = tep_get_field_raw(s, trace_event, "event", record, &val, 0);
4556d60f896SDaniel Bristot de Oliveira next_state = tep_get_field_raw(s, trace_event, "next_state", record, &val, 0);
4566d60f896SDaniel Bristot de Oliveira tep_get_field_val(s, trace_event, "final_state", record, &final_state, 1);
4576d60f896SDaniel Bristot de Oliveira
4586d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n",
4596d60f896SDaniel Bristot de Oliveira state,
4606d60f896SDaniel Bristot de Oliveira event,
4616d60f896SDaniel Bristot de Oliveira next_state,
4626d60f896SDaniel Bristot de Oliveira final_state ? "Y" : "N");
4636d60f896SDaniel Bristot de Oliveira
4646d60f896SDaniel Bristot de Oliveira trace_seq_do_printf(s);
4656d60f896SDaniel Bristot de Oliveira trace_seq_reset(s);
4666d60f896SDaniel Bristot de Oliveira
4676d60f896SDaniel Bristot de Oliveira return 0;
4686d60f896SDaniel Bristot de Oliveira }
4696d60f896SDaniel Bristot de Oliveira
4706d60f896SDaniel Bristot de Oliveira /*
4716d60f896SDaniel Bristot de Oliveira * ikm_error_handler - callback to handle error events
4726d60f896SDaniel Bristot de Oliveira *
4736d60f896SDaniel Bristot de Oliveira * Called any time a rv:"monitor"_errors events is generated.
474f88b8871SBa Jing * It parses and prints event.
4756d60f896SDaniel Bristot de Oliveira */
4766d60f896SDaniel Bristot de Oliveira static int
ikm_error_handler(struct trace_seq * s,struct tep_record * record,struct tep_event * trace_event,void * context)4776d60f896SDaniel Bristot de Oliveira ikm_error_handler(struct trace_seq *s, struct tep_record *record,
4786d60f896SDaniel Bristot de Oliveira struct tep_event *trace_event, void *context)
4796d60f896SDaniel Bristot de Oliveira {
4806d60f896SDaniel Bristot de Oliveira unsigned long long pid, id;
4816d60f896SDaniel Bristot de Oliveira int cpu = record->cpu;
4826d60f896SDaniel Bristot de Oliveira char *state, *event;
4836d60f896SDaniel Bristot de Oliveira int val;
484eba321a1SGabriele Monaco bool missing_id;
4856d60f896SDaniel Bristot de Oliveira
4866d60f896SDaniel Bristot de Oliveira if (config_has_id)
487eba321a1SGabriele Monaco missing_id = tep_get_field_val(s, trace_event, "id", record, &id, 1);
4886d60f896SDaniel Bristot de Oliveira
4896d60f896SDaniel Bristot de Oliveira tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1);
4906d60f896SDaniel Bristot de Oliveira
4916d60f896SDaniel Bristot de Oliveira if (config_has_id && config_my_pid == id)
4926d60f896SDaniel Bristot de Oliveira return 0;
4936d60f896SDaniel Bristot de Oliveira else if (config_my_pid == pid)
4946d60f896SDaniel Bristot de Oliveira return 0;
4956d60f896SDaniel Bristot de Oliveira
496eba321a1SGabriele Monaco trace_seq_printf(s, "%8lld [%03d] ", pid, cpu);
4976d60f896SDaniel Bristot de Oliveira
498eba321a1SGabriele Monaco if (config_is_container)
499eba321a1SGabriele Monaco tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME);
500eba321a1SGabriele Monaco else
501eba321a1SGabriele Monaco trace_seq_printf(s, "error ");
502eba321a1SGabriele Monaco
503eba321a1SGabriele Monaco if (config_has_id) {
504eba321a1SGabriele Monaco if (missing_id)
505eba321a1SGabriele Monaco /* placeholder if we are dealing with a mixed-type container*/
506eba321a1SGabriele Monaco trace_seq_printf(s, " ");
507eba321a1SGabriele Monaco else
5086d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%8llu ", id);
509eba321a1SGabriele Monaco }
5106d60f896SDaniel Bristot de Oliveira
5116d60f896SDaniel Bristot de Oliveira state = tep_get_field_raw(s, trace_event, "state", record, &val, 0);
5126d60f896SDaniel Bristot de Oliveira event = tep_get_field_raw(s, trace_event, "event", record, &val, 0);
5136d60f896SDaniel Bristot de Oliveira
5146d60f896SDaniel Bristot de Oliveira trace_seq_printf(s, "%24s x %s\n", state, event);
5156d60f896SDaniel Bristot de Oliveira
5166d60f896SDaniel Bristot de Oliveira trace_seq_do_printf(s);
5176d60f896SDaniel Bristot de Oliveira trace_seq_reset(s);
5186d60f896SDaniel Bristot de Oliveira
5196d60f896SDaniel Bristot de Oliveira return 0;
5206d60f896SDaniel Bristot de Oliveira }
5216d60f896SDaniel Bristot de Oliveira
ikm_enable_trace_events(char * monitor_name,struct trace_instance * inst)522eba321a1SGabriele Monaco static int ikm_enable_trace_events(char *monitor_name, struct trace_instance *inst)
523eba321a1SGabriele Monaco {
524eba321a1SGabriele Monaco char event[MAX_DA_NAME_LEN + 7]; /* max(error_,event_) + '0' = 7 */
525eba321a1SGabriele Monaco int retval;
526eba321a1SGabriele Monaco
527eba321a1SGabriele Monaco snprintf(event, sizeof(event), "event_%s", monitor_name);
528eba321a1SGabriele Monaco retval = tracefs_event_enable(inst->inst, "rv", event);
529eba321a1SGabriele Monaco if (retval)
530eba321a1SGabriele Monaco return -1;
531eba321a1SGabriele Monaco
532eba321a1SGabriele Monaco tep_register_event_handler(inst->tep, -1, "rv", event,
533eba321a1SGabriele Monaco ikm_event_handler, NULL);
534eba321a1SGabriele Monaco
535eba321a1SGabriele Monaco snprintf(event, sizeof(event), "error_%s", monitor_name);
536eba321a1SGabriele Monaco retval = tracefs_event_enable(inst->inst, "rv", event);
537eba321a1SGabriele Monaco if (retval)
538eba321a1SGabriele Monaco return -1;
539eba321a1SGabriele Monaco
540eba321a1SGabriele Monaco tep_register_event_handler(inst->tep, -1, "rv", event,
541eba321a1SGabriele Monaco ikm_error_handler, NULL);
542eba321a1SGabriele Monaco
543eba321a1SGabriele Monaco /* set if at least 1 monitor has id in case of a container */
544eba321a1SGabriele Monaco config_has_id = ikm_has_id(monitor_name);
545eba321a1SGabriele Monaco if (config_has_id < 0)
546eba321a1SGabriele Monaco return -1;
547eba321a1SGabriele Monaco
548eba321a1SGabriele Monaco
549eba321a1SGabriele Monaco return 0;
550eba321a1SGabriele Monaco }
551eba321a1SGabriele Monaco
ikm_enable_trace_container(char * monitor_name,struct trace_instance * inst)552eba321a1SGabriele Monaco static int ikm_enable_trace_container(char *monitor_name,
553eba321a1SGabriele Monaco struct trace_instance *inst)
554eba321a1SGabriele Monaco {
555eba321a1SGabriele Monaco DIR *dp;
556eba321a1SGabriele Monaco char *abs_path, rv_path[MAX_PATH];
557eba321a1SGabriele Monaco struct dirent *ep;
558eba321a1SGabriele Monaco int retval = 0;
559eba321a1SGabriele Monaco
560eba321a1SGabriele Monaco snprintf(rv_path, MAX_PATH, "rv/monitors/%s", monitor_name);
561eba321a1SGabriele Monaco abs_path = tracefs_instance_get_file(NULL, rv_path);
562eba321a1SGabriele Monaco if (!abs_path)
563eba321a1SGabriele Monaco return -1;
564eba321a1SGabriele Monaco dp = opendir(abs_path);
565eba321a1SGabriele Monaco if (!dp)
566eba321a1SGabriele Monaco goto out_free;
567eba321a1SGabriele Monaco
568eba321a1SGabriele Monaco while (!retval && (ep = readdir(dp))) {
569eba321a1SGabriele Monaco if (ep->d_type != DT_DIR || ep->d_name[0] == '.')
570eba321a1SGabriele Monaco continue;
571eba321a1SGabriele Monaco retval = ikm_enable_trace_events(ep->d_name, inst);
572eba321a1SGabriele Monaco }
573eba321a1SGabriele Monaco
574eba321a1SGabriele Monaco closedir(dp);
575eba321a1SGabriele Monaco out_free:
576eba321a1SGabriele Monaco free(abs_path);
577eba321a1SGabriele Monaco return retval;
578eba321a1SGabriele Monaco }
579eba321a1SGabriele Monaco
5806d60f896SDaniel Bristot de Oliveira /*
5816d60f896SDaniel Bristot de Oliveira * ikm_setup_trace_instance - set up a tracing instance to collect data
5826d60f896SDaniel Bristot de Oliveira *
5836d60f896SDaniel Bristot de Oliveira * Create a trace instance, enable rv: events and enable the trace.
5846d60f896SDaniel Bristot de Oliveira *
5856d60f896SDaniel Bristot de Oliveira * Returns the trace_instance * with all set, NULL otherwise.
5866d60f896SDaniel Bristot de Oliveira */
ikm_setup_trace_instance(char * monitor_name)5876d60f896SDaniel Bristot de Oliveira static struct trace_instance *ikm_setup_trace_instance(char *monitor_name)
5886d60f896SDaniel Bristot de Oliveira {
5896d60f896SDaniel Bristot de Oliveira struct trace_instance *inst;
5906d60f896SDaniel Bristot de Oliveira int retval;
5916d60f896SDaniel Bristot de Oliveira
5926d60f896SDaniel Bristot de Oliveira if (!config_trace)
5936d60f896SDaniel Bristot de Oliveira return NULL;
5946d60f896SDaniel Bristot de Oliveira
5956d60f896SDaniel Bristot de Oliveira /* alloc data */
5966d60f896SDaniel Bristot de Oliveira inst = calloc(1, sizeof(*inst));
5976d60f896SDaniel Bristot de Oliveira if (!inst) {
5986d60f896SDaniel Bristot de Oliveira err_msg("ikm: failed to allocate trace instance");
5996d60f896SDaniel Bristot de Oliveira goto out_err;
6006d60f896SDaniel Bristot de Oliveira }
6016d60f896SDaniel Bristot de Oliveira
6026d60f896SDaniel Bristot de Oliveira retval = trace_instance_init(inst, monitor_name);
6036d60f896SDaniel Bristot de Oliveira if (retval)
6046d60f896SDaniel Bristot de Oliveira goto out_free;
6056d60f896SDaniel Bristot de Oliveira
606eba321a1SGabriele Monaco if (config_is_container)
607eba321a1SGabriele Monaco retval = ikm_enable_trace_container(monitor_name, inst);
608eba321a1SGabriele Monaco else
609eba321a1SGabriele Monaco retval = ikm_enable_trace_events(monitor_name, inst);
6106d60f896SDaniel Bristot de Oliveira if (retval)
6116d60f896SDaniel Bristot de Oliveira goto out_inst;
6126d60f896SDaniel Bristot de Oliveira
6136d60f896SDaniel Bristot de Oliveira /* ready to enable */
6146d60f896SDaniel Bristot de Oliveira tracefs_trace_on(inst->inst);
6156d60f896SDaniel Bristot de Oliveira
6166d60f896SDaniel Bristot de Oliveira return inst;
6176d60f896SDaniel Bristot de Oliveira
6186d60f896SDaniel Bristot de Oliveira out_inst:
6196d60f896SDaniel Bristot de Oliveira trace_instance_destroy(inst);
6206d60f896SDaniel Bristot de Oliveira out_free:
6216d60f896SDaniel Bristot de Oliveira free(inst);
6226d60f896SDaniel Bristot de Oliveira out_err:
6236d60f896SDaniel Bristot de Oliveira return NULL;
6246d60f896SDaniel Bristot de Oliveira }
6256d60f896SDaniel Bristot de Oliveira
6266d60f896SDaniel Bristot de Oliveira /**
6276d60f896SDaniel Bristot de Oliveira * ikm_destroy_trace_instance - destroy a previously created instance
6286d60f896SDaniel Bristot de Oliveira */
ikm_destroy_trace_instance(struct trace_instance * inst)6296d60f896SDaniel Bristot de Oliveira static void ikm_destroy_trace_instance(struct trace_instance *inst)
6306d60f896SDaniel Bristot de Oliveira {
6316d60f896SDaniel Bristot de Oliveira if (!inst)
6326d60f896SDaniel Bristot de Oliveira return;
6336d60f896SDaniel Bristot de Oliveira
6346d60f896SDaniel Bristot de Oliveira trace_instance_destroy(inst);
6356d60f896SDaniel Bristot de Oliveira free(inst);
6366d60f896SDaniel Bristot de Oliveira }
6376d60f896SDaniel Bristot de Oliveira
6386d60f896SDaniel Bristot de Oliveira /*
6396d60f896SDaniel Bristot de Oliveira * ikm_usage_print_reactors - print all available reactors, one per line.
6406d60f896SDaniel Bristot de Oliveira */
ikm_usage_print_reactors(void)6416d60f896SDaniel Bristot de Oliveira static void ikm_usage_print_reactors(void)
6426d60f896SDaniel Bristot de Oliveira {
6436d60f896SDaniel Bristot de Oliveira char *reactors = tracefs_instance_file_read(NULL, "rv/available_reactors", NULL);
6446d60f896SDaniel Bristot de Oliveira char *start, *end;
6456d60f896SDaniel Bristot de Oliveira
6466d60f896SDaniel Bristot de Oliveira if (!reactors)
6476d60f896SDaniel Bristot de Oliveira return;
6486d60f896SDaniel Bristot de Oliveira
6496d60f896SDaniel Bristot de Oliveira fprintf(stderr, " available reactors:");
6506d60f896SDaniel Bristot de Oliveira
6516d60f896SDaniel Bristot de Oliveira start = reactors;
6526d60f896SDaniel Bristot de Oliveira end = strstr(start, "\n");
6536d60f896SDaniel Bristot de Oliveira
6546d60f896SDaniel Bristot de Oliveira while (end) {
6556d60f896SDaniel Bristot de Oliveira *end = '\0';
6566d60f896SDaniel Bristot de Oliveira
6576d60f896SDaniel Bristot de Oliveira fprintf(stderr, " %s", start);
6586d60f896SDaniel Bristot de Oliveira
6596d60f896SDaniel Bristot de Oliveira start = ++end;
6606d60f896SDaniel Bristot de Oliveira end = strstr(start, "\n");
661a37380efSzhang songyi }
6626d60f896SDaniel Bristot de Oliveira
6636d60f896SDaniel Bristot de Oliveira fprintf(stderr, "\n");
6646d60f896SDaniel Bristot de Oliveira }
6656d60f896SDaniel Bristot de Oliveira /*
6666d60f896SDaniel Bristot de Oliveira * ikm_usage - print usage
6676d60f896SDaniel Bristot de Oliveira */
ikm_usage(int exit_val,char * monitor_name,const char * fmt,...)6686d60f896SDaniel Bristot de Oliveira static void ikm_usage(int exit_val, char *monitor_name, const char *fmt, ...)
6696d60f896SDaniel Bristot de Oliveira {
6706d60f896SDaniel Bristot de Oliveira
6716d60f896SDaniel Bristot de Oliveira char message[1024];
6726d60f896SDaniel Bristot de Oliveira va_list ap;
6736d60f896SDaniel Bristot de Oliveira int i;
6746d60f896SDaniel Bristot de Oliveira
6756d60f896SDaniel Bristot de Oliveira static const char *const usage[] = {
6766d60f896SDaniel Bristot de Oliveira "",
6776d60f896SDaniel Bristot de Oliveira " -h/--help: print this menu and the reactor list",
6786d60f896SDaniel Bristot de Oliveira " -r/--reactor 'reactor': enables the 'reactor'",
6796d60f896SDaniel Bristot de Oliveira " -s/--self: when tracing (-t), also trace rv command",
6806d60f896SDaniel Bristot de Oliveira " -t/--trace: trace monitor's event",
6816d60f896SDaniel Bristot de Oliveira " -v/--verbose: print debug messages",
6826d60f896SDaniel Bristot de Oliveira "",
6836d60f896SDaniel Bristot de Oliveira NULL,
6846d60f896SDaniel Bristot de Oliveira };
6856d60f896SDaniel Bristot de Oliveira
6866d60f896SDaniel Bristot de Oliveira va_start(ap, fmt);
6876d60f896SDaniel Bristot de Oliveira vsnprintf(message, sizeof(message), fmt, ap);
6886d60f896SDaniel Bristot de Oliveira va_end(ap);
6896d60f896SDaniel Bristot de Oliveira
6906d60f896SDaniel Bristot de Oliveira fprintf(stderr, " %s\n", message);
6916d60f896SDaniel Bristot de Oliveira
6926d60f896SDaniel Bristot de Oliveira fprintf(stderr, "\n usage: rv mon %s [-h] [-q] [-r reactor] [-s] [-v]", monitor_name);
6936d60f896SDaniel Bristot de Oliveira
6946d60f896SDaniel Bristot de Oliveira for (i = 0; usage[i]; i++)
6956d60f896SDaniel Bristot de Oliveira fprintf(stderr, "%s\n", usage[i]);
6966d60f896SDaniel Bristot de Oliveira
6976d60f896SDaniel Bristot de Oliveira ikm_usage_print_reactors();
6986d60f896SDaniel Bristot de Oliveira exit(exit_val);
6996d60f896SDaniel Bristot de Oliveira }
7006d60f896SDaniel Bristot de Oliveira
7016d60f896SDaniel Bristot de Oliveira /*
7026d60f896SDaniel Bristot de Oliveira * parse_arguments - parse arguments and set config
7036d60f896SDaniel Bristot de Oliveira */
parse_arguments(char * monitor_name,int argc,char ** argv)7046d60f896SDaniel Bristot de Oliveira static int parse_arguments(char *monitor_name, int argc, char **argv)
7056d60f896SDaniel Bristot de Oliveira {
7066d60f896SDaniel Bristot de Oliveira int c, retval;
7076d60f896SDaniel Bristot de Oliveira
7086d60f896SDaniel Bristot de Oliveira config_my_pid = getpid();
7096d60f896SDaniel Bristot de Oliveira
7106d60f896SDaniel Bristot de Oliveira while (1) {
7116d60f896SDaniel Bristot de Oliveira static struct option long_options[] = {
7126d60f896SDaniel Bristot de Oliveira {"help", no_argument, 0, 'h'},
7136d60f896SDaniel Bristot de Oliveira {"reactor", required_argument, 0, 'r'},
7146d60f896SDaniel Bristot de Oliveira {"self", no_argument, 0, 's'},
7156d60f896SDaniel Bristot de Oliveira {"trace", no_argument, 0, 't'},
7166d60f896SDaniel Bristot de Oliveira {"verbose", no_argument, 0, 'v'},
7176d60f896SDaniel Bristot de Oliveira {0, 0, 0, 0}
7186d60f896SDaniel Bristot de Oliveira };
7196d60f896SDaniel Bristot de Oliveira
7206d60f896SDaniel Bristot de Oliveira /* getopt_long stores the option index here. */
7216d60f896SDaniel Bristot de Oliveira int option_index = 0;
7226d60f896SDaniel Bristot de Oliveira
7236d60f896SDaniel Bristot de Oliveira c = getopt_long(argc, argv, "hr:stv", long_options, &option_index);
7246d60f896SDaniel Bristot de Oliveira
7256d60f896SDaniel Bristot de Oliveira /* detect the end of the options. */
7266d60f896SDaniel Bristot de Oliveira if (c == -1)
7276d60f896SDaniel Bristot de Oliveira break;
7286d60f896SDaniel Bristot de Oliveira
7296d60f896SDaniel Bristot de Oliveira switch (c) {
7306d60f896SDaniel Bristot de Oliveira case 'h':
7316d60f896SDaniel Bristot de Oliveira ikm_usage(0, monitor_name, "help:");
7326d60f896SDaniel Bristot de Oliveira break;
7336d60f896SDaniel Bristot de Oliveira case 'r':
7346d60f896SDaniel Bristot de Oliveira config_reactor = optarg;
7356d60f896SDaniel Bristot de Oliveira break;
7366d60f896SDaniel Bristot de Oliveira case 's':
7376d60f896SDaniel Bristot de Oliveira config_my_pid = 0;
7386d60f896SDaniel Bristot de Oliveira break;
7396d60f896SDaniel Bristot de Oliveira case 't':
7406d60f896SDaniel Bristot de Oliveira config_trace = 1;
7416d60f896SDaniel Bristot de Oliveira break;
7426d60f896SDaniel Bristot de Oliveira case 'v':
7436d60f896SDaniel Bristot de Oliveira config_debug = 1;
7446d60f896SDaniel Bristot de Oliveira break;
7456d60f896SDaniel Bristot de Oliveira }
7466d60f896SDaniel Bristot de Oliveira }
7476d60f896SDaniel Bristot de Oliveira
7486d60f896SDaniel Bristot de Oliveira if (config_reactor) {
7496d60f896SDaniel Bristot de Oliveira config_initial_reactor = ikm_get_current_reactor(monitor_name);
7506d60f896SDaniel Bristot de Oliveira if (!config_initial_reactor)
7516d60f896SDaniel Bristot de Oliveira ikm_usage(1, monitor_name,
7526d60f896SDaniel Bristot de Oliveira "ikm: failed to read current reactor, are reactors enabled?");
7536d60f896SDaniel Bristot de Oliveira
7546d60f896SDaniel Bristot de Oliveira retval = ikm_write_reactor(monitor_name, config_reactor);
7556d60f896SDaniel Bristot de Oliveira if (retval <= 0)
7566d60f896SDaniel Bristot de Oliveira ikm_usage(1, monitor_name,
7576d60f896SDaniel Bristot de Oliveira "ikm: failed to set %s reactor, is it available?",
7586d60f896SDaniel Bristot de Oliveira config_reactor);
7596d60f896SDaniel Bristot de Oliveira }
7606d60f896SDaniel Bristot de Oliveira
7616d60f896SDaniel Bristot de Oliveira debug_msg("ikm: my pid is %d\n", config_my_pid);
7626d60f896SDaniel Bristot de Oliveira
7636d60f896SDaniel Bristot de Oliveira return 0;
7646d60f896SDaniel Bristot de Oliveira }
7656d60f896SDaniel Bristot de Oliveira
7666d60f896SDaniel Bristot de Oliveira /**
7676d60f896SDaniel Bristot de Oliveira * ikm_run_monitor - apply configs and run the monitor
7686d60f896SDaniel Bristot de Oliveira *
7696d60f896SDaniel Bristot de Oliveira * Returns 1 if a monitor was found an executed, 0 if no
7706d60f896SDaniel Bristot de Oliveira * monitors were found, or -1 on error.
7716d60f896SDaniel Bristot de Oliveira */
ikm_run_monitor(char * monitor_name,int argc,char ** argv)7726d60f896SDaniel Bristot de Oliveira int ikm_run_monitor(char *monitor_name, int argc, char **argv)
7736d60f896SDaniel Bristot de Oliveira {
7746d60f896SDaniel Bristot de Oliveira struct trace_instance *inst = NULL;
775eba321a1SGabriele Monaco char *nested_name, full_name[2*MAX_DA_NAME_LEN];
7766d60f896SDaniel Bristot de Oliveira int retval;
7776d60f896SDaniel Bristot de Oliveira
778eba321a1SGabriele Monaco nested_name = strstr(monitor_name, ":");
779eba321a1SGabriele Monaco if (nested_name)
780eba321a1SGabriele Monaco ++nested_name;
781eba321a1SGabriele Monaco else
782eba321a1SGabriele Monaco nested_name = monitor_name;
7836d60f896SDaniel Bristot de Oliveira
784eba321a1SGabriele Monaco retval = __ikm_find_monitor_name(monitor_name, full_name);
785eba321a1SGabriele Monaco if (!retval)
786eba321a1SGabriele Monaco return 0;
787eba321a1SGabriele Monaco if (retval < 0) {
788eba321a1SGabriele Monaco err_msg("ikm: error finding monitor %s\n", nested_name);
789eba321a1SGabriele Monaco return -1;
790eba321a1SGabriele Monaco }
791eba321a1SGabriele Monaco
792eba321a1SGabriele Monaco retval = __ikm_read_enable(full_name);
7936d60f896SDaniel Bristot de Oliveira if (retval) {
794eba321a1SGabriele Monaco err_msg("ikm: monitor %s (in-kernel) is already enabled\n", nested_name);
7956d60f896SDaniel Bristot de Oliveira return -1;
7966d60f896SDaniel Bristot de Oliveira }
7976d60f896SDaniel Bristot de Oliveira
7986d60f896SDaniel Bristot de Oliveira /* we should be good to go */
799eba321a1SGabriele Monaco retval = parse_arguments(full_name, argc, argv);
8006d60f896SDaniel Bristot de Oliveira if (retval)
801eba321a1SGabriele Monaco ikm_usage(1, nested_name, "ikm: failed parsing arguments");
8026d60f896SDaniel Bristot de Oliveira
8036d60f896SDaniel Bristot de Oliveira if (config_trace) {
804eba321a1SGabriele Monaco inst = ikm_setup_trace_instance(nested_name);
8056d60f896SDaniel Bristot de Oliveira if (!inst)
8066d60f896SDaniel Bristot de Oliveira return -1;
8076d60f896SDaniel Bristot de Oliveira }
8086d60f896SDaniel Bristot de Oliveira
809eba321a1SGabriele Monaco retval = ikm_enable(full_name);
8106d60f896SDaniel Bristot de Oliveira if (retval < 0)
8116d60f896SDaniel Bristot de Oliveira goto out_free_instance;
8126d60f896SDaniel Bristot de Oliveira
8136d60f896SDaniel Bristot de Oliveira if (config_trace)
8146d60f896SDaniel Bristot de Oliveira ikm_print_header(inst->seq);
8156d60f896SDaniel Bristot de Oliveira
8166d60f896SDaniel Bristot de Oliveira while (!should_stop()) {
8176d60f896SDaniel Bristot de Oliveira if (config_trace) {
8186d60f896SDaniel Bristot de Oliveira retval = tracefs_iterate_raw_events(inst->tep,
8196d60f896SDaniel Bristot de Oliveira inst->inst,
8206d60f896SDaniel Bristot de Oliveira NULL,
8216d60f896SDaniel Bristot de Oliveira 0,
8226d60f896SDaniel Bristot de Oliveira collect_registered_events,
8236d60f896SDaniel Bristot de Oliveira inst);
8246d60f896SDaniel Bristot de Oliveira if (retval) {
8256d60f896SDaniel Bristot de Oliveira err_msg("ikm: error reading trace buffer\n");
8266d60f896SDaniel Bristot de Oliveira break;
8276d60f896SDaniel Bristot de Oliveira }
8286d60f896SDaniel Bristot de Oliveira }
8296d60f896SDaniel Bristot de Oliveira
8306d60f896SDaniel Bristot de Oliveira sleep(1);
8316d60f896SDaniel Bristot de Oliveira }
8326d60f896SDaniel Bristot de Oliveira
833eba321a1SGabriele Monaco ikm_disable(full_name);
8346d60f896SDaniel Bristot de Oliveira ikm_destroy_trace_instance(inst);
8356d60f896SDaniel Bristot de Oliveira
8366d60f896SDaniel Bristot de Oliveira if (config_reactor && config_initial_reactor)
837eba321a1SGabriele Monaco ikm_write_reactor(full_name, config_initial_reactor);
8386d60f896SDaniel Bristot de Oliveira
8396d60f896SDaniel Bristot de Oliveira return 1;
8406d60f896SDaniel Bristot de Oliveira
8416d60f896SDaniel Bristot de Oliveira out_free_instance:
8426d60f896SDaniel Bristot de Oliveira ikm_destroy_trace_instance(inst);
8436d60f896SDaniel Bristot de Oliveira if (config_reactor && config_initial_reactor)
844eba321a1SGabriele Monaco ikm_write_reactor(full_name, config_initial_reactor);
8456d60f896SDaniel Bristot de Oliveira return -1;
8466d60f896SDaniel Bristot de Oliveira }
847