@@ -80,4 +80,65 @@ int tracefs_fill_local_events(const char *tracing_dir,
char *tracefs_get_clock(struct tracefs_instance *instance);
+enum tracefs_option_id {
+ TRACEFS_OPTION_INVALID = 0,
+ TRACEFS_OPTION_ANNOTATE,
+ TRACEFS_OPTION_BIN,
+ TRACEFS_OPTION_BLK_CGNAME,
+ TRACEFS_OPTION_BLK_CGROUP,
+ TRACEFS_OPTION_BLK_CLASSIC,
+ TRACEFS_OPTION_BLOCK,
+ TRACEFS_OPTION_CONTEXT_INFO,
+ TRACEFS_OPTION_DISABLE_ON_FREE,
+ TRACEFS_OPTION_DISPLAY_GRAPH,
+ TRACEFS_OPTION_EVENT_FORK,
+ TRACEFS_OPTION_FGRAPH_ABSTIME,
+ TRACEFS_OPTION_FGRAPH_CPU,
+ TRACEFS_OPTION_FGRAPH_DURATION,
+ TRACEFS_OPTION_FGRAPH_IRQS,
+ TRACEFS_OPTION_FGRAPH_OVERHEAD,
+ TRACEFS_OPTION_FGRAPH_OVERRUN,
+ TRACEFS_OPTION_FGRAPH_PROC,
+ TRACEFS_OPTION_FGRAPH_TAIL,
+ TRACEFS_OPTION_FUNC_STACKTRACE,
+ TRACEFS_OPTION_FUNCTION_FORK,
+ TRACEFS_OPTION_FUNCTION_TRACE,
+ TRACEFS_OPTION_GRAPH_TIME,
+ TRACEFS_OPTION_HEX,
+ TRACEFS_OPTION_IRQ_INFO,
+ TRACEFS_OPTION_LATENCY_FORMAT,
+ TRACEFS_OPTION_MARKERS,
+ TRACEFS_OPTION_OVERWRITE,
+ TRACEFS_OPTION_PAUSE_ON_TRACE,
+ TRACEFS_OPTION_PRINTK_MSG_ONLY,
+ TRACEFS_OPTION_PRINT_PARENT,
+ TRACEFS_OPTION_RAW,
+ TRACEFS_OPTION_RECORD_CMD,
+ TRACEFS_OPTION_RECORD_TGID,
+ TRACEFS_OPTION_SLEEP_TIME,
+ TRACEFS_OPTION_STACKTRACE,
+ TRACEFS_OPTION_SYM_ADDR,
+ TRACEFS_OPTION_SYM_OFFSET,
+ TRACEFS_OPTION_SYM_USEROBJ,
+ TRACEFS_OPTION_TRACE_PRINTK,
+ TRACEFS_OPTION_USERSTACKTRACE,
+ TRACEFS_OPTION_VERBOSE,
+};
+#define TRACEFS_OPTION_MAX (TRACEFS_OPTION_VERBOSE + 1)
+
+struct tracefs_options_mask {
+ unsigned long long mask;
+};
+void tracefs_option_set(struct tracefs_options_mask *options, enum tracefs_option_id id);
+void tracefs_option_clear(struct tracefs_options_mask *options, enum tracefs_option_id id);
+bool tracefs_option_is_set(struct tracefs_options_mask options, enum tracefs_option_id id);
+
+struct tracefs_options_mask *tracefs_options_get_supported(struct tracefs_instance *instance);
+bool tracefs_option_is_supported(struct tracefs_instance *instance, enum tracefs_option_id id);
+struct tracefs_options_mask *tracefs_options_get_enabled(struct tracefs_instance *instance);
+bool tracefs_option_is_enabled(struct tracefs_instance *instance, enum tracefs_option_id id);
+int tracefs_option_enable(struct tracefs_instance *instance, enum tracefs_option_id id);
+int tracefs_option_diasble(struct tracefs_instance *instance, enum tracefs_option_id id);
+const char *tracefs_option_name(enum tracefs_option_id id);
+
#endif /* _TRACE_FS_H */
@@ -9,12 +9,27 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+#include <errno.h>
#include "tracefs.h"
#include "tracefs-local.h"
#define TRACE_CTRL "tracing_on"
+static const char * const options_map[TRACEFS_OPTION_MAX] = {
+ "unknown", "annotate", "bin", "blk_cgname", "blk_cgroup", "blk_classic",
+ "block", "context-info", "disable_on_free", "display-graph", "event-fork",
+ "funcgraph-abstime", "funcgraph-cpu", "funcgraph-duration", "funcgraph-irqs",
+ "funcgraph-overhead", "funcgraph-overrun", "funcgraph-proc", "funcgraph-tail",
+ "func_stack_trace", "function-fork", "function-trace", "graph-time", "hex",
+ "irq-info", "latency-format", "markers", "overwrite", "pause-on-trace",
+ "printk-msg-only", "print-parent", "raw", "record-cmd", "record-tgid",
+ "sleep-time", "stacktrace", "sym-addr", "sym-offset", "sym-userobj",
+ "trace_printk", "userstacktrace", "verbose" };
+
static int trace_on_off(int fd, bool on)
{
const char *val = on ? "1" : "0";
@@ -107,3 +122,232 @@ int tracefs_trace_off_fd(int fd)
return -1;
return trace_on_off(fd, false);
}
+
+/**
+ * tracefs_option_name - Get trace option name from id
+ * @id: trace option id
+ *
+ * Returns string with option name, or "unknown" in case of not known option id.
+ * The returned string must *not* be freed.
+ */
+const char *tracefs_option_name(enum tracefs_option_id id)
+{
+ if (id < TRACEFS_OPTION_MAX)
+ return options_map[id];
+
+ return options_map[0];
+}
+
+/**
+ * tracefs_option_id - Get trace option ID from name
+ * @name: trace option name
+ *
+ * Returns trace option ID or TRACEFS_OPTION_INVALID in case of an error or
+ * unknown option name.
+ */
+enum tracefs_option_id tracefs_option_id(char *name)
+{
+ int i;
+
+ if (!name)
+ return TRACEFS_OPTION_INVALID;
+
+ for (i = 0; i < TRACEFS_OPTION_MAX; i++) {
+ if (strlen(name) == strlen(options_map[i]) &&
+ !strcmp(options_map[i], name))
+ return i;
+ }
+
+ return TRACEFS_OPTION_INVALID;
+}
+
+static struct tracefs_options_mask *trace_get_options(struct tracefs_instance *instance,
+ bool enabled)
+{
+ struct tracefs_options_mask *bitmask;
+ enum tracefs_option_id id;
+ char file[PATH_MAX];
+ struct dirent *dent;
+ char *dname = NULL;
+ DIR *dir = NULL;
+ long long val;
+
+ bitmask = calloc(1, sizeof(struct tracefs_options_mask));
+ if (!bitmask)
+ return NULL;
+ dname = tracefs_instance_get_file(instance, "options");
+ if (!dname)
+ goto error;
+ dir = opendir(dname);
+ if (!dir)
+ goto error;
+
+ while ((dent = readdir(dir))) {
+ if (*dent->d_name == '.')
+ continue;
+ if (enabled) {
+ snprintf(file, PATH_MAX, "options/%s", dent->d_name);
+ if (tracefs_instance_file_read_number(instance, file, &val) != 0 ||
+ val != 1)
+ continue;
+ }
+ id = tracefs_option_id(dent->d_name);
+ if (id != TRACEFS_OPTION_INVALID)
+ tracefs_option_set(bitmask, id);
+ }
+ closedir(dir);
+ tracefs_put_tracing_file(dname);
+
+ return bitmask;
+
+error:
+ if (dir)
+ closedir(dir);
+ tracefs_put_tracing_file(dname);
+ free(bitmask);
+ return NULL;
+}
+
+/**
+ * tracefs_options_get_supported - Get all supported trace options in given instance
+ * @instance: ftrace instance, can be NULL for the top instance
+ *
+ * Returns allocated bitmask structure with all trace options, supported in given
+ * instance, or NULL in case of an error. The returned structure must be freed with free()
+ */
+struct tracefs_options_mask *tracefs_options_get_supported(struct tracefs_instance *instance)
+{
+ return trace_get_options(instance, false);
+}
+
+/**
+ * tracefs_options_get_enabled - Get all currently enabled trace options in given instance
+ * @instance: ftrace instance, can be NULL for the top instance
+ *
+ * Returns allocated bitmask structure with all trace options, enabled in given
+ * instance, or NULL in case of an error. The returned structure must be freed with free()
+ */
+struct tracefs_options_mask *tracefs_options_get_enabled(struct tracefs_instance *instance)
+{
+ return trace_get_options(instance, true);
+}
+
+static int trace_config_option(struct tracefs_instance *instance,
+ enum tracefs_option_id id, bool set)
+{
+ char *set_str = set ? "1" : "0";
+ char file[PATH_MAX];
+ const char *name;
+
+ name = tracefs_option_name(id);
+ if (!name)
+ return -1;
+
+ snprintf(file, PATH_MAX, "options/%s", name);
+ if (strlen(set_str) != tracefs_instance_file_write(instance, file, set_str))
+ return -1;
+ return 0;
+}
+
+/**
+ * tracefs_option_enable - Enable trace option
+ * @instance: ftrace instance, can be NULL for the top instance
+ * @id: trace option id
+ *
+ * Returns -1 in case of an error or 0 otherwise
+ */
+int tracefs_option_enable(struct tracefs_instance *instance, enum tracefs_option_id id)
+{
+ return trace_config_option(instance, id, true);
+}
+
+/**
+ * tracefs_option_diasble - Disable trace option
+ * @instance: ftrace instance, can be NULL for the top instance
+ * @id: trace option id
+ *
+ * Returns -1 in case of an error or 0 otherwise
+ */
+int tracefs_option_diasble(struct tracefs_instance *instance, enum tracefs_option_id id)
+{
+ return trace_config_option(instance, id, false);
+}
+
+/**
+ * tracefs_option_is_supported - Check if an option is supported
+ * @instance: ftrace instance, can be NULL for the top instance
+ * @id: trace option id
+ *
+ * Returns true if an option with given id is supported by the system, false if
+ * it is not supported.
+ */
+bool tracefs_option_is_supported(struct tracefs_instance *instance, enum tracefs_option_id id)
+{
+ const char *name = tracefs_option_name(id);
+ char file[PATH_MAX];
+
+ if (!name)
+ return false;
+ snprintf(file, PATH_MAX, "options/%s", name);
+ return tracefs_file_exists(instance, file);
+}
+
+/**
+ * tracefs_option_is_enabled - Check if an option is enabled in given instance
+ * @instance: ftrace instance, can be NULL for the top instance
+ * @id: trace option id
+ *
+ * Returns true if an option with given id is enabled in the given instance,
+ * false if it is not enabled.
+ */
+bool tracefs_option_is_enabled(struct tracefs_instance *instance, enum tracefs_option_id id)
+{
+ const char *name = tracefs_option_name(id);
+ char file[PATH_MAX];
+ long long res;
+
+ if (!name)
+ return false;
+ snprintf(file, PATH_MAX, "options/%s", name);
+ if (!tracefs_instance_file_read_number(instance, file, &res) && res)
+ return true;
+
+ return false;
+}
+
+/**
+ * tracefs_option_is_set - Check if given option is set in the bitmask
+ * @options: Options bitmask
+ * @id: trace option id
+ *
+ * Returns true if an option with given id is set in the bitmask,
+ * false if it is not set.
+ */
+bool tracefs_option_is_set(struct tracefs_options_mask options, enum tracefs_option_id id)
+{
+ if (id > TRACEFS_OPTION_INVALID)
+ return options.mask & (1ULL << (id - 1));
+ return false;
+}
+
+/**
+ * tracefs_option_set - Set option in options bitmask
+ * @options: Pointer to a bitmask with options
+ * @id: trace option id
+ */
+void tracefs_option_set(struct tracefs_options_mask *options, enum tracefs_option_id id)
+{
+ if (options && id > TRACEFS_OPTION_INVALID)
+ options->mask |= (1ULL << (id - 1));
+}
+
+/**
+ * tracefs_option_clear - Clear option from options bitmask
+ * @options: Pointer to a bitmask with options
+ * @id: trace option id
+ */
+void tracefs_option_clear(struct tracefs_options_mask *options, enum tracefs_option_id id)
+{
+ if (options && id > TRACEFS_OPTION_INVALID)
+ options->mask &= ~(1ULL << (id - 1));
+}
These new APIs can be used to check and set various trace options tracefs_option_set(); tracefs_option_clear(); tracefs_option_is_set(); tracefs_options_get_supported(); tracefs_option_is_supported(); tracefs_options_get_enabled(); tracefs_option_is_enabled(); tracefs_option_enable(); tracefs_option_diasble(); tracefs_option_name(); Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com> --- include/tracefs.h | 61 +++++++++++ src/tracefs-tools.c | 244 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+)