From: "Steven Rostedt (Google)" <rostedt@xxxxxxxxxxx> Add a function that checks if an event (or events) are enabled or not. Returns the enums: TRACEFS_ERROR = -1 TRACEFS_ALL_DISABLED = 0 TRACEFS_ALL_ENABLED = 1 TRACEFS_SOME_ENABLED = 2 Signed-off-by: Steven Rostedt (Google) <rostedt@xxxxxxxxxxx> --- Documentation/libtracefs-events.txt | 30 ++++++- include/tracefs.h | 9 ++ src/tracefs-events.c | 128 ++++++++++++++++++++++++++-- 3 files changed, 157 insertions(+), 10 deletions(-) diff --git a/Documentation/libtracefs-events.txt b/Documentation/libtracefs-events.txt index f998c79b04ec..2c1c83bf7685 100644 --- a/Documentation/libtracefs-events.txt +++ b/Documentation/libtracefs-events.txt @@ -4,7 +4,7 @@ libtracefs(3) NAME ---- tracefs_event_systems, tracefs_system_events, tracefs_event_enable, tracefs_event_disable, -tracefs_iterate_raw_events, tracefs_iterate_stop - Work with trace systems and events. +tracefs_event_is_enabled, tracefs_iterate_raw_events, tracefs_iterate_stop - Work with trace systems and events. SYNOPSIS -------- @@ -12,12 +12,22 @@ SYNOPSIS -- *#include <tracefs.h>* +enum tracefs_event_state { + TRACEFS_ERROR = -1, + TRACEFS_ALL_DISABLED = 0, + TRACEFS_ALL_ENABLED = 1, + TRACEFS_SOME_ENABLED = 2, +}; + char pass:[*]pass:[*]*tracefs_event_systems*(const char pass:[*]_tracing_dir_); char pass:[*]pass:[*]*tracefs_system_events*(const char pass:[*]_tracing_dir_, const char pass:[*]_system_); int *tracefs_event_enable*(struct tracefs_instance pass:[*]_instance_, const char pass:[*]_system_, const char pass:[*]_event_); int *tracefs_event_disable*(struct tracefs_instance pass:[*]_instance_, const char pass:[*]_system_, const char pass:[*]_event_); +enum tracefs_enable_state *tracefs_event_is_enabled*(struct tracefs_instance pass:[*]instance, + const char pass:[*]system, const char pass:[*]event); + int *tracefs_iterate_raw_events*(struct tep_handle pass:[*]_tep_, struct tracefs_instance pass:[*]_instance_, cpu_set_t pass:[*]_cpus_, int _cpu_size_, int (pass:[*]_callback_)(struct tep_event pass:[*], struct tep_record pass:[*], int, void pass:[*]), @@ -61,6 +71,24 @@ events. That is, if _instance_ is NULL, then the top level tracing directory is used. If both _system_ and _event_ are NULL then all events are disabled for the given _instance_, and so on. +The *tracefs_event_is_enabled()* returns if an event is enabled, a set of +events are enabled, a system is enabled, or all events are enabled. If both +_system_ and _event_ are NULL, then it returns the enable state of all events. +If _system_ is not NULL and _event_ is NULL, then it will check if all the events +in all the systems that _system_ and return the enable state of those events. +If _system_ is NULL and _event_ is not NULL, then it will match all the events +in all systmes that match _event_ and return their enabled state. If both _system_ +and _event_ are not NULL, then it will return the enabled state of all matching +events. The enabled state is defined as: + +*TRACEFS_ERROR* - An error occurred including no event were matched. + +*TRACEFS_ALL_DISABLED* - All matching events are disabled. + +*TRACEFS_ALL_ENABLED* - All matching events are enabled. + +*TRACEFS_SOME_ENABLED* - Some matching events were enabled while others were not. + The *tracefs_iterate_raw_events()* function will read the tracefs raw data buffers and call the specified _callback_ function for every event it encounters. Events are iterated in sorted order: oldest first. An initialized diff --git a/include/tracefs.h b/include/tracefs.h index 9f0bdc62836a..f2524b07501d 100644 --- a/include/tracefs.h +++ b/include/tracefs.h @@ -67,8 +67,17 @@ int tracefs_trace_off(struct tracefs_instance *instance); int tracefs_trace_on_fd(int fd); int tracefs_trace_off_fd(int fd); +enum tracefs_enable_state { + TRACEFS_ERROR = -1, + TRACEFS_ALL_DISABLED = 0, + TRACEFS_ALL_ENABLED = 1, + TRACEFS_SOME_ENABLED = 2, +}; + int tracefs_event_enable(struct tracefs_instance *instance, const char *system, const char *event); int tracefs_event_disable(struct tracefs_instance *instance, const char *system, const char *event); +enum tracefs_enable_state tracefs_event_is_enabled(struct tracefs_instance *instance, + const char *system, const char *event); char *tracefs_error_last(struct tracefs_instance *instance); char *tracefs_error_all(struct tracefs_instance *instance); diff --git a/src/tracefs-events.c b/src/tracefs-events.c index d870241e127f..57b22964f893 100644 --- a/src/tracefs-events.c +++ b/src/tracefs-events.c @@ -1044,9 +1044,68 @@ static bool match(const char *str, regex_t *re) return regexec(re, str, 0, NULL, 0) == 0; } +enum event_state { + STATE_INIT, + STATE_ENABLED, + STATE_DISABLED, + STATE_MIXED, + STATE_ERROR, +}; + +static int read_event_state(struct tracefs_instance *instance, const char *file, + enum event_state *state) +{ + char *val; + int ret = 0; + + if (*state == STATE_ERROR) + return -1; + + val = tracefs_instance_file_read(instance, file, NULL); + if (!val) + return -1; + + switch (val[0]) { + case '0': + switch (*state) { + case STATE_INIT: + *state = STATE_DISABLED; + break; + case STATE_ENABLED: + *state = STATE_MIXED; + break; + default: + break; + } + break; + case '1': + switch (*state) { + case STATE_INIT: + *state = STATE_ENABLED; + break; + case STATE_DISABLED: + *state = STATE_MIXED; + break; + default: + break; + } + break; + case 'X': + *state = STATE_MIXED; + break; + default: + *state = TRACEFS_ERROR; + ret = -1; + break; + } + free(val); + + return ret; +} + static int enable_disable_event(struct tracefs_instance *instance, const char *system, const char *event, - bool enable) + bool enable, enum event_state *state) { const char *str = enable ? "1" : "0"; char *system_event; @@ -1056,14 +1115,18 @@ static int enable_disable_event(struct tracefs_instance *instance, if (ret < 0) return ret; - ret = tracefs_instance_file_write(instance, system_event, str); + if (state) + ret = read_event_state(instance, system_event, state); + else + ret = tracefs_instance_file_write(instance, system_event, str); free(system_event); return ret; } static int enable_disable_system(struct tracefs_instance *instance, - const char *system, bool enable) + const char *system, bool enable, + enum event_state *state) { const char *str = enable ? "1" : "0"; char *system_path; @@ -1073,7 +1136,10 @@ static int enable_disable_system(struct tracefs_instance *instance, if (ret < 0) return ret; - ret = tracefs_instance_file_write(instance, system_path, str); + if (state) + ret = read_event_state(instance, system_path, state); + else + ret = tracefs_instance_file_write(instance, system_path, str); free(system_path); return ret; @@ -1111,7 +1177,7 @@ static int make_regex(regex_t *re, const char *match) static int event_enable_disable(struct tracefs_instance *instance, const char *system, const char *event, - bool enable) + bool enable, enum event_state *state) { regex_t system_re, event_re; char **systems; @@ -1148,7 +1214,7 @@ static int event_enable_disable(struct tracefs_instance *instance, /* Check for the short cut first */ if (!event) { - ret = enable_disable_system(instance, systems[s], enable); + ret = enable_disable_system(instance, systems[s], enable, state); if (ret < 0) break; ret = 0; @@ -1163,7 +1229,7 @@ static int event_enable_disable(struct tracefs_instance *instance, if (!match(events[e], &event_re)) continue; ret = enable_disable_event(instance, systems[s], - events[e], enable); + events[e], enable, state); if (ret < 0) break; ret = 0; @@ -1202,11 +1268,55 @@ static int event_enable_disable(struct tracefs_instance *instance, int tracefs_event_enable(struct tracefs_instance *instance, const char *system, const char *event) { - return event_enable_disable(instance, system, event, true); + return event_enable_disable(instance, system, event, true, NULL); } int tracefs_event_disable(struct tracefs_instance *instance, const char *system, const char *event) { - return event_enable_disable(instance, system, event, false); + return event_enable_disable(instance, system, event, false, NULL); +} + +/** + * tracefs_event_is_enabled - return if the event is enabled or not + * @instance: ftrace instance, can be NULL for the top instance + * @system: The name of the system to check + * @event: The name of the event to check + * + * Checks is an event or multiple events are enabled. + * + * If @system is NULL, then it will check all the systems where @event is + * a match. + * + * If @event is NULL, then it will check all events where @system is a match. + * + * If both @system and @event are NULL, then it will check all events + * + * Returns TRACEFS_ALL_ENABLED if all matching are enabled. + * Returns TRACEFS_SOME_ENABLED if some are enabled and some are not + * Returns TRACEFS_ALL_DISABLED if none of the events are enabled. + * Returns TRACEFS_ERROR if there is an error reading the events. + */ +enum tracefs_enable_state +tracefs_event_is_enabled(struct tracefs_instance *instance, + const char *system, const char *event) +{ + enum event_state state = STATE_INIT; + int ret; + + ret = event_enable_disable(instance, system, event, false, &state); + + if (ret < 0) + return TRACEFS_ERROR; + + switch (state) { + case STATE_ENABLED: + return TRACEFS_ALL_ENABLED; + case STATE_DISABLED: + return TRACEFS_ALL_DISABLED; + case STATE_MIXED: + return TRACEFS_SOME_ENABLED; + default: + return TRACEFS_ERROR; + } } -- 2.35.1