linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] New libtracefs APIs for trace options and trace dir
@ 2021-01-20 15:12 Tzvetomir Stoyanov (VMware)
  2021-01-20 15:12 ` [PATCH v2 1/5] libtracefs: New APIs for trace options Tzvetomir Stoyanov (VMware)
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-01-20 15:12 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel

A new set of tracefs library APIs for:
 - Working with trace options.
 - Working with non default tracing directory.

v2 changes:
 - Changed the trace options IDs from bitmask to enum.
 - Abstracted trace options bitmap structure.
 - Removed test_nop_refuse and test_nop_accept options from the library.
 - Renamed tracefs_instance_get() to tracefs_instance_alloc().
 
Tzvetomir Stoyanov (VMware) (5):
  libtracefs: New APIs for trace options
  libtracefs: Unit tests for tracing options APIs
  libtracefs: Add information about top tracing directory in instance
    structure
  libtracefs: New APIs for getting existing trace instance
  libtracefs: Unit tests for working with non default tracing dir

 include/tracefs.h      |  64 ++++++
 src/tracefs-instance.c | 137 ++++++++++---
 src/tracefs-tools.c    | 244 +++++++++++++++++++++++
 utest/tracefs-utest.c  | 431 +++++++++++++++++++++++++++++++++++------
 4 files changed, 786 insertions(+), 90 deletions(-)

-- 
2.29.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/5] libtracefs: New APIs for trace options
  2021-01-20 15:12 [PATCH v2 0/5] New libtracefs APIs for trace options and trace dir Tzvetomir Stoyanov (VMware)
@ 2021-01-20 15:12 ` Tzvetomir Stoyanov (VMware)
  2021-01-20 15:12 ` [PATCH v2 2/5] libtracefs: Unit tests for tracing options APIs Tzvetomir Stoyanov (VMware)
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-01-20 15:12 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel

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(+)

diff --git a/include/tracefs.h b/include/tracefs.h
index 85a776e..2df596f 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -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 */
diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c
index 101f389..6e7fce5 100644
--- a/src/tracefs-tools.c
+++ b/src/tracefs-tools.c
@@ -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));
+}
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/5] libtracefs: Unit tests for tracing options APIs
  2021-01-20 15:12 [PATCH v2 0/5] New libtracefs APIs for trace options and trace dir Tzvetomir Stoyanov (VMware)
  2021-01-20 15:12 ` [PATCH v2 1/5] libtracefs: New APIs for trace options Tzvetomir Stoyanov (VMware)
@ 2021-01-20 15:12 ` Tzvetomir Stoyanov (VMware)
  2021-01-20 15:12 ` [PATCH v2 3/5] libtracefs: Add information about top tracing directory in instance structure Tzvetomir Stoyanov (VMware)
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-01-20 15:12 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel

Unit tests for these new APIs:

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>
---
 utest/tracefs-utest.c | 144 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/utest/tracefs-utest.c b/utest/tracefs-utest.c
index 0520f49..1f3c042 100644
--- a/utest/tracefs-utest.c
+++ b/utest/tracefs-utest.c
@@ -452,6 +452,148 @@ static void test_tracing_onoff(void)
 		close(fd);
 }
 
+static bool check_option(struct tracefs_instance *instance,
+			 enum tracefs_option_id id, bool exist, int enabled)
+{
+	const char *name = tracefs_option_name(id);
+	char file[PATH_MAX];
+	char *path = NULL;
+	bool ret = false;
+	bool supported;
+	struct stat st;
+	char buf[10];
+	int fd;
+	int r;
+	int rstat;
+
+	CU_TEST(name != NULL);
+	supported = tracefs_option_is_supported(instance, id);
+	CU_TEST(supported == exist);
+	if (supported != exist)
+		goto out;
+	snprintf(file, PATH_MAX, "options/%s", name);
+	path = tracefs_instance_get_file(instance, file);
+	CU_TEST(path != NULL);
+	rstat = stat(path, &st);
+	if (exist) {
+		CU_TEST(rstat == 0);
+		if (rstat != 0)
+			goto out;
+	} else {
+		CU_TEST(stat(path, &st) == -1);
+		if (rstat != -1)
+			goto out;
+	}
+
+	fd = open(path, O_RDONLY);
+	if (exist) {
+		CU_TEST(fd >= 0);
+		if (fd < 0)
+			goto out;
+	} else {
+		CU_TEST(fd < 0);
+		if (fd >= 0)
+			goto out;
+	}
+
+	if (exist && enabled >= 0) {
+		int val = enabled ? '1' : '0';
+
+		r = read(fd, buf, 10);
+		CU_TEST(r >= 1);
+		CU_TEST(buf[0] == val);
+		if (buf[0] != val)
+			goto out;
+	}
+
+	ret = true;
+out:
+	tracefs_put_tracing_file(path);
+	if (fd >= 0)
+		close(fd);
+	return ret;
+}
+
+static bool check_options_mask_empty(struct tracefs_options_mask *mask)
+{
+	int i;
+
+	for (i = 1; i < TRACEFS_OPTION_MAX; i++) {
+		if (tracefs_option_is_set(*mask, i))
+			return false;
+	}
+	return true;
+}
+
+static void test_instance_tracing_options(struct tracefs_instance *instance)
+{
+	struct tracefs_options_mask *enabled;
+	struct tracefs_options_mask *all, *all_copy;
+	enum tracefs_option_id i = 1;
+	char file[PATH_MAX];
+	const char *name;
+
+	all = tracefs_options_get_supported(instance);
+	all_copy = tracefs_options_get_supported(instance);
+	enabled = tracefs_options_get_enabled(instance);
+	CU_TEST(all != NULL);
+
+	/* Invalid parameters test */
+	CU_TEST(!tracefs_option_is_supported(instance, TRACEFS_OPTION_INVALID));
+	CU_TEST(!tracefs_option_is_enabled(instance, TRACEFS_OPTION_INVALID));
+	CU_TEST(tracefs_option_enable(instance, TRACEFS_OPTION_INVALID) == -1);
+	CU_TEST(tracefs_option_diasble(instance, TRACEFS_OPTION_INVALID) == -1);
+	name = tracefs_option_name(TRACEFS_OPTION_INVALID);
+	CU_TEST(!strcmp(name, "unknown"));
+	/* Test all valid options */
+	for (i = 1; i < TRACEFS_OPTION_MAX; i++) {
+		name = tracefs_option_name(i);
+		CU_TEST(name != NULL);
+		CU_TEST(strcmp(name, "unknown"));
+		snprintf(file, PATH_MAX, "options/%s", name);
+
+		if (tracefs_option_is_set(*all, i)) {
+			tracefs_option_clear(all, i);
+			CU_TEST(!tracefs_option_is_set(*all, i));
+			CU_TEST(check_option(instance, i, true, -1));
+			CU_TEST(tracefs_option_is_supported(instance, i));
+		} else {
+			CU_TEST(check_option(instance, i, false, -1));
+			CU_TEST(!tracefs_option_is_supported(instance, i));
+		}
+
+		if (tracefs_option_is_set(*enabled, i)) {
+			tracefs_option_clear(enabled, i);
+			CU_TEST(!tracefs_option_is_set(*enabled, i));
+			CU_TEST(check_option(instance, i, true, 1));
+			CU_TEST(tracefs_option_is_supported(instance, i));
+			CU_TEST(tracefs_option_is_enabled(instance, i));
+			CU_TEST(tracefs_option_diasble(instance, i) == 0);
+			CU_TEST(check_option(instance, i, true, 0));
+			CU_TEST(tracefs_option_enable(instance, i) == 0);
+			CU_TEST(check_option(instance, i, true, 1));
+		} else if (tracefs_option_is_set(*all_copy, i)) {
+			CU_TEST(check_option(instance, i, true, 0));
+			CU_TEST(tracefs_option_is_supported(instance, i));
+			CU_TEST(!tracefs_option_is_enabled(instance, i));
+			CU_TEST(tracefs_option_enable(instance, i) == 0);
+			CU_TEST(check_option(instance, i, true, 1));
+			CU_TEST(tracefs_option_diasble(instance, i) == 0);
+			CU_TEST(check_option(instance, i, true, 0));
+		}
+	}
+	CU_TEST(check_options_mask_empty(all));
+	CU_TEST(check_options_mask_empty(enabled));
+
+	free(all);
+	free(enabled);
+}
+
+static void test_tracing_options(void)
+{
+	test_instance_tracing_options(test_instance);
+}
+
 static void exclude_string(char **strings, char *name)
 {
 	int i;
@@ -761,5 +903,7 @@ void test_tracefs_lib(void)
 		    test_get_clock);
 	CU_add_test(suite, "tracing on / off",
 		    test_tracing_onoff);
+	CU_add_test(suite, "tracing options",
+		    test_tracing_options);
 
 }
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/5] libtracefs: Add information about top tracing directory in instance structure
  2021-01-20 15:12 [PATCH v2 0/5] New libtracefs APIs for trace options and trace dir Tzvetomir Stoyanov (VMware)
  2021-01-20 15:12 ` [PATCH v2 1/5] libtracefs: New APIs for trace options Tzvetomir Stoyanov (VMware)
  2021-01-20 15:12 ` [PATCH v2 2/5] libtracefs: Unit tests for tracing options APIs Tzvetomir Stoyanov (VMware)
@ 2021-01-20 15:12 ` Tzvetomir Stoyanov (VMware)
  2021-01-20 15:12 ` [PATCH v2 4/5] libtracefs: New APIs for getting existing trace instance Tzvetomir Stoyanov (VMware)
  2021-01-20 15:12 ` [PATCH v2 5/5] libtracefs: Unit tests for working with non default tracing dir Tzvetomir Stoyanov (VMware)
  4 siblings, 0 replies; 6+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-01-20 15:12 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel

There are use cases, where the library could be used with non default
system trace directory - for example a partial copy of a system trace
directory from another machine. More flexibility is added to the tracefs
library, to handle these use cases. The full path to the system trace
directory is added in the instance structure and is used to get trace
files from that instance.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 src/tracefs-instance.c | 80 ++++++++++++++++++++++++++----------------
 1 file changed, 49 insertions(+), 31 deletions(-)

diff --git a/src/tracefs-instance.c b/src/tracefs-instance.c
index b5f8298..468da1b 100644
--- a/src/tracefs-instance.c
+++ b/src/tracefs-instance.c
@@ -20,30 +20,43 @@
 
 #define FLAG_INSTANCE_NEWLY_CREATED	(1 << 0)
 struct tracefs_instance {
+	char	*trace_dir;
 	char	*name;
 	int	flags;
 };
 
 /**
  * instance_alloc - allocate a new ftrace instance
+ * @trace_dir - Full path to the tracing directory, where the instance is
  * @name: The name of the instance (instance will point to this)
  *
  * Returns a newly allocated instance, or NULL in case of an error.
  */
-static struct tracefs_instance *instance_alloc(const char *name)
+static struct tracefs_instance *instance_alloc(const char *trace_dir, const char *name)
 {
 	struct tracefs_instance *instance;
 
 	instance = calloc(1, sizeof(*instance));
-	if (instance && name) {
+	if (!instance)
+		goto error;
+	instance->trace_dir = strdup(trace_dir);
+	if (!instance->trace_dir)
+		goto error;
+	if (name) {
 		instance->name = strdup(name);
-		if (!instance->name) {
-			free(instance);
-			instance = NULL;
-		}
+		if (!instance->name)
+			goto error;
 	}
 
 	return instance;
+
+error:
+	if (instance) {
+		free(instance->name);
+		free(instance->trace_dir);
+		free(instance);
+	}
+	return NULL;
 }
 
 /**
@@ -56,6 +69,7 @@ void tracefs_instance_free(struct tracefs_instance *instance)
 {
 	if (!instance)
 		return;
+	free(instance->trace_dir);
 	free(instance->name);
 	free(instance);
 }
@@ -105,12 +119,16 @@ bool tracefs_instance_is_new(struct tracefs_instance *instance)
 struct tracefs_instance *tracefs_instance_create(const char *name)
 {
 	struct tracefs_instance *inst = NULL;
+	char *path = NULL;
+	const char *tdir;
 	struct stat st;
 	mode_t mode;
-	char *path;
 	int ret;
 
-	inst = instance_alloc(name);
+	tdir = tracefs_tracing_dir();
+	if (!tdir)
+		return NULL;
+	inst = instance_alloc(tdir, name);
 	if (!inst)
 		return NULL;
 
@@ -170,18 +188,18 @@ int tracefs_instance_destroy(struct tracefs_instance *instance)
 char *
 tracefs_instance_get_file(struct tracefs_instance *instance, const char *file)
 {
-	char *path;
-	char *buf;
+	char *path = NULL;
 	int ret;
 
-	if (instance && instance->name) {
-		ret = asprintf(&buf, "instances/%s/%s", instance->name, file);
-		if (ret < 0)
-			return NULL;
-		path = tracefs_get_tracing_file(buf);
-		free(buf);
-	} else
-		path = tracefs_get_tracing_file(file);
+	if (!instance)
+		return tracefs_get_tracing_file(file);
+	if (!instance->name)
+		ret = asprintf(&path, "%s/%s", instance->trace_dir, file);
+	else
+		ret = asprintf(&path, "%s/instances/%s/%s",
+			       instance->trace_dir, instance->name, file);
+	if (ret < 0)
+		return NULL;
 
 	return path;
 }
@@ -196,21 +214,21 @@ tracefs_instance_get_file(struct tracefs_instance *instance, const char *file)
  */
 char *tracefs_instance_get_dir(struct tracefs_instance *instance)
 {
-	char *buf;
-	char *path;
+	char *path = NULL;
 	int ret;
 
-	if (instance && instance->name) {
-		ret = asprintf(&buf, "instances/%s", instance->name);
-		if (ret < 0) {
-			warning("Failed to allocate path for instance %s",
-				 instance->name);
-			return NULL;
-		}
-		path = tracefs_get_tracing_file(buf);
-		free(buf);
-	} else
-		path = trace_find_tracing_dir();
+	if (!instance) /* Top instance of default system trace directory */
+		return trace_find_tracing_dir();
+
+	if (!instance->name)
+		return strdup(instance->trace_dir);
+
+	ret = asprintf(&path, "%s/instances/%s", instance->trace_dir, instance->name);
+	if (ret < 0) {
+		warning("Failed to allocate path for instance %s",
+			 instance->name);
+		return NULL;
+	}
 
 	return path;
 }
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 4/5] libtracefs: New APIs for getting existing trace instance
  2021-01-20 15:12 [PATCH v2 0/5] New libtracefs APIs for trace options and trace dir Tzvetomir Stoyanov (VMware)
                   ` (2 preceding siblings ...)
  2021-01-20 15:12 ` [PATCH v2 3/5] libtracefs: Add information about top tracing directory in instance structure Tzvetomir Stoyanov (VMware)
@ 2021-01-20 15:12 ` Tzvetomir Stoyanov (VMware)
  2021-01-20 15:12 ` [PATCH v2 5/5] libtracefs: Unit tests for working with non default tracing dir Tzvetomir Stoyanov (VMware)
  4 siblings, 0 replies; 6+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-01-20 15:12 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel

The new API allocates an instance structure for existing trace instance.
It has an optional tracing_dir parameter, which allows to get instances
from non default trace directory. If the instance with the given name does
not exist, the API fails. If no name is given, the structure for the top
instance in the given trace directory is allocated and returned.

struct tracefs_instance *tracefs_instance_alloc(const char *tracing_dir,
					        const char *name);

This helper API is added also, to get the tracing directory where the
instance is configured. In most cases this should be the default system
trace directroy mount point.

const char *tracefs_instance_get_trace_dir(struct tracefs_instance *instance);

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 include/tracefs.h      |  3 +++
 src/tracefs-instance.c | 57 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/include/tracefs.h b/include/tracefs.h
index 2df596f..3059dbb 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -20,9 +20,12 @@ struct tracefs_instance;
 
 void tracefs_instance_free(struct tracefs_instance *instance);
 struct tracefs_instance *tracefs_instance_create(const char *name);
+struct tracefs_instance *tracefs_instance_alloc(const char *tracing_dir,
+						const char *name);
 int tracefs_instance_destroy(struct tracefs_instance *instance);
 bool tracefs_instance_is_new(struct tracefs_instance *instance);
 const char *tracefs_instance_get_name(struct tracefs_instance *instance);
+const char *tracefs_instance_get_trace_dir(struct tracefs_instance *instance);
 char *
 tracefs_instance_get_file(struct tracefs_instance *instance, const char *file);
 char *tracefs_instance_get_dir(struct tracefs_instance *instance);
diff --git a/src/tracefs-instance.c b/src/tracefs-instance.c
index 468da1b..0df4e13 100644
--- a/src/tracefs-instance.c
+++ b/src/tracefs-instance.c
@@ -151,6 +151,49 @@ error:
 	return NULL;
 }
 
+/**
+ * tracefs_instance_alloc - Allocate an instance structure for existing trace instance
+ * @tracing_dir: full path to the system trace directory, where the new instance is
+ *		 if NULL, the default top tracing directory is used.
+ * @name: Name of the instance.
+ *
+ * Allocates and initializes a new instance structure. If the instance does not
+ * exist, do not create it and exit with error.
+ * Returns a pointer to a newly allocated instance, or NULL in case of an error
+ * or the requested instance does not exists.
+ * The returned instance must be freed by tracefs_instance_free().
+ */
+struct tracefs_instance *tracefs_instance_alloc(const char *tracing_dir,
+						const char *name)
+{
+	struct tracefs_instance *inst = NULL;
+	char file[PATH_MAX];
+	const char *tdir;
+	struct stat st;
+	int ret;
+
+	if (tracing_dir) {
+		ret = stat(tracing_dir, &st);
+		if (ret < 0 || !S_ISDIR(st.st_mode))
+			return NULL;
+		tdir = tracing_dir;
+
+	} else
+		tdir = tracefs_tracing_dir();
+	if (!tdir)
+		return NULL;
+
+	if (name) {
+		sprintf(file, "%s/instances/%s", tdir, name);
+		ret = stat(file, &st);
+		if (ret < 0 || !S_ISDIR(st.st_mode))
+			return NULL;
+	}
+	inst = instance_alloc(tdir, name);
+
+	return inst;
+}
+
 /**
  * tracefs_instance_destroy - Remove a ftrace instance
  * @instance: Pointer to the instance to be removed
@@ -247,6 +290,20 @@ const char *tracefs_instance_get_name(struct tracefs_instance *instance)
 	return NULL;
 }
 
+/**
+ * tracefs_instance_get_trace_dir - return the top trace directory, where the instance is confuigred
+ * @instance: ftrace instance
+ *
+ * Returns the top trace directory where the given @instance is configured.
+ * The returned string must *not* be freed.
+ */
+const char *tracefs_instance_get_trace_dir(struct tracefs_instance *instance)
+{
+	if (instance)
+		return instance->trace_dir;
+	return NULL;
+}
+
 static int write_file(const char *file, const char *str)
 {
 	int ret;
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 5/5] libtracefs: Unit tests for working with non default tracing dir
  2021-01-20 15:12 [PATCH v2 0/5] New libtracefs APIs for trace options and trace dir Tzvetomir Stoyanov (VMware)
                   ` (3 preceding siblings ...)
  2021-01-20 15:12 ` [PATCH v2 4/5] libtracefs: New APIs for getting existing trace instance Tzvetomir Stoyanov (VMware)
@ 2021-01-20 15:12 ` Tzvetomir Stoyanov (VMware)
  4 siblings, 0 replies; 6+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-01-20 15:12 UTC (permalink / raw)
  To: rostedt; +Cc: linux-trace-devel

All unit tests are modified to work with custom defined trace directory,
instead of default system one. A new tests are added which duplicate
part of the system trace directory and test various library APIs on
that copy.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 utest/tracefs-utest.c | 287 +++++++++++++++++++++++++++++++++---------
 1 file changed, 228 insertions(+), 59 deletions(-)

diff --git a/utest/tracefs-utest.c b/utest/tracefs-utest.c
index 1f3c042..ed2693b 100644
--- a/utest/tracefs-utest.c
+++ b/utest/tracefs-utest.c
@@ -10,6 +10,7 @@
 #include <unistd.h>
 #include <time.h>
 #include <dirent.h>
+#include <ftw.h>
 
 #include <CUnit/CUnit.h>
 #include <CUnit/Basic.h>
@@ -18,8 +19,15 @@
 
 #define TRACEFS_SUITE		"trasefs library"
 #define TEST_INSTANCE_NAME	"cunit_test_iter"
+#define TEST_TRACE_DIR		"/tmp/trace_utest.XXXXXX"
 #define TEST_ARRAY_SIZE		500
 
+#define ALL_TRACERS	"available_tracers"
+#define CUR_TRACER	"current_tracer"
+#define PER_CPU		"per_cpu"
+#define TRACE_ON	"tracing_on"
+#define TRACE_CLOCK	"trace_clock"
+
 static struct tracefs_instance *test_instance;
 static struct tep_handle *test_tep;
 struct test_sample {
@@ -55,7 +63,7 @@ static int test_callback(struct tep_event *event, struct tep_record *record,
 	return 0;
 }
 
-static void test_iter_write(void)
+static void test_iter_write(struct tracefs_instance *instance)
 {
 	int cpus = sysconf(_SC_NPROCESSORS_CONF);
 	cpu_set_t *cpuset, *cpusave;
@@ -70,7 +78,7 @@ static void test_iter_write(void)
 
 	sched_getaffinity(0, cpu_size, cpusave);
 
-	path = tracefs_instance_get_file(test_instance, "trace_marker");
+	path = tracefs_instance_get_file(instance, "trace_marker");
 	CU_TEST(path != NULL);
 	fd = open(path, O_WRONLY);
 	tracefs_put_tracing_file(path);
@@ -94,15 +102,15 @@ static void test_iter_write(void)
 }
 
 
-static void iter_raw_events_on_cpu(int cpu)
+static void iter_raw_events_on_cpu(struct tracefs_instance *instance, int cpu)
 {
 	int check = 0;
 	int ret;
 	int i;
 
 	test_found = 0;
-	test_iter_write();
-	ret = tracefs_iterate_raw_events(test_tep, test_instance, NULL, 0,
+	test_iter_write(instance);
+	ret = tracefs_iterate_raw_events(test_tep, instance, NULL, 0,
 					 test_callback, &cpu);
 	CU_TEST(ret == 0);
 	if (cpu < 0) {
@@ -120,22 +128,27 @@ static void iter_raw_events_on_cpu(int cpu)
 	}
 }
 
-static void test_iter_raw_events(void)
+static void test_instance_iter_raw_events(struct tracefs_instance *instance)
 {
 	int cpus = sysconf(_SC_NPROCESSORS_CONF);
 	int ret;
 	int i;
 
-	ret = tracefs_iterate_raw_events(NULL, test_instance, NULL, 0, test_callback, NULL);
+	ret = tracefs_iterate_raw_events(NULL, instance, NULL, 0, test_callback, NULL);
 	CU_TEST(ret < 0);
 	ret = tracefs_iterate_raw_events(test_tep, NULL, NULL, 0, test_callback, NULL);
 	CU_TEST(ret == 0);
-	ret = tracefs_iterate_raw_events(test_tep, test_instance, NULL, 0, NULL, NULL);
+	ret = tracefs_iterate_raw_events(test_tep, instance, NULL, 0, NULL, NULL);
 	CU_TEST(ret < 0);
 
-	iter_raw_events_on_cpu(-1);
+	iter_raw_events_on_cpu(instance, -1);
 	for (i = 0; i < cpus; i++)
-		iter_raw_events_on_cpu(i);
+		iter_raw_events_on_cpu(instance, i);
+}
+
+static void test_iter_raw_events(void)
+{
+	test_instance_iter_raw_events(test_instance);
 }
 
 #define RAND_STR_SIZE 20
@@ -215,10 +228,6 @@ static void test_instance_file_read(struct tracefs_instance *inst, const char *f
 	free(file);
 }
 
-#define ALL_TRACERS	"available_tracers"
-#define CUR_TRACER	"current_tracer"
-#define PER_CPU		"per_cpu"
-#define TRACE_ON	"tracing_on"
 static void test_instance_file(void)
 {
 	struct tracefs_instance *instance = NULL;
@@ -323,7 +332,7 @@ static void test_instance_file(void)
 	free(inst_dir);
 }
 
-static bool check_fd_name(int fd, char *name)
+static bool check_fd_name(int fd, const char *dir, const char *name)
 {
 	char link[PATH_MAX + 1];
 	char path[PATH_MAX + 1];
@@ -344,6 +353,10 @@ static bool check_fd_name(int fd, char *name)
 	if (ret > PATH_MAX || ret < 0)
 		return false;
 	path[ret] = 0;
+	ret = strncmp(dir, path, strlen(dir));
+	CU_TEST(ret == 0);
+	if (ret)
+		return false;
 	file = basename(path);
 	CU_TEST(file != NULL);
 	if (!file)
@@ -389,23 +402,26 @@ static bool check_fd_mode(int fd, int mode)
 	return true;
 }
 
-static void test_instance_file_fd(void)
+static void test_instance_file_fd(struct tracefs_instance *instance)
 {
 	const char *name = get_rand_str();
+	const char *tdir = tracefs_instance_get_trace_dir(instance);
 	long long res = -1;
 	char rd[2];
 	int fd;
 
-	fd = tracefs_instance_file_open(test_instance, name, -1);
+	CU_TEST(tdir != NULL);
+	fd = tracefs_instance_file_open(instance, name, -1);
 	CU_TEST(fd == -1);
-	fd = tracefs_instance_file_open(test_instance, TRACE_ON, O_RDONLY);
+	fd = tracefs_instance_file_open(instance, TRACE_ON, O_RDONLY);
 	CU_TEST(fd >= 0);
-	CU_TEST(check_fd_name(fd, TRACE_ON));
+
+	CU_TEST(check_fd_name(fd, tdir, TRACE_ON));
 	CU_TEST(check_fd_mode(fd, O_RDONLY));
 
-	CU_TEST(tracefs_instance_file_read_number(test_instance, "available_tracer", &res) != 0);
-	CU_TEST(tracefs_instance_file_read_number(test_instance, name, &res) != 0);
-	CU_TEST(tracefs_instance_file_read_number(test_instance, TRACE_ON, &res) == 0);
+	CU_TEST(tracefs_instance_file_read_number(instance, ALL_TRACERS, &res) != 0);
+	CU_TEST(tracefs_instance_file_read_number(instance, name, &res) != 0);
+	CU_TEST(tracefs_instance_file_read_number(instance, TRACE_ON, &res) == 0);
 	CU_TEST((res == 0 || res == 1));
 	CU_TEST(read(fd, &rd, 1) == 1);
 	rd[1] = 0;
@@ -414,44 +430,56 @@ static void test_instance_file_fd(void)
 	close(fd);
 }
 
-static void test_tracing_onoff(void)
+static void test_file_fd(void)
+{
+	test_instance_file_fd(test_instance);
+}
+
+static void test_instance_tracing_onoff(struct tracefs_instance *instance)
 {
+	const char *tdir = tracefs_instance_get_trace_dir(instance);
 	long long res = -1;
 	int fd;
 
-	fd = tracefs_trace_on_get_fd(test_instance);
+	CU_TEST(tdir != NULL);
+	fd = tracefs_trace_on_get_fd(instance);
 	CU_TEST(fd >= 0);
-	CU_TEST(check_fd_name(fd, TRACE_ON));
+	CU_TEST(check_fd_name(fd, tdir, TRACE_ON));
 	CU_TEST(check_fd_mode(fd, O_RDWR));
-	CU_TEST(tracefs_instance_file_read_number(test_instance, TRACE_ON, &res) == 0);
+	CU_TEST(tracefs_instance_file_read_number(instance, TRACE_ON, &res) == 0);
 	if (res == 1) {
-		CU_TEST(tracefs_trace_is_on(test_instance) == 1);
-		CU_TEST(tracefs_trace_off(test_instance) == 0);
-		CU_TEST(tracefs_trace_is_on(test_instance) == 0);
-		CU_TEST(tracefs_trace_on(test_instance) == 0);
-		CU_TEST(tracefs_trace_is_on(test_instance) == 1);
+		CU_TEST(tracefs_trace_is_on(instance) == 1);
+		CU_TEST(tracefs_trace_off(instance) == 0);
+		CU_TEST(tracefs_trace_is_on(instance) == 0);
+		CU_TEST(tracefs_trace_on(instance) == 0);
+		CU_TEST(tracefs_trace_is_on(instance) == 1);
 
 		CU_TEST(tracefs_trace_off_fd(fd) == 0);
-		CU_TEST(tracefs_trace_is_on(test_instance) == 0);
+		CU_TEST(tracefs_trace_is_on(instance) == 0);
 		CU_TEST(tracefs_trace_on_fd(fd) == 0);
-		CU_TEST(tracefs_trace_is_on(test_instance) == 1);
+		CU_TEST(tracefs_trace_is_on(instance) == 1);
 	} else {
-		CU_TEST(tracefs_trace_is_on(test_instance) == 0);
-		CU_TEST(tracefs_trace_on(test_instance) == 0);
-		CU_TEST(tracefs_trace_is_on(test_instance) == 1);
-		CU_TEST(tracefs_trace_off(test_instance) == 0);
-		CU_TEST(tracefs_trace_is_on(test_instance) == 0);
+		CU_TEST(tracefs_trace_is_on(instance) == 0);
+		CU_TEST(tracefs_trace_on(instance) == 0);
+		CU_TEST(tracefs_trace_is_on(instance) == 1);
+		CU_TEST(tracefs_trace_off(instance) == 0);
+		CU_TEST(tracefs_trace_is_on(instance) == 0);
 
 		CU_TEST(tracefs_trace_on_fd(fd) == 0);
-		CU_TEST(tracefs_trace_is_on(test_instance) == 1);
+		CU_TEST(tracefs_trace_is_on(instance) == 1);
 		CU_TEST(tracefs_trace_off_fd(fd) == 0);
-		CU_TEST(tracefs_trace_is_on(test_instance) == 0);
+		CU_TEST(tracefs_trace_is_on(instance) == 0);
 	}
 
 	if (fd >= 0)
 		close(fd);
 }
 
+static void test_tracing_onoff(void)
+{
+	test_instance_tracing_onoff(test_instance);
+}
+
 static bool check_option(struct tracefs_instance *instance,
 			 enum tracefs_option_id id, bool exist, int enabled)
 {
@@ -625,16 +653,13 @@ static void test_check_files(const char *fdir, char **files)
 		CU_TEST(files[i][0] == '/');
 }
 
-static void test_system_event(void)
+static void system_event(const char *tdir)
 {
-	const char *tdir;
+
 	char **systems;
 	char **events;
 	char *sdir = NULL;
 
-	tdir  = tracefs_tracing_dir();
-	CU_TEST(tdir != NULL);
-
 	systems = tracefs_event_systems(tdir);
 	CU_TEST(systems != NULL);
 
@@ -657,7 +682,16 @@ static void test_system_event(void)
 	free(sdir);
 }
 
-static void test_tracers(void)
+static void test_system_event(void)
+{
+	const char *tdir;
+
+	tdir  = tracefs_tracing_dir();
+	CU_TEST(tdir != NULL);
+	system_event(tdir);
+}
+
+static void test_instance_tracers(struct tracefs_instance *instance)
 {
 	const char *tdir;
 	char **tracers;
@@ -665,7 +699,7 @@ static void test_tracers(void)
 	char *tracer;
 	int i;
 
-	tdir  = tracefs_tracing_dir();
+	tdir  = tracefs_instance_get_trace_dir(instance);
 	CU_TEST(tdir != NULL);
 
 	tracers = tracefs_tracers(tdir);
@@ -686,6 +720,11 @@ static void test_tracers(void)
 	free(tfile);
 }
 
+static void test_tracers(void)
+{
+	test_instance_tracers(test_instance);
+}
+
 static void test_check_events(struct tep_handle *tep, char *system, bool exist)
 {
 	struct dirent *dent;
@@ -725,17 +764,13 @@ static void test_check_events(struct tep_handle *tep, char *system, bool exist)
 
 }
 
-static void test_local_events(void)
+static void local_events(const char *tdir)
 {
 	struct tep_handle *tep;
-	const char *tdir;
 	char **systems;
 	char *lsystems[3];
 	int i;
 
-	tdir  = tracefs_tracing_dir();
-	CU_TEST(tdir != NULL);
-
 	tep = tracefs_local_events(tdir);
 	CU_TEST(tep != NULL);
 
@@ -776,6 +811,15 @@ static void test_local_events(void)
 	tracefs_list_free(systems);
 }
 
+static void test_local_events(void)
+{
+	const char *tdir;
+
+	tdir  = tracefs_tracing_dir();
+	CU_TEST(tdir != NULL);
+	local_events(tdir);
+}
+
 struct test_walk_instance {
 	struct tracefs_instance *instance;
 	bool found;
@@ -825,13 +869,13 @@ static void test_instances_walk(void)
 	}
 }
 
-static void current_clock_check(const char *clock)
+static void current_clock_check(struct tracefs_instance *instance, const char *clock)
 {
 	int size = 0;
 	char *clocks;
 	char *str;
 
-	clocks = tracefs_instance_file_read(test_instance, "trace_clock", &size);
+	clocks = tracefs_instance_file_read(instance, TRACE_CLOCK, &size);
 	CU_TEST(clocks != NULL);
 	CU_TEST(size > strlen(clock));
 	str = strstr(clocks, clock);
@@ -842,16 +886,140 @@ static void current_clock_check(const char *clock)
 	free(clocks);
 }
 
-static void test_get_clock(void)
+static void test_instance_get_clock(struct tracefs_instance *instance)
 {
 	const char *clock;
 
-	clock = tracefs_get_clock(test_instance);
+	clock = tracefs_get_clock(instance);
 	CU_TEST(clock != NULL);
-	current_clock_check(clock);
+	current_clock_check(instance, clock);
 	free((char *)clock);
 }
 
+static void test_get_clock(void)
+{
+	test_instance_get_clock(test_instance);
+}
+
+static void copy_trace_file(const char *from, char *to)
+{
+	int fd_from = -1;
+	int fd_to = -1;
+	char buf[512];
+	int ret;
+
+	fd_from = open(from, O_RDONLY);
+	if (fd_from < 0)
+		goto out;
+	fd_to = open(to, O_WRONLY | O_TRUNC | O_CREAT);
+	if (fd_to < 0)
+		goto out;
+
+	while ((ret = read(fd_from, buf, 512)) > 0) {
+		if (write(fd_to, buf, ret) == -1)
+			break;
+	}
+
+out:
+	if (fd_to >= 0)
+		close(fd_to);
+	if (fd_from >= 0)
+		close(fd_from);
+}
+
+static int trace_dir_base;
+static char *trace_tmp_dir;
+static int copy_trace_walk(const char *fpath, const struct stat *sb,
+			   int typeflag, struct FTW *ftwbuf)
+{
+	char path[PATH_MAX];
+
+	sprintf(path, "%s%s", trace_tmp_dir, fpath + trace_dir_base);
+
+	switch (typeflag) {
+	case FTW_D:
+		mkdir(path, 0750);
+		break;
+	case FTW_F:
+		copy_trace_file(fpath, path);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static void dup_trace_dir(char *to, char *dir)
+{
+	const char *trace_dir = tracefs_tracing_dir();
+	char file_from[PATH_MAX];
+	char file_to[PATH_MAX];
+
+	sprintf(file_from, "%s/%s", trace_dir, dir);
+	sprintf(file_to, "%s/%s", to, dir);
+	trace_tmp_dir = file_to;
+	trace_dir_base = strlen(file_from);
+	nftw(file_from, copy_trace_walk, 20, 0);
+}
+
+static void dup_trace_file(char *to, char *file)
+{
+	const char *trace_dir = tracefs_tracing_dir();
+	char file_from[PATH_MAX];
+	char file_to[PATH_MAX];
+
+	sprintf(file_from, "%s/%s", trace_dir, file);
+	sprintf(file_to, "%s/%s", to, file);
+	copy_trace_file(file_from, file_to);
+}
+
+static char *copy_trace_dir(void)
+{
+	char template[] = TEST_TRACE_DIR;
+	char *dname = mkdtemp(template);
+
+	dup_trace_dir(dname, "events");
+	dup_trace_dir(dname, "options");
+	dup_trace_file(dname, TRACE_ON);
+	dup_trace_file(dname, CUR_TRACER);
+	dup_trace_file(dname, TRACE_CLOCK);
+	dup_trace_file(dname, ALL_TRACERS);
+
+	return strdup(dname);
+}
+
+static int del_trace_walk(const char *fpath, const struct stat *sb,
+			  int typeflag, struct FTW *ftwbuf)
+{
+	remove(fpath);
+	return 0;
+}
+
+void del_trace_dir(char *dir)
+{
+	nftw(dir, del_trace_walk, 20, FTW_DEPTH);
+}
+
+static void test_custom_trace_dir(void)
+{
+	struct tracefs_instance *instance;
+	char *dname = copy_trace_dir();
+
+	instance = tracefs_instance_alloc(dname, NULL);
+	CU_TEST(instance != NULL);
+
+	system_event(dname);
+	local_events(dname);
+	test_instance_tracing_options(instance);
+	test_instance_get_clock(instance);
+	test_instance_file_fd(instance);
+	test_instance_tracers(instance);
+
+	tracefs_instance_free(instance);
+	del_trace_dir(dname);
+	free(dname);
+}
+
 static int test_suite_destroy(void)
 {
 	tracefs_instance_destroy(test_instance);
@@ -886,7 +1054,7 @@ void test_tracefs_lib(void)
 	CU_add_test(suite, "tracing file / directory APIs",
 		    test_trace_file);
 	CU_add_test(suite, "instance file / directory APIs",
-		    test_instance_file_fd);
+		    test_file_fd);
 	CU_add_test(suite, "instance file descriptor",
 		    test_instance_file);
 	CU_add_test(suite, "systems and events APIs",
@@ -905,5 +1073,6 @@ void test_tracefs_lib(void)
 		    test_tracing_onoff);
 	CU_add_test(suite, "tracing options",
 		    test_tracing_options);
-
+	CU_add_test(suite, "custom system directory",
+		    test_custom_trace_dir);
 }
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-01-20 15:33 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-20 15:12 [PATCH v2 0/5] New libtracefs APIs for trace options and trace dir Tzvetomir Stoyanov (VMware)
2021-01-20 15:12 ` [PATCH v2 1/5] libtracefs: New APIs for trace options Tzvetomir Stoyanov (VMware)
2021-01-20 15:12 ` [PATCH v2 2/5] libtracefs: Unit tests for tracing options APIs Tzvetomir Stoyanov (VMware)
2021-01-20 15:12 ` [PATCH v2 3/5] libtracefs: Add information about top tracing directory in instance structure Tzvetomir Stoyanov (VMware)
2021-01-20 15:12 ` [PATCH v2 4/5] libtracefs: New APIs for getting existing trace instance Tzvetomir Stoyanov (VMware)
2021-01-20 15:12 ` [PATCH v2 5/5] libtracefs: Unit tests for working with non default tracing dir Tzvetomir Stoyanov (VMware)

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).