linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] New tracefs APIs
@ 2021-11-30  5:00 Tzvetomir Stoyanov (VMware)
  2021-11-30  5:00 ` [PATCH 1/4] libtracefs: Reuse logic for loading events inside the library Tzvetomir Stoyanov (VMware)
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-11-30  5:00 UTC (permalink / raw)
  To: rostedt, y.karadz; +Cc: linux-trace-devel

Two new library APIs are proposed, to provide a missing functionality:
 tracefs_dynevent_get_event()
 tracefs_event_apply_filter()

Tzvetomir Stoyanov (VMware) (4):
  libtracefs: Reuse logic for loading events inside the library
  libtracefs: New API for getting dynamic event
  libtracefs: Unit test for tracefs_dynevent_get_event()
  libtracefs: New API for applying filter on event.

 Documentation/libtracefs-dynevents.txt | 15 ++++++-
 Documentation/libtracefs-filter.txt    | 11 ++++-
 include/tracefs-local.h                |  3 ++
 include/tracefs.h                      |  5 +++
 src/tracefs-dynevents.c                | 29 +++++++++++++
 src/tracefs-events.c                   | 11 +++--
 src/tracefs-filter.c                   | 19 +++++++++
 utest/tracefs-utest.c                  | 58 +++++++++++++++++---------
 8 files changed, 125 insertions(+), 26 deletions(-)

-- 
2.33.1


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

* [PATCH 1/4] libtracefs: Reuse logic for loading events inside the library
  2021-11-30  5:00 [PATCH 0/4] New tracefs APIs Tzvetomir Stoyanov (VMware)
@ 2021-11-30  5:00 ` Tzvetomir Stoyanov (VMware)
  2021-11-30  5:00 ` [PATCH 2/4] libtracefs: New API for getting dynamic event Tzvetomir Stoyanov (VMware)
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-11-30  5:00 UTC (permalink / raw)
  To: rostedt, y.karadz; +Cc: linux-trace-devel

The logic for parsing and loading new tep events could be reused in
tracefs library. The function load_events() is exposed as internal API.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 include/tracefs-local.h |  3 +++
 src/tracefs-events.c    | 11 +++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/include/tracefs-local.h b/include/tracefs-local.h
index a59e806..0540956 100644
--- a/include/tracefs-local.h
+++ b/include/tracefs-local.h
@@ -112,4 +112,7 @@ dynevent_alloc(enum tracefs_dynevent_type type, const char *system,
 	       const char *event, const char *address, const char *format);
 int dynevent_get_count(unsigned int types, const char *system);
 
+int trace_load_events(struct tep_handle *tep,
+		      const char *tracing_dir, const char *system);
+
 #endif /* _TRACE_FS_LOCAL_H */
diff --git a/src/tracefs-events.c b/src/tracefs-events.c
index 4679926..e3962e5 100644
--- a/src/tracefs-events.c
+++ b/src/tracefs-events.c
@@ -688,8 +688,8 @@ char **tracefs_tracers(const char *tracing_dir)
 	return plugins;
 }
 
-static int load_events(struct tep_handle *tep,
-		       const char *tracing_dir, const char *system)
+__hidden int trace_load_events(struct tep_handle *tep,
+			       const char *tracing_dir, const char *system)
 {
 	int ret = 0, failure = 0;
 	char **events = NULL;
@@ -697,6 +697,9 @@ static int load_events(struct tep_handle *tep,
 	int len = 0;
 	int i;
 
+	if (!tracing_dir)
+		tracing_dir = tracefs_tracing_dir();
+
 	events = tracefs_system_events(tracing_dir, system);
 	if (!events)
 		return -ENOENT;
@@ -886,14 +889,14 @@ static int fill_local_events_system(const char *tracing_dir,
 	for (i = 0; systems[i]; i++) {
 		if (sys_names && !contains(systems[i], sys_names))
 			continue;
-		ret = load_events(tep, tracing_dir, systems[i]);
+		ret = trace_load_events(tep, tracing_dir, systems[i]);
 		if (ret && parsing_failures)
 			(*parsing_failures)++;
 	}
 
 	/* Include ftrace, as it is excluded for not having "enable" file */
 	if (!sys_names || contains("ftrace", sys_names))
-		load_events(tep, tracing_dir, "ftrace");
+		trace_load_events(tep, tracing_dir, "ftrace");
 
 	load_mappings(tracing_dir, tep);
 
-- 
2.33.1


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

* [PATCH 2/4] libtracefs: New API for getting dynamic event
  2021-11-30  5:00 [PATCH 0/4] New tracefs APIs Tzvetomir Stoyanov (VMware)
  2021-11-30  5:00 ` [PATCH 1/4] libtracefs: Reuse logic for loading events inside the library Tzvetomir Stoyanov (VMware)
@ 2021-11-30  5:00 ` Tzvetomir Stoyanov (VMware)
  2021-12-01 21:04   ` Steven Rostedt
  2021-11-30  5:00 ` [PATCH 3/4] libtracefs: Unit test for tracefs_dynevent_get_event() Tzvetomir Stoyanov (VMware)
  2021-11-30  5:00 ` [PATCH 4/4] libtracefs: New API for applying filter on event Tzvetomir Stoyanov (VMware)
  3 siblings, 1 reply; 8+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-11-30  5:00 UTC (permalink / raw)
  To: rostedt, y.karadz; +Cc: linux-trace-devel

A new API is proposed, to get tep event describing given dynamic event:
	tracefs_dynevent_get_event()
The API detects any newly created dynamic events, but does not detect
the deletion.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 Documentation/libtracefs-dynevents.txt | 14 +++++++++++--
 include/tracefs.h                      |  2 ++
 src/tracefs-dynevents.c                | 29 ++++++++++++++++++++++++++
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/Documentation/libtracefs-dynevents.txt b/Documentation/libtracefs-dynevents.txt
index a374651..7de06be 100644
--- a/Documentation/libtracefs-dynevents.txt
+++ b/Documentation/libtracefs-dynevents.txt
@@ -4,8 +4,8 @@ libtracefs(3)
 NAME
 ----
 tracefs_dynevent_create, tracefs_dynevent_destroy, tracefs_dynevent_destroy_all,
-tracefs_dynevent_free, tracefs_dynevent_list_free, tracefs_dynevent_get_all, tracefs_dynevent_info -
-Create, destroy, free and get dynamic events.
+tracefs_dynevent_free, tracefs_dynevent_list_free, tracefs_dynevent_get_all, tracefs_dynevent_info,
+tracefs_dynevent_get_event - Create, destroy, free and get dynamic events.
 
 SYNOPSIS
 --------
@@ -23,6 +23,7 @@ void *tracefs_dynevent_list_free*(struct tracefs_dynevent pass:[*]pass:[*]_event
 struct tracefs_dynevent pass:[*]*tracefs_dynevent_get*(enum tracefs_dynevent_type _type_, const char pass:[*]_system_, const char pass:[*]_event_);
 struct tracefs_dynevent pass:[*]pass:[*]*tracefs_dynevent_get_all*(unsigned int _types_, const char pass:[*]_system_);
 enum tracefs_dynevent_type *tracefs_dynevent_info*(struct tracefs_dynevent pass:[*]_dynevent_, char pass:[*]pass:[*]_system_, char pass:[*]pass:[*]_event_, char pass:[*]pass:[*]_prefix_, char pass:[*]pass:[*]_addr_, char pass:[*]pass:[*]_format_);
+struct tep_event pass:[*]*tracefs_dynevent_get_event*(struct tep_handle pass:[*]_tep_, struct tracefs_dynevent pass:[*]_dynevent_);
 --
 
 DESCRIPTION
@@ -68,6 +69,11 @@ if relevant for this event type. If _format_ is non NULL, it will hold the forma
 dynamic event. Note, that the content in _group_, _event_, _prefix_, _addr_, and _format_ must be
 freed with free(3) if they are set.
 
+The *tracefs_dynevent_get_event*() function returns tep event, describing the given dynamic event.
+If the dynamic event is newly created and not yet loaded in the @tep, the dynamic event system is
+rescanned for any new events. The returned pointer to tep event is controlled by @tep and must not
+be freed.
+
 RETURN VALUE
 ------------
 
@@ -88,6 +94,10 @@ in case of an error or in case there are no events in the system. That array mus
 on error. If _system_, _event_, _prefix_, _addr_, or _format_ are non NULL, they will contain
 allocated strings that must be freed by free(3).
 
+The *tracefs_dynevent_get_event*() function returns pointer to tep event or NULL in case of an error
+or if the requested dynamic event is missing. The returned pointer to tep event is controlled by
+@tep and must not be freed.
+
 ERRORS
 ------
 The following errors are for all the above calls:
diff --git a/include/tracefs.h b/include/tracefs.h
index 9662603..fbd7d31 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -262,6 +262,8 @@ tracefs_dynevent_get(enum tracefs_dynevent_type type, const char *system, const
 enum tracefs_dynevent_type
 tracefs_dynevent_info(struct tracefs_dynevent *dynevent, char **system,
 		      char **event, char **prefix, char **addr, char **format);
+struct tep_event *
+tracefs_dynevent_get_event(struct tep_handle *tep, struct tracefs_dynevent *dynevent);
 
 struct tracefs_dynevent *
 tracefs_eprobe_alloc(const char *system, const char *event,
diff --git a/src/tracefs-dynevents.c b/src/tracefs-dynevents.c
index ea07d13..2ff3c87 100644
--- a/src/tracefs-dynevents.c
+++ b/src/tracefs-dynevents.c
@@ -752,3 +752,32 @@ error:
 
 	return TRACEFS_DYNEVENT_UNKNOWN;
 }
+
+/**
+ * tracefs_dynevent_get_event - return tep event, representing the given dynamic event
+ * @tep: a handle to the trace event parser context, that holds the events
+ * @dynevent: a dynamic event context, describing given dynamic event.
+ *
+ * Returns pointer to tep event, describing the given dynamic event. The pointer
+ * is managed by @tep handle and must not be freed. In case of an error, or in case
+ * the requested dynamic event is missing in the @tep handler - NULL is returned.
+ */
+struct tep_event *
+tracefs_dynevent_get_event(struct tep_handle *tep, struct tracefs_dynevent *dynevent)
+{
+	struct tep_event *event;
+
+	if (!tep || !dynevent || !dynevent->event)
+		return NULL;
+
+	/* If the dynamic event is already loaded in the tep, return it */
+	event = tep_find_event_by_name(tep, dynevent->system, dynevent->event);
+	if (event)
+		return event;
+
+	/* Try to load any new events from the given system */
+	if (trace_load_events(tep, NULL, dynevent->system))
+		return NULL;
+
+	return tep_find_event_by_name(tep, dynevent->system, dynevent->event);
+}
-- 
2.33.1


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

* [PATCH 3/4] libtracefs: Unit test for tracefs_dynevent_get_event()
  2021-11-30  5:00 [PATCH 0/4] New tracefs APIs Tzvetomir Stoyanov (VMware)
  2021-11-30  5:00 ` [PATCH 1/4] libtracefs: Reuse logic for loading events inside the library Tzvetomir Stoyanov (VMware)
  2021-11-30  5:00 ` [PATCH 2/4] libtracefs: New API for getting dynamic event Tzvetomir Stoyanov (VMware)
@ 2021-11-30  5:00 ` Tzvetomir Stoyanov (VMware)
  2021-11-30  5:00 ` [PATCH 4/4] libtracefs: New API for applying filter on event Tzvetomir Stoyanov (VMware)
  3 siblings, 0 replies; 8+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-11-30  5:00 UTC (permalink / raw)
  To: rostedt, y.karadz; +Cc: linux-trace-devel

Unit tests for dynamic events are extended to test the newly introduced
tracefs_dynevent_get_event() API.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 Documentation/libtracefs-dynevents.txt |  5 ++-
 utest/tracefs-utest.c                  | 58 +++++++++++++++++---------
 2 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/Documentation/libtracefs-dynevents.txt b/Documentation/libtracefs-dynevents.txt
index 7de06be..bd18f5b 100644
--- a/Documentation/libtracefs-dynevents.txt
+++ b/Documentation/libtracefs-dynevents.txt
@@ -71,8 +71,9 @@ freed with free(3) if they are set.
 
 The *tracefs_dynevent_get_event*() function returns tep event, describing the given dynamic event.
 If the dynamic event is newly created and not yet loaded in the @tep, the dynamic event system is
-rescanned for any new events. The returned pointer to tep event is controlled by @tep and must not
-be freed.
+rescanned for any new events. If the dynamic event is deleted from the system, any subsequent calls
+to *tracefs_dynevent_get_event*() may return a tep event, as the deletion is not detected by the API.
+The returned pointer to tep event is controlled by @tep and must not be freed.
 
 RETURN VALUE
 ------------
diff --git a/utest/tracefs-utest.c b/utest/tracefs-utest.c
index 3a01f38..c555b06 100644
--- a/utest/tracefs-utest.c
+++ b/utest/tracefs-utest.c
@@ -567,9 +567,10 @@ struct probe_test {
 
 static bool check_probes(struct probe_test *probes, int count,
 			 struct tracefs_dynevent **devents, bool in_system,
-			 struct tracefs_instance *instance)
+			 struct tracefs_instance *instance, struct tep_handle *tep)
 {
 	enum tracefs_dynevent_type type;
+	struct tep_event *tevent;
 	char *ename;
 	char *address;
 	char *event;
@@ -615,6 +616,15 @@ static bool check_probes(struct probe_test *probes, int count,
 				CU_TEST(ret != 0);
 			}
 
+			if (in_system) {
+				tevent =  tracefs_dynevent_get_event(tep, devents[i]);
+				CU_TEST(tevent != NULL);
+				if (tevent) {
+					CU_TEST(strcmp(tevent->name, event) == 0);
+					CU_TEST(strcmp(tevent->system, system) == 0);
+				}
+			}
+
 			found++;
 			break;
 		}
@@ -649,10 +659,14 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
 	struct tracefs_dynevent **dkretprobe;
 	struct tracefs_dynevent **dkprobe;
 	struct tracefs_dynevent **devents;
+	struct tep_handle *tep;
 	char *tmp;
 	int ret;
 	int i;
 
+	tep = tep_alloc();
+	CU_TEST(tep != NULL);
+
 	dkprobe = calloc(kprobe_count + 1, sizeof(*dkprobe));
 	dkretprobe = calloc(kretprobe_count + 1, sizeof(*dkretprobe));
 
@@ -676,7 +690,7 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
 	}
 	dkprobe[i] = NULL;
 	get_dynevents_check(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, 0);
-	CU_TEST(check_probes(ktests, kprobe_count, dkprobe, false, instance));
+	CU_TEST(check_probes(ktests, kprobe_count, dkprobe, false, instance, tep));
 
 	for (i = 0; i < kretprobe_count; i++) {
 		dkretprobe[i] = tracefs_kretprobe_alloc(kretests[i].system, kretests[i].event,
@@ -685,15 +699,15 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
 	}
 	dkretprobe[i] = NULL;
 	get_dynevents_check(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, 0);
-	CU_TEST(check_probes(kretests, kretprobe_count, dkretprobe, false, instance));
+	CU_TEST(check_probes(kretests, kretprobe_count, dkretprobe, false, instance, tep));
 
 	for (i = 0; i < kprobe_count; i++) {
 		CU_TEST(tracefs_dynevent_create(dkprobe[i]) == 0);
 	}
 	devents = get_dynevents_check(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE,
 				    kprobe_count);
-	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance));
-	CU_TEST(check_probes(kretests, kretprobe_count, dkretprobe, false, instance));
+	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance, tep));
+	CU_TEST(check_probes(kretests, kretprobe_count, dkretprobe, false, instance, tep));
 	tracefs_dynevent_list_free(devents);
 	devents = NULL;
 
@@ -702,8 +716,8 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
 	}
 	devents = get_dynevents_check(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE,
 				    kprobe_count + kretprobe_count);
-	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance));
-	CU_TEST(check_probes(kretests, kretprobe_count, devents, true, instance));
+	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance, tep));
+	CU_TEST(check_probes(kretests, kretprobe_count, devents, true, instance, tep));
 	tracefs_dynevent_list_free(devents);
 	devents = NULL;
 
@@ -712,8 +726,8 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
 	}
 	devents = get_dynevents_check(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE,
 				    kprobe_count);
-	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance));
-	CU_TEST(check_probes(kretests, kretprobe_count, dkretprobe, false, instance));
+	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance, tep));
+	CU_TEST(check_probes(kretests, kretprobe_count, dkretprobe, false, instance, tep));
 	tracefs_dynevent_list_free(devents);
 	devents = NULL;
 
@@ -721,8 +735,8 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
 		CU_TEST(tracefs_dynevent_destroy(dkprobe[i], false) == 0);
 	}
 	get_dynevents_check(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, 0);
-	CU_TEST(check_probes(ktests, kprobe_count, dkprobe, false, instance));
-	CU_TEST(check_probes(kretests, kretprobe_count, dkretprobe, false, instance));
+	CU_TEST(check_probes(ktests, kprobe_count, dkprobe, false, instance, tep));
+	CU_TEST(check_probes(kretests, kretprobe_count, dkretprobe, false, instance, tep));
 	tracefs_dynevent_list_free(devents);
 	devents = NULL;
 
@@ -743,7 +757,7 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
 	}
 
 	devents = get_dynevents_check(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, kprobe_count);
-	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance));
+	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance, tep));
 	tracefs_dynevent_list_free(devents);
 	devents = NULL;
 
@@ -754,19 +768,19 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
 	}
 
 	devents = get_dynevents_check(TRACEFS_DYNEVENT_KPROBE, kprobe_count);
-	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance));
+	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance, tep));
 	tracefs_dynevent_list_free(devents);
 	devents = NULL;
 
 	devents = get_dynevents_check(TRACEFS_DYNEVENT_KRETPROBE, kretprobe_count);
-	CU_TEST(check_probes(kretests, kretprobe_count, devents, true, instance));
+	CU_TEST(check_probes(kretests, kretprobe_count, devents, true, instance, tep));
 	tracefs_dynevent_list_free(devents);
 	devents = NULL;
 
 	devents = get_dynevents_check(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE,
 				    kprobe_count + kretprobe_count);
-	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance));
-	CU_TEST(check_probes(kretests, kretprobe_count, devents, true, instance));
+	CU_TEST(check_probes(ktests, kprobe_count, devents, true, instance, tep));
+	CU_TEST(check_probes(kretests, kretprobe_count, devents, true, instance, tep));
 	tracefs_dynevent_list_free(devents);
 	devents = NULL;
 
@@ -775,6 +789,7 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
 	get_dynevents_check(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, 0);
 	free(dkretprobe);
 	free(dkprobe);
+	tep_free(tep);
 }
 
 static void test_kprobes(void)
@@ -793,11 +808,15 @@ static void test_eprobes_instance(struct tracefs_instance *instance)
 	int count = sizeof(etests) / sizeof((etests)[0]);
 	struct tracefs_dynevent **deprobes;
 	struct tracefs_dynevent **devents;
+	struct tep_handle *tep;
 	char *tsys, *tevent;
 	char *tmp, *sav;
 	int ret;
 	int i;
 
+	tep = tep_alloc();
+	CU_TEST(tep != NULL);
+
 	deprobes = calloc(count + 1, sizeof(*deprobes));
 
 	/* Invalid parameters */
@@ -821,14 +840,14 @@ static void test_eprobes_instance(struct tracefs_instance *instance)
 	deprobes[i] = NULL;
 
 	get_dynevents_check(TRACEFS_DYNEVENT_EPROBE, 0);
-	CU_TEST(check_probes(etests, count, deprobes, false, instance));
+	CU_TEST(check_probes(etests, count, deprobes, false, instance, tep));
 
 	for (i = 0; i < count; i++) {
 		CU_TEST(tracefs_dynevent_create(deprobes[i]) == 0);
 	}
 
 	devents = get_dynevents_check(TRACEFS_DYNEVENT_EPROBE, count);
-	CU_TEST(check_probes(etests, count, devents, true, instance));
+	CU_TEST(check_probes(etests, count, devents, true, instance, tep));
 	tracefs_dynevent_list_free(devents);
 	devents = NULL;
 
@@ -836,12 +855,13 @@ static void test_eprobes_instance(struct tracefs_instance *instance)
 		CU_TEST(tracefs_dynevent_destroy(deprobes[i], false) == 0);
 	}
 	get_dynevents_check(TRACEFS_DYNEVENT_EPROBE, 0);
-	CU_TEST(check_probes(etests, count, deprobes, false, instance));
+	CU_TEST(check_probes(etests, count, deprobes, false, instance, tep));
 
 	for (i = 0; i < count; i++)
 		tracefs_dynevent_free(deprobes[i]);
 
 	free(deprobes);
+	tep_free(tep);
 }
 
 static void test_eprobes(void)
-- 
2.33.1


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

* [PATCH 4/4] libtracefs: New API for applying filter on event.
  2021-11-30  5:00 [PATCH 0/4] New tracefs APIs Tzvetomir Stoyanov (VMware)
                   ` (2 preceding siblings ...)
  2021-11-30  5:00 ` [PATCH 3/4] libtracefs: Unit test for tracefs_dynevent_get_event() Tzvetomir Stoyanov (VMware)
@ 2021-11-30  5:00 ` Tzvetomir Stoyanov (VMware)
  2021-12-01 19:55   ` Steven Rostedt
  3 siblings, 1 reply; 8+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2021-11-30  5:00 UTC (permalink / raw)
  To: rostedt, y.karadz; +Cc: linux-trace-devel

There is no API for applying a filter string on event. Existing APIs
only constructs and verifies the filter string. Even though the actual
applying is just writing into the event's filter file, it is good to
have a dedicated API for that:
	tracefs_event_apply_filter()

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 Documentation/libtracefs-filter.txt | 11 ++++++++++-
 include/tracefs.h                   |  3 +++
 src/tracefs-filter.c                | 19 +++++++++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/Documentation/libtracefs-filter.txt b/Documentation/libtracefs-filter.txt
index 7e167bc..7532c96 100644
--- a/Documentation/libtracefs-filter.txt
+++ b/Documentation/libtracefs-filter.txt
@@ -3,7 +3,8 @@ libtracefs(3)
 
 NAME
 ----
-tracefs_event_append_filter, tracefs_event_verify_filter - Add and verify event filters
+tracefs_event_append_filter, tracefs_event_verify_filter tracefs_event_apply_filter -
+Add, verify and apply event filters
 
 SYNOPSIS
 --------
@@ -15,6 +16,7 @@ int tracefs_event_append_filter(struct tep_event pass:[*]event, char pass:[**] f
 				 struct tracefs_filter type, const char pass:[*]field,
 				 enum tracefs_synth_compare compare, const char pass:[*]val);
 int tracefs_event_verify_filter(struct tep_event pass:[*]event, const char pass:[*]filter, char pass:[**]err);
+int tracefs_event_apply_filter(struct tracefs_instance pass:[*]instance, struct tep_event pass:[*]event, const char pass:[*]filter);
 
 --
 
@@ -66,6 +68,8 @@ error in the syntax, and _err_ is not NULL, then it will be allocated with an
 error message stating what was found wrong with the filter. _err_ must be freed
 with *free*().
 
+*tracefs_event_apply_filter*() applies given _filter_ string on _event_ in given _instance_.
+
 RETURN VALUE
 ------------
 *tracefs_event_append_filter*() returns 0 on success and -1 on error.
@@ -75,6 +79,8 @@ is an error, and _errno_ is not *ENOMEM*, then _err_ is allocated and will
 contain a string describing what was found wrong with _filter_. _err_ must be
 freed with *free*().
 
+*tracefs_event_apply_filter*() returns 0 on success and -1 on error.
+
 EXAMPLE
 -------
 [source,c]
@@ -269,6 +275,9 @@ int main (int argc, char **argv)
 		}
 	}
 
+	if (tracefs_event_apply_filter(NULL, event, new_filter))
+		fprintf(stderr, "Failed to apply filter on event");
+
 	tep_free(tep);
 
 	printf("Created new filter: '%s'\n", new_filter);
diff --git a/include/tracefs.h b/include/tracefs.h
index fbd7d31..8ac9694 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -475,6 +475,9 @@ int tracefs_event_append_filter(struct tep_event *event, char **filter,
 				const char *val);
 int tracefs_event_verify_filter(struct tep_event *event, const char *filter,
 				char **err);
+int tracefs_event_apply_filter(struct tracefs_instance *instance,
+			       struct tep_event *event, const char *filter);
+
 
 #define TRACEFS_TIMESTAMP "common_timestamp"
 #define TRACEFS_TIMESTAMP_USECS "common_timestamp.usecs"
diff --git a/src/tracefs-filter.c b/src/tracefs-filter.c
index def8f68..43683d0 100644
--- a/src/tracefs-filter.c
+++ b/src/tracefs-filter.c
@@ -745,3 +745,22 @@ int tracefs_event_verify_filter(struct tep_event *event, const char *filter,
 	free(str);
 	return 0;
 }
+
+/**
+ * tracefs_event_apply_filter - apply given filter on event in given instance
+ * @instance: The instance in which the filter will be applied (NULL for toplevel).
+ * @event: The event to apply the filter on.
+ * @filter: The filter to apply.
+ *
+ * Apply the @filter to given @event in givem @instance. The @filter string
+ * should be created with tracefs_event_append_filter().
+ *
+ * Returns 0 on succes and -1 on error.
+ */
+int tracefs_event_apply_filter(struct tracefs_instance *instance,
+			       struct tep_event *event, const char *filter)
+{
+	return tracefs_event_file_append(instance, event->system, event->name,
+					 "filter", filter);
+}
+
-- 
2.33.1


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

* Re: [PATCH 4/4] libtracefs: New API for applying filter on event.
  2021-11-30  5:00 ` [PATCH 4/4] libtracefs: New API for applying filter on event Tzvetomir Stoyanov (VMware)
@ 2021-12-01 19:55   ` Steven Rostedt
  0 siblings, 0 replies; 8+ messages in thread
From: Steven Rostedt @ 2021-12-01 19:55 UTC (permalink / raw)
  To: Tzvetomir Stoyanov (VMware); +Cc: y.karadz, linux-trace-devel


Note, the subject should not have a period.

On Tue, 30 Nov 2021 07:00:57 +0200
"Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com> wrote:

> There is no API for applying a filter string on event. Existing APIs

"on an event."

> only constructs and verifies the filter string. Even though the actual

  "only construct and verify"

> applying is just writing into the event's filter file, it is good to
> have a dedicated API for that:

[ add empty line here ]

> 	tracefs_event_apply_filter()
> 
> Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
> ---
>  Documentation/libtracefs-filter.txt | 11 ++++++++++-
>  include/tracefs.h                   |  3 +++
>  src/tracefs-filter.c                | 19 +++++++++++++++++++
>  3 files changed, 32 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/libtracefs-filter.txt b/Documentation/libtracefs-filter.txt
> index 7e167bc..7532c96 100644
> --- a/Documentation/libtracefs-filter.txt
> +++ b/Documentation/libtracefs-filter.txt
> @@ -3,7 +3,8 @@ libtracefs(3)
>  
>  NAME
>  ----
> -tracefs_event_append_filter, tracefs_event_verify_filter - Add and verify event filters
> +tracefs_event_append_filter, tracefs_event_verify_filter tracefs_event_apply_filter -

Missing comma (and you also need to rebase with the updates).


> +Add, verify and apply event filters
>  
>  SYNOPSIS
>  --------
> @@ -15,6 +16,7 @@ int tracefs_event_append_filter(struct tep_event pass:[*]event, char pass:[**] f
>  				 struct tracefs_filter type, const char pass:[*]field,
>  				 enum tracefs_synth_compare compare, const char pass:[*]val);
>  int tracefs_event_verify_filter(struct tep_event pass:[*]event, const char pass:[*]filter, char pass:[**]err);

I renamed the above, because it doesn't really affect the event.

> +int tracefs_event_apply_filter(struct tracefs_instance pass:[*]instance, struct tep_event pass:[*]event, const char pass:[*]filter);

But you can keep this name, as it makes sense to call this
"tracefs_event_.."

>  
>  --
>  
> @@ -66,6 +68,8 @@ error in the syntax, and _err_ is not NULL, then it will be allocated with an
>  error message stating what was found wrong with the filter. _err_ must be freed
>  with *free*().
>  
> +*tracefs_event_apply_filter*() applies given _filter_ string on _event_ in given _instance_.
> +
>  RETURN VALUE
>  ------------
>  *tracefs_event_append_filter*() returns 0 on success and -1 on error.
> @@ -75,6 +79,8 @@ is an error, and _errno_ is not *ENOMEM*, then _err_ is allocated and will
>  contain a string describing what was found wrong with _filter_. _err_ must be
>  freed with *free*().
>  
> +*tracefs_event_apply_filter*() returns 0 on success and -1 on error.
> +
>  EXAMPLE
>  -------
>  [source,c]
> @@ -269,6 +275,9 @@ int main (int argc, char **argv)
>  		}
>  	}
>  
> +	if (tracefs_event_apply_filter(NULL, event, new_filter))
> +		fprintf(stderr, "Failed to apply filter on event");
> +
>  	tep_free(tep);
>  
>  	printf("Created new filter: '%s'\n", new_filter);
> diff --git a/include/tracefs.h b/include/tracefs.h
> index fbd7d31..8ac9694 100644
> --- a/include/tracefs.h
> +++ b/include/tracefs.h
> @@ -475,6 +475,9 @@ int tracefs_event_append_filter(struct tep_event *event, char **filter,
>  				const char *val);
>  int tracefs_event_verify_filter(struct tep_event *event, const char *filter,
>  				char **err);
> +int tracefs_event_apply_filter(struct tracefs_instance *instance,
> +			       struct tep_event *event, const char *filter);
> +
>  
>  #define TRACEFS_TIMESTAMP "common_timestamp"
>  #define TRACEFS_TIMESTAMP_USECS "common_timestamp.usecs"
> diff --git a/src/tracefs-filter.c b/src/tracefs-filter.c
> index def8f68..43683d0 100644
> --- a/src/tracefs-filter.c
> +++ b/src/tracefs-filter.c
> @@ -745,3 +745,22 @@ int tracefs_event_verify_filter(struct tep_event *event, const char *filter,
>  	free(str);
>  	return 0;
>  }
> +
> +/**
> + * tracefs_event_apply_filter - apply given filter on event in given instance
> + * @instance: The instance in which the filter will be applied (NULL for toplevel).
> + * @event: The event to apply the filter on.
> + * @filter: The filter to apply.
> + *
> + * Apply the @filter to given @event in givem @instance. The @filter string
> + * should be created with tracefs_event_append_filter().

The name of the function has been renamed.

> + *
> + * Returns 0 on succes and -1 on error.
> + */
> +int tracefs_event_apply_filter(struct tracefs_instance *instance,
> +			       struct tep_event *event, const char *filter)
> +{
> +	return tracefs_event_file_append(instance, event->system, event->name,
> +					 "filter", filter);

I think we want this to be tracefs_event_file_write(), as it should replace
the filter, not add on to it.

> +}
> +

Note, I moved the old deprecated names at the end of the file. Make sure
they stay at the end. In other words, this goes before them.

-- Steve

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

* Re: [PATCH 2/4] libtracefs: New API for getting dynamic event
  2021-11-30  5:00 ` [PATCH 2/4] libtracefs: New API for getting dynamic event Tzvetomir Stoyanov (VMware)
@ 2021-12-01 21:04   ` Steven Rostedt
  2021-12-02  5:05     ` Tzvetomir Stoyanov
  0 siblings, 1 reply; 8+ messages in thread
From: Steven Rostedt @ 2021-12-01 21:04 UTC (permalink / raw)
  To: Tzvetomir Stoyanov (VMware); +Cc: y.karadz, linux-trace-devel

On Tue, 30 Nov 2021 07:00:55 +0200
"Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com> wrote:

> A new API is proposed, to get tep event describing given dynamic event:
[blank line]
> 	tracefs_dynevent_get_event()
[blank line]
> The API detects any newly created dynamic events, but does not detect
> the deletion.
> 
> Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
> ---
>  Documentation/libtracefs-dynevents.txt | 14 +++++++++++--
>  include/tracefs.h                      |  2 ++
>  src/tracefs-dynevents.c                | 29 ++++++++++++++++++++++++++
>  3 files changed, 43 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/libtracefs-dynevents.txt b/Documentation/libtracefs-dynevents.txt
> index a374651..7de06be 100644
> --- a/Documentation/libtracefs-dynevents.txt
> +++ b/Documentation/libtracefs-dynevents.txt
> @@ -4,8 +4,8 @@ libtracefs(3)
>  NAME
>  ----
>  tracefs_dynevent_create, tracefs_dynevent_destroy, tracefs_dynevent_destroy_all,
> -tracefs_dynevent_free, tracefs_dynevent_list_free, tracefs_dynevent_get_all, tracefs_dynevent_info -
> -Create, destroy, free and get dynamic events.
> +tracefs_dynevent_free, tracefs_dynevent_list_free, tracefs_dynevent_get_all, tracefs_dynevent_info,
> +tracefs_dynevent_get_event - Create, destroy, free and get dynamic events.
>  
>  SYNOPSIS
>  --------
> @@ -23,6 +23,7 @@ void *tracefs_dynevent_list_free*(struct tracefs_dynevent pass:[*]pass:[*]_event
>  struct tracefs_dynevent pass:[*]*tracefs_dynevent_get*(enum tracefs_dynevent_type _type_, const char pass:[*]_system_, const char pass:[*]_event_);
>  struct tracefs_dynevent pass:[*]pass:[*]*tracefs_dynevent_get_all*(unsigned int _types_, const char pass:[*]_system_);
>  enum tracefs_dynevent_type *tracefs_dynevent_info*(struct tracefs_dynevent pass:[*]_dynevent_, char pass:[*]pass:[*]_system_, char pass:[*]pass:[*]_event_, char pass:[*]pass:[*]_prefix_, char pass:[*]pass:[*]_addr_, char pass:[*]pass:[*]_format_);
> +struct tep_event pass:[*]*tracefs_dynevent_get_event*(struct tep_handle pass:[*]_tep_, struct tracefs_dynevent pass:[*]_dynevent_);
>  --
>  
>  DESCRIPTION
> @@ -68,6 +69,11 @@ if relevant for this event type. If _format_ is non NULL, it will hold the forma
>  dynamic event. Note, that the content in _group_, _event_, _prefix_, _addr_, and _format_ must be
>  freed with free(3) if they are set.
>  
> +The *tracefs_dynevent_get_event*() function returns tep event, describing the given dynamic event.

					  "returns a tep event"

> +If the dynamic event is newly created and not yet loaded in the @tep, the dynamic event system is

            "loaded in @tep"

> +rescanned for any new events. The returned pointer to tep event is controlled by @tep and must not
> +be freed.


> +
>  RETURN VALUE
>  ------------
>  
> @@ -88,6 +94,10 @@ in case of an error or in case there are no events in the system. That array mus
>  on error. If _system_, _event_, _prefix_, _addr_, or _format_ are non NULL, they will contain
>  allocated strings that must be freed by free(3).
>  
> +The *tracefs_dynevent_get_event*() function returns pointer to tep event or NULL in case of an error

  "returns a pointer to a tep event'

> +or if the requested dynamic event is missing. The returned pointer to tep event is controlled by
> +@tep and must not be freed.
> +
>  ERRORS
>  ------
>  The following errors are for all the above calls:
> diff --git a/include/tracefs.h b/include/tracefs.h
> index 9662603..fbd7d31 100644
> --- a/include/tracefs.h
> +++ b/include/tracefs.h
> @@ -262,6 +262,8 @@ tracefs_dynevent_get(enum tracefs_dynevent_type type, const char *system, const
>  enum tracefs_dynevent_type
>  tracefs_dynevent_info(struct tracefs_dynevent *dynevent, char **system,
>  		      char **event, char **prefix, char **addr, char **format);
> +struct tep_event *
> +tracefs_dynevent_get_event(struct tep_handle *tep, struct tracefs_dynevent *dynevent);
>  
>  struct tracefs_dynevent *
>  tracefs_eprobe_alloc(const char *system, const char *event,
> diff --git a/src/tracefs-dynevents.c b/src/tracefs-dynevents.c
> index ea07d13..2ff3c87 100644
> --- a/src/tracefs-dynevents.c
> +++ b/src/tracefs-dynevents.c
> @@ -752,3 +752,32 @@ error:
>  
>  	return TRACEFS_DYNEVENT_UNKNOWN;
>  }
> +
> +/**
> + * tracefs_dynevent_get_event - return tep event, representing the given dynamic event

  remove the comma.

> + * @tep: a handle to the trace event parser context, that holds the events

  remove the comma.

> + * @dynevent: a dynamic event context, describing given dynamic event.

  remove the comma ;-)

> + *
> + * Returns pointer to tep event, describing the given dynamic event. The pointer

 "Returns a pointer to a tep event describing the given dynamic event".

> + * is managed by @tep handle and must not be freed. In case of an error, or in case

  "by the @tep handle"

> + * the requested dynamic event is missing in the @tep handler - NULL is returned.
> + */
> +struct tep_event *
> +tracefs_dynevent_get_event(struct tep_handle *tep, struct tracefs_dynevent *dynevent)
> +{
> +	struct tep_event *event;
> +
> +	if (!tep || !dynevent || !dynevent->event)
> +		return NULL;
> +
> +	/* If the dynamic event is already loaded in the tep, return it */
> +	event = tep_find_event_by_name(tep, dynevent->system, dynevent->event);
> +	if (event)
> +		return event;
> +
> +	/* Try to load any new events from the given system */
> +	if (trace_load_events(tep, NULL, dynevent->system))

Does this refresh, or does just append?

That is, if there are already dynamic events, wouldn't this re-add the
existing events that are already there?

Perhaps we need an interface in libtraceevent that rescans, and checks for
duplicates.

-- Steve

> +		return NULL;
> +
> +	return tep_find_event_by_name(tep, dynevent->system, dynevent->event);
> +}


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

* Re: [PATCH 2/4] libtracefs: New API for getting dynamic event
  2021-12-01 21:04   ` Steven Rostedt
@ 2021-12-02  5:05     ` Tzvetomir Stoyanov
  0 siblings, 0 replies; 8+ messages in thread
From: Tzvetomir Stoyanov @ 2021-12-02  5:05 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Yordan Karadzhov, Linux Trace Devel

On Wed, Dec 1, 2021 at 11:04 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
[ ... ]
>
> > + * the requested dynamic event is missing in the @tep handler - NULL is returned.
> > + */
> > +struct tep_event *
> > +tracefs_dynevent_get_event(struct tep_handle *tep, struct tracefs_dynevent *dynevent)
> > +{
> > +     struct tep_event *event;
> > +
> > +     if (!tep || !dynevent || !dynevent->event)
> > +             return NULL;
> > +
> > +     /* If the dynamic event is already loaded in the tep, return it */
> > +     event = tep_find_event_by_name(tep, dynevent->system, dynevent->event);
> > +     if (event)
> > +             return event;
> > +
> > +     /* Try to load any new events from the given system */
> > +     if (trace_load_events(tep, NULL, dynevent->system))
>
> Does this refresh, or does just append?
>

This calls tep_parse_event() for all events in the given system, so it
only appends.

> That is, if there are already dynamic events, wouldn't this re-add the
> existing events that are already there?

I just realized that there is a bug, there will be duplicates.

>
> Perhaps we need an interface in libtraceevent that rescans, and checks for
> duplicates.

Yes, that logic should be in libtraceevent, there should be new API.

>


> -- Steve
>
> > +             return NULL;
> > +
> > +     return tep_find_event_by_name(tep, dynevent->system, dynevent->event);
> > +}
>


-- 
Tzvetomir (Ceco) Stoyanov
VMware Open Source Technology Center

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

end of thread, other threads:[~2021-12-02  5:05 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-11-30  5:00 [PATCH 0/4] New tracefs APIs Tzvetomir Stoyanov (VMware)
2021-11-30  5:00 ` [PATCH 1/4] libtracefs: Reuse logic for loading events inside the library Tzvetomir Stoyanov (VMware)
2021-11-30  5:00 ` [PATCH 2/4] libtracefs: New API for getting dynamic event Tzvetomir Stoyanov (VMware)
2021-12-01 21:04   ` Steven Rostedt
2021-12-02  5:05     ` Tzvetomir Stoyanov
2021-11-30  5:00 ` [PATCH 3/4] libtracefs: Unit test for tracefs_dynevent_get_event() Tzvetomir Stoyanov (VMware)
2021-11-30  5:00 ` [PATCH 4/4] libtracefs: New API for applying filter on event Tzvetomir Stoyanov (VMware)
2021-12-01 19:55   ` Steven Rostedt

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