From: "Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com>
To: rostedt@goodmis.org
Cc: linux-trace-devel@vger.kernel.org
Subject: [PATCH 1/5] libtracefs: New APIs for trace options
Date: Fri, 15 Jan 2021 07:04:06 +0200 [thread overview]
Message-ID: <20210115050410.1194011-2-tz.stoyanov@gmail.com> (raw)
In-Reply-To: <20210115050410.1194011-1-tz.stoyanov@gmail.com>
These new APIs can be used to check and set various trace options
tracefs_options_get_supported();
tracefs_option_is_supported();
tracefs_options_get_enabled();
tracefs_option_is_enabled();
tracefs_options_set();
tracefs_options_clear();
tracefs_option_string();
Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
include/tracefs.h | 54 ++++++++++
src/tracefs-tools.c | 251 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 305 insertions(+)
diff --git a/include/tracefs.h b/include/tracefs.h
index 85a776e..1f10a00 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -80,4 +80,58 @@ int tracefs_fill_local_events(const char *tracing_dir,
char *tracefs_get_clock(struct tracefs_instance *instance);
+#define TRACEFS_OPTION_ANNOTATE ((unsigned long long)1 << 0)
+#define TRACEFS_OPTION_BIN ((unsigned long long)1 << 1)
+#define TRACEFS_OPTION_BLK_CGNAME ((unsigned long long)1 << 2)
+#define TRACEFS_OPTION_BLK_CGROUP ((unsigned long long)1 << 3)
+#define TRACEFS_OPTION_BLK_CLASSIC ((unsigned long long)1 << 4)
+#define TRACEFS_OPTION_BLOCK ((unsigned long long)1 << 5)
+#define TRACEFS_OPTION_CONTEXT_INFO ((unsigned long long)1 << 6)
+#define TRACEFS_OPTION_DISABLE_ON_FREE ((unsigned long long)1 << 7)
+#define TRACEFS_OPTION_DISPLAY_GRAPH ((unsigned long long)1 << 8)
+#define TRACEFS_OPTION_EVENT_FORK ((unsigned long long)1 << 9)
+#define TRACEFS_OPTION_FGRAPH_ABSTIME ((unsigned long long)1 << 10)
+#define TRACEFS_OPTION_FGRAPH_CPU ((unsigned long long)1 << 11)
+#define TRACEFS_OPTION_FGRAPH_DURATION ((unsigned long long)1 << 12)
+#define TRACEFS_OPTION_FGRAPH_IRQS ((unsigned long long)1 << 13)
+#define TRACEFS_OPTION_FGRAPH_OVERHEAD ((unsigned long long)1 << 14)
+#define TRACEFS_OPTION_FGRAPH_OVERRUN ((unsigned long long)1 << 15)
+#define TRACEFS_OPTION_FGRAPH_PROC ((unsigned long long)1 << 16)
+#define TRACEFS_OPTION_FGRAPH_TAIL ((unsigned long long)1 << 17)
+#define TRACEFS_OPTION_FUNC_STACKTRACE ((unsigned long long)1 << 18)
+#define TRACEFS_OPTION_FUNCTION_FORK ((unsigned long long)1 << 19)
+#define TRACEFS_OPTION_FUNCTION_TRACE ((unsigned long long)1 << 20)
+#define TRACEFS_OPTION_GRAPH_TIME ((unsigned long long)1 << 21)
+#define TRACEFS_OPTION_HEX ((unsigned long long)1 << 22)
+#define TRACEFS_OPTION_IRQ_INFO ((unsigned long long)1 << 23)
+#define TRACEFS_OPTION_LATENCY_FORMAT ((unsigned long long)1 << 24)
+#define TRACEFS_OPTION_MARKERS ((unsigned long long)1 << 25)
+#define TRACEFS_OPTION_OVERWRITE ((unsigned long long)1 << 26)
+#define TRACEFS_OPTION_PAUSE_ON_TRACE ((unsigned long long)1 << 27)
+#define TRACEFS_OPTION_PRINTK_MSG_ONLY ((unsigned long long)1 << 28)
+#define TRACEFS_OPTION_PRINT_PARENT ((unsigned long long)1 << 29)
+#define TRACEFS_OPTION_RAW ((unsigned long long)1 << 30)
+#define TRACEFS_OPTION_RECORD_CMD ((unsigned long long)1 << 31)
+#define TRACEFS_OPTION_RECORD_TGID ((unsigned long long)1 << 32)
+#define TRACEFS_OPTION_SLEEP_TIME ((unsigned long long)1 << 33)
+#define TRACEFS_OPTION_STACKTRACE ((unsigned long long)1 << 34)
+#define TRACEFS_OPTION_SYM_ADDR ((unsigned long long)1 << 35)
+#define TRACEFS_OPTION_SYM_OFFSET ((unsigned long long)1 << 36)
+#define TRACEFS_OPTION_SYM_USEROBJ ((unsigned long long)1 << 37)
+#define TRACEFS_OPTION_TEST_NOP_ACCEPT ((unsigned long long)1 << 38)
+#define TRACEFS_OPTION_TEST_NOP_REFUSE ((unsigned long long)1 << 39)
+#define TRACEFS_OPTION_TRACE_PRINTK ((unsigned long long)1 << 40)
+#define TRACEFS_OPTION_USERSTACKTRACE ((unsigned long long)1 << 41)
+#define TRACEFS_OPTION_VERBOSE ((unsigned long long)1 << 42)
+
+#define TRACEFS_OPTION_INVALID ((unsigned long long)1 << 43)
+
+unsigned long long tracefs_options_get_supported(struct tracefs_instance *instance);
+bool tracefs_option_is_supported(struct tracefs_instance *instance, unsigned long long id);
+unsigned long long tracefs_options_get_enabled(struct tracefs_instance *instance);
+bool tracefs_option_is_enabled(struct tracefs_instance *instance, unsigned long long id);
+int tracefs_options_set(struct tracefs_instance *instance, unsigned long long options);
+int tracefs_options_clear(struct tracefs_instance *instance, unsigned long long options);
+const char *tracefs_option_string(unsigned long long id);
+
#endif /* _TRACE_FS_H */
diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c
index 101f389..0505552 100644
--- a/src/tracefs-tools.c
+++ b/src/tracefs-tools.c
@@ -9,12 +9,66 @@
#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"
+struct options_map {
+ unsigned long long id;
+ char *name;
+} options_map[] = {
+ { TRACEFS_OPTION_ANNOTATE, "annotate" },
+ { TRACEFS_OPTION_BIN, "bin" },
+ { TRACEFS_OPTION_BLK_CGNAME, "blk_cgname" },
+ { TRACEFS_OPTION_BLK_CGROUP, "blk_cgroup" },
+ { TRACEFS_OPTION_BLK_CLASSIC, "blk_classic" },
+ { TRACEFS_OPTION_BLOCK, "block" },
+ { TRACEFS_OPTION_CONTEXT_INFO, "context-info" },
+ { TRACEFS_OPTION_DISABLE_ON_FREE, "disable_on_free" },
+ { TRACEFS_OPTION_DISPLAY_GRAPH, "display-graph" },
+ { TRACEFS_OPTION_EVENT_FORK, "event-fork" },
+ { TRACEFS_OPTION_FGRAPH_ABSTIME, "funcgraph-abstime" },
+ { TRACEFS_OPTION_FGRAPH_CPU, "funcgraph-cpu" },
+ { TRACEFS_OPTION_FGRAPH_DURATION, "funcgraph-duration" },
+ { TRACEFS_OPTION_FGRAPH_IRQS, "funcgraph-irqs" },
+ { TRACEFS_OPTION_FGRAPH_OVERHEAD, "funcgraph-overhead" },
+ { TRACEFS_OPTION_FGRAPH_OVERRUN, "funcgraph-overrun" },
+ { TRACEFS_OPTION_FGRAPH_PROC, "funcgraph-proc" },
+ { TRACEFS_OPTION_FGRAPH_TAIL, "funcgraph-tail" },
+ { TRACEFS_OPTION_FUNC_STACKTRACE, "func_stack_trace" },
+ { TRACEFS_OPTION_FUNCTION_FORK, "function-fork" },
+ { TRACEFS_OPTION_FUNCTION_TRACE, "function-trace" },
+ { TRACEFS_OPTION_GRAPH_TIME, "graph-time" },
+ { TRACEFS_OPTION_HEX, "hex" },
+ { TRACEFS_OPTION_IRQ_INFO, "irq-info" },
+ { TRACEFS_OPTION_LATENCY_FORMAT, "latency-format" },
+ { TRACEFS_OPTION_MARKERS, "markers" },
+ { TRACEFS_OPTION_OVERWRITE, "overwrite" },
+ { TRACEFS_OPTION_PAUSE_ON_TRACE, "pause-on-trace" },
+ { TRACEFS_OPTION_PRINTK_MSG_ONLY, "printk-msg-only" },
+ { TRACEFS_OPTION_PRINT_PARENT, "print-parent" },
+ { TRACEFS_OPTION_RAW, "raw" },
+ { TRACEFS_OPTION_RECORD_CMD, "record-cmd" },
+ { TRACEFS_OPTION_RECORD_TGID, "record-tgid" },
+ { TRACEFS_OPTION_SLEEP_TIME, "sleep-time" },
+ { TRACEFS_OPTION_STACKTRACE, "stacktrace" },
+ { TRACEFS_OPTION_SYM_ADDR, "sym-addr" },
+ { TRACEFS_OPTION_SYM_OFFSET, "sym-offset" },
+ { TRACEFS_OPTION_SYM_USEROBJ, "sym-userobj" },
+ { TRACEFS_OPTION_TEST_NOP_ACCEPT, "test_nop_accept" },
+ { TRACEFS_OPTION_TEST_NOP_REFUSE, "test_nop_refuse" },
+ { TRACEFS_OPTION_TRACE_PRINTK, "trace_printk" },
+ { TRACEFS_OPTION_USERSTACKTRACE, "userstacktrace" },
+ { TRACEFS_OPTION_VERBOSE, "verbose" },
+ { TRACEFS_OPTION_INVALID, "unknown" },
+};
+
static int trace_on_off(int fd, bool on)
{
const char *val = on ? "1" : "0";
@@ -107,3 +161,200 @@ int tracefs_trace_off_fd(int fd)
return -1;
return trace_on_off(fd, false);
}
+
+/**
+ * tracefs_option_string - Get trace option name from ID
+ * @id: trace option ID
+ *
+ * Returns string with option name, or "unknown" in case of not known option ID
+ */
+const char *tracefs_option_string(unsigned long long id)
+{
+ int size = sizeof(options_map) / sizeof(struct options_map);
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (options_map[i].id == id)
+ return options_map[i].name;
+ }
+
+ return options_map[size - 1].name;
+}
+
+/**
+ * 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.
+ */
+unsigned long long tracefs_option_id(char *name)
+{
+ int size = sizeof(options_map) / sizeof(struct options_map);
+ int i;
+
+ if (!name)
+ return TRACEFS_OPTION_INVALID;
+
+ for (i = 0; i < size; i++) {
+ if (strlen(name) == strlen(options_map[i].name) &&
+ !strcmp(options_map[i].name, name))
+ return options_map[i].id;
+ }
+
+ return TRACEFS_OPTION_INVALID;
+}
+
+static unsigned long long trace_get_options(struct tracefs_instance *instance,
+ bool enabled)
+{
+ unsigned long long options = 0;
+ unsigned long long id;
+ char file[PATH_MAX];
+ struct dirent *dent;
+ char *dname = NULL;
+ DIR *dir = NULL;
+ long long val;
+
+ 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)
+ options |= id;
+ }
+ closedir(dir);
+ tracefs_put_tracing_file(dname);
+
+ return options;
+
+error:
+ if (dir)
+ closedir(dir);
+ tracefs_put_tracing_file(dname);
+ return 0;
+}
+
+/**
+ * tracefs_options_get_supported - Get all supported trace options in given instance
+ * @instance: ftrace instance, can be NULL for the top instance
+ *
+ * Returns bitmask of all trace options, supported in given instance
+ */
+unsigned long long 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 bitmask of all trace options, that are currently set in given instance
+ */
+unsigned long long tracefs_options_get_enabled(struct tracefs_instance *instance)
+{
+ return trace_get_options(instance, true);
+}
+
+static int trace_config_options(struct tracefs_instance *instance,
+ unsigned long long options, bool set)
+{
+ int size = sizeof(options_map) / sizeof(struct options_map);
+ char *set_str = set ? "1" : "0";
+ int str_size = strlen(set_str);
+ char file[PATH_MAX];
+ long long i;
+
+ for (i = 0; i < size && options; i++) {
+ if (!(options & options_map[i].id))
+ continue;
+ options &= ~options_map[i].id;
+ snprintf(file, PATH_MAX, "options/%s", options_map[i].name);
+ if (str_size != tracefs_instance_file_write(instance, file, set_str))
+ break;
+ }
+
+ if (options)
+ return -1;
+ return 0;
+}
+
+/**
+ * tracefs_options_set - Enable trace options
+ * @instance: ftrace instance, can be NULL for the top instance
+ * @options: bitmask of trace options that will be enabled
+ *
+ * Returns -1 in case of an error or 0 otherwise
+ */
+int tracefs_options_set(struct tracefs_instance *instance, unsigned long long options)
+{
+ return trace_config_options(instance, options, true);
+}
+
+/**
+ * tracefs_options_clear - Disable trace options
+ * @instance: ftrace instance, can be NULL for the top instance
+ * @options: bitmask of trace options that will be disabled
+ *
+ * Returns -1 in case of an error or 0 otherwise
+ */
+int tracefs_options_clear(struct tracefs_instance *instance, unsigned long long options)
+{
+ return trace_config_options(instance, options, false);
+}
+
+/**
+ * tracefs_option_is_supported - Check if an option is supported
+ * @instance: ftrace instance, can be NULL for the top instance
+ * @id: 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, unsigned long long id)
+{
+ char file[PATH_MAX];
+ const char *oname = tracefs_option_string(id);
+
+ if (!oname)
+ return false;
+ snprintf(file, PATH_MAX, "options/%s", oname);
+ return tracefs_file_exists(instance, (char *)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: 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, unsigned long long id)
+{
+ const char *oname = tracefs_option_string(id);
+ char file[PATH_MAX];
+ long long res;
+
+ if (!oname)
+ return false;
+ snprintf(file, PATH_MAX, "options/%s", oname);
+ if (!tracefs_instance_file_read_number(instance, file, &res) && res)
+ return true;
+
+ return false;
+}
--
2.29.2
next prev parent reply other threads:[~2021-01-15 5:04 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-15 5:04 [PATCH 0/5] New libtracefs APIs for trace options and trace dir Tzvetomir Stoyanov (VMware)
2021-01-15 5:04 ` Tzvetomir Stoyanov (VMware) [this message]
2021-01-19 21:12 ` [PATCH 1/5] libtracefs: New APIs for trace options Steven Rostedt
2021-01-15 5:04 ` [PATCH 2/5] libtracefs: Unit tests for tracing options APIs Tzvetomir Stoyanov (VMware)
2021-01-15 5:04 ` [PATCH 3/5] libtracefs: Add information about top tracing directory in instance structure Tzvetomir Stoyanov (VMware)
2021-01-15 5:04 ` [PATCH 4/5] libtracefs: New APIs for getting existing trace instance Tzvetomir Stoyanov (VMware)
2021-01-19 22:18 ` Steven Rostedt
2021-01-15 5:04 ` [PATCH 5/5] libtracefs: Unit tests for working with non default tracing dir Tzvetomir Stoyanov (VMware)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210115050410.1194011-2-tz.stoyanov@gmail.com \
--to=tz.stoyanov@gmail.com \
--cc=linux-trace-devel@vger.kernel.org \
--cc=rostedt@goodmis.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).