All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] trace-cruncher: Add support for event probes
@ 2022-01-24 15:20 Tzvetomir Stoyanov (VMware)
  2022-01-25 13:28 ` Yordan Karadzhov
  0 siblings, 1 reply; 2+ messages in thread
From: Tzvetomir Stoyanov (VMware) @ 2022-01-24 15:20 UTC (permalink / raw)
  To: y.karadz; +Cc: linux-trace-devel

Event probe (eprobe) is a new type of ftrace dynamic events, introduced
in the Linux kernel 5.15 version. It is useful to have support for it in
trace-cruncher, as it allows more flexibility when printing event's
data.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 src/ftracepy-utils.c                          | 34 ++++++++++++++++
 src/ftracepy-utils.h                          |  3 ++
 src/ftracepy.c                                |  5 +++
 .../tests/1_unit/test_01_ftracepy_unit.py     | 39 +++++++++++++++++++
 4 files changed, 81 insertions(+)

diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c
index cecb180..28ed7b9 100644
--- a/src/ftracepy-utils.c
+++ b/src/ftracepy-utils.c
@@ -2064,6 +2064,40 @@ PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args,
 	return PyDynevent_New(kprobe);
 }
 
+PyObject *PyFtrace_register_eprobe(PyObject *self, PyObject *args,
+						   PyObject *kwargs)
+{
+	static char *kwlist[] = {"event", "target_system", "target_event", "fetchargs", NULL};
+	const char *event, *target_system, *target_event, *fetchargs;
+	struct tracefs_dynevent *eprobe;
+
+	if (!PyArg_ParseTupleAndKeywords(args,
+					 kwargs,
+					 "ssss",
+					 kwlist,
+					 &event,
+					 &target_system,
+					 &target_event,
+					 &fetchargs)) {
+		return NULL;
+	}
+
+	eprobe = tracefs_eprobe_alloc(TC_SYS, event, target_system, target_event, fetchargs);
+	if (!eprobe) {
+		MEM_ERROR;
+		return NULL;
+	}
+
+	if (tracefs_dynevent_create(eprobe) < 0) {
+		TfsError_fmt(NULL, "Failed to create eprobe '%s'", event);
+		tracefs_dynevent_free(eprobe);
+		return NULL;
+	}
+
+	return PyDynevent_New(eprobe);
+}
+
+
 PyObject *PyDynevent_set_filter(PyDynevent *self, PyObject *args,
 						  PyObject *kwargs)
 {
diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h
index fc5016c..1030a50 100644
--- a/src/ftracepy-utils.h
+++ b/src/ftracepy-utils.h
@@ -207,6 +207,9 @@ PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args,
 PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args,
 						      PyObject *kwargs);
 
+PyObject *PyFtrace_register_eprobe(PyObject *self, PyObject *args,
+						   PyObject *kwargs);
+
 PyObject *PyFtrace_hist(PyObject *self, PyObject *args,
 					PyObject *kwargs);
 
diff --git a/src/ftracepy.c b/src/ftracepy.c
index f59bd4c..50ee4d3 100644
--- a/src/ftracepy.c
+++ b/src/ftracepy.c
@@ -377,6 +377,11 @@ static PyMethodDef ftracepy_methods[] = {
 	 METH_VARARGS | METH_KEYWORDS,
 	 "Define a kretprobe."
 	},
+	{"register_eprobe",
+	 (PyCFunction) PyFtrace_register_eprobe,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Define an eprobe."
+	},
 	{"hist",
 	 (PyCFunction) PyFtrace_hist,
 	 METH_VARARGS | METH_KEYWORDS,
diff --git a/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py b/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py
index 51970d3..12b58a0 100644
--- a/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py
+++ b/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py
@@ -457,6 +457,45 @@ class KprobeTestCase(unittest.TestCase):
         ret = kp1.is_enabled(instance=inst)
         self.assertEqual(ret, '0')
 
+class EprobeTestCase(unittest.TestCase):
+    def test_register_eprobe(self):
+        evt1 = 'sopen_in'
+        evt1_tsys = 'syscalls'
+        evt1_tevent = 'sys_enter_openat'
+        evt1_args = 'file=+0($filename):ustring'
+        evt2 = 'sopen_out'
+        evt2_tsys = 'syscalls'
+        evt2_tevent = 'sys_exit_openat'
+        evt2_args = 'res=$ret:u64'
+
+        ep1 = ft.register_eprobe(event=evt1, target_system=evt1_tsys, target_event=evt1_tevent,
+                                 fetchargs=evt1_args)
+        self.assertEqual(evt1, ep1.event())
+        self.assertEqual("{}.{}".format(evt1_tsys, evt1_tevent), ep1.address())
+        self.assertEqual(evt1_args, ep1.probe())
+
+        ep2 = ft.register_eprobe(event=evt2, target_system=evt2_tsys, target_event=evt2_tevent,
+                                 fetchargs=evt2_args)
+        self.assertEqual(evt2, ep2.event())
+        self.assertEqual("{}.{}".format(evt2_tsys, evt2_tevent), ep2.address())
+        self.assertEqual(evt2_args, ep2.probe())
+
+    def test_enable_eprobe(self):
+        evt1 = 'sopen_out'
+        evt1_tsys = 'syscalls'
+        evt1_tevent = 'sys_exit_openat'
+        evt1_args = 'res=$ret:u64'
+
+        ep1 = ft.register_eprobe(event=evt1, target_system=evt1_tsys, target_event=evt1_tevent,
+                                 fetchargs=evt1_args)
+        inst = ft.create_instance(instance_name)
+        ep1.enable(instance=inst)
+        ret = ep1.is_enabled(instance=inst)
+        self.assertEqual(ret, '1')
+
+        ep1.disable(instance=inst)
+        ret = ep1.is_enabled(instance=inst)
+        self.assertEqual(ret, '0')
 
 class TracingOnTestCase(unittest.TestCase):
     def test_ON_OF(self):
-- 
2.34.1


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

* Re: [PATCH] trace-cruncher: Add support for event probes
  2022-01-24 15:20 [PATCH] trace-cruncher: Add support for event probes Tzvetomir Stoyanov (VMware)
@ 2022-01-25 13:28 ` Yordan Karadzhov
  0 siblings, 0 replies; 2+ messages in thread
From: Yordan Karadzhov @ 2022-01-25 13:28 UTC (permalink / raw)
  To: Tzvetomir Stoyanov (VMware); +Cc: linux-trace-devel



On 24.01.22 г. 17:20 ч., Tzvetomir Stoyanov (VMware) wrote:
> Event probe (eprobe) is a new type of ftrace dynamic events, introduced
> in the Linux kernel 5.15 version. It is useful to have support for it in
> trace-cruncher, as it allows more flexibility when printing event's
> data.
> 
> Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
> ---
>   src/ftracepy-utils.c                          | 34 ++++++++++++++++
>   src/ftracepy-utils.h                          |  3 ++
>   src/ftracepy.c                                |  5 +++
>   .../tests/1_unit/test_01_ftracepy_unit.py     | 39 +++++++++++++++++++
>   4 files changed, 81 insertions(+)
> 
> diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c
> index cecb180..28ed7b9 100644
> --- a/src/ftracepy-utils.c
> +++ b/src/ftracepy-utils.c
> @@ -2064,6 +2064,40 @@ PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args,
>   	return PyDynevent_New(kprobe);
>   }
>   
> +PyObject *PyFtrace_register_eprobe(PyObject *self, PyObject *args,
> +						   PyObject *kwargs)
> +{

It seems that we have an inconsistency in the naming convention of the 'constructor' methods. The 'constructor' for 
kprobes is called 'register_kprobe', while for histograms and synthetic events we have just 'hist' and 'synth'. Lets use 
the short naming here (just 'eprobe') and you can remove the 'register' prefix from the constructor for kprobes in 
another patch.

> +	static char *kwlist[] = {"event", "target_system", "target_event", "fetchargs", NULL};
> +	const char *event, *target_system, *target_event, *fetchargs;
> +	struct tracefs_dynevent *eprobe;
> +
> +	if (!PyArg_ParseTupleAndKeywords(args,
> +					 kwargs,
> +					 "ssss",
> +					 kwlist,
> +					 &event,
> +					 &target_system,
> +					 &target_event,
> +					 &fetchargs)) {
> +		return NULL;
> +	}
> +
> +	eprobe = tracefs_eprobe_alloc(TC_SYS, event, target_system, target_event, fetchargs);
> +	if (!eprobe) {
> +		MEM_ERROR;
> +		return NULL;
> +	}
> +
> +	if (tracefs_dynevent_create(eprobe) < 0) {
> +		TfsError_fmt(NULL, "Failed to create eprobe '%s'", event);
> +		tracefs_dynevent_free(eprobe);
> +		return NULL;
> +	}
> +
> +	return PyDynevent_New(eprobe);
> +}
> +
> +
>   PyObject *PyDynevent_set_filter(PyDynevent *self, PyObject *args,
>   						  PyObject *kwargs)
>   {
> diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h
> index fc5016c..1030a50 100644
> --- a/src/ftracepy-utils.h
> +++ b/src/ftracepy-utils.h
> @@ -207,6 +207,9 @@ PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args,
>   PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args,
>   						      PyObject *kwargs);
>   
> +PyObject *PyFtrace_register_eprobe(PyObject *self, PyObject *args,
> +						   PyObject *kwargs);
> +
>   PyObject *PyFtrace_hist(PyObject *self, PyObject *args,
>   					PyObject *kwargs);
>   
> diff --git a/src/ftracepy.c b/src/ftracepy.c
> index f59bd4c..50ee4d3 100644
> --- a/src/ftracepy.c
> +++ b/src/ftracepy.c
> @@ -377,6 +377,11 @@ static PyMethodDef ftracepy_methods[] = {
>   	 METH_VARARGS | METH_KEYWORDS,
>   	 "Define a kretprobe."
>   	},
> +	{"register_eprobe",
> +	 (PyCFunction) PyFtrace_register_eprobe,
> +	 METH_VARARGS | METH_KEYWORDS,
> +	 "Define an eprobe."
> +	},
>   	{"hist",
>   	 (PyCFunction) PyFtrace_hist,
>   	 METH_VARARGS | METH_KEYWORDS,
> diff --git a/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py b/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py
> index 51970d3..12b58a0 100644
> --- a/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py
> +++ b/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py


Please move the tests in separate patch!

> @@ -457,6 +457,45 @@ class KprobeTestCase(unittest.TestCase):
>           ret = kp1.is_enabled(instance=inst)
>           self.assertEqual(ret, '0')
>   
> +class EprobeTestCase(unittest.TestCase):
> +    def test_register_eprobe(self):

This fails on my machine, because I am still on the 5.13 kernel. Maybe somewhere up in the file you can add a global 
variable defined like this:

kernel_version = tuple(map(int, (os.uname()[2].split('.')[:2])))

and here you can check the kernel version

	if kernel_version < (5, 15):
		return

> +        evt1 = 'sopen_in'
> +        evt1_tsys = 'syscalls'
> +        evt1_tevent = 'sys_enter_openat'
> +        evt1_args = 'file=+0($filename):ustring'
> +        evt2 = 'sopen_out'
> +        evt2_tsys = 'syscalls'
> +        evt2_tevent = 'sys_exit_openat'
> +        evt2_args = 'res=$ret:u64'
> +
> +        ep1 = ft.register_eprobe(event=evt1, target_system=evt1_tsys, target_event=evt1_tevent,
> +                                 fetchargs=evt1_args)
> +        self.assertEqual(evt1, ep1.event())
> +        self.assertEqual("{}.{}".format(evt1_tsys, evt1_tevent), ep1.address())
> +        self.assertEqual(evt1_args, ep1.probe())
> +
> +        ep2 = ft.register_eprobe(event=evt2, target_system=evt2_tsys, target_event=evt2_tevent,
> +                                 fetchargs=evt2_args)
> +        self.assertEqual(evt2, ep2.event())
> +        self.assertEqual("{}.{}".format(evt2_tsys, evt2_tevent), ep2.address())
> +        self.assertEqual(evt2_args, ep2.probe())
> +
> +    def test_enable_eprobe(self):

Another kernel version check

> +        evt1 = 'sopen_out'
> +        evt1_tsys = 'syscalls'
> +        evt1_tevent = 'sys_exit_openat'
> +        evt1_args = 'res=$ret:u64'
> +
> +        ep1 = ft.register_eprobe(event=evt1, target_system=evt1_tsys, target_event=evt1_tevent,
> +                                 fetchargs=evt1_args)
> +        inst = ft.create_instance(instance_name)
> +        ep1.enable(instance=inst)
> +        ret = ep1.is_enabled(instance=inst)
> +        self.assertEqual(ret, '1')
> +
> +        ep1.disable(instance=inst)
> +        ret = ep1.is_enabled(instance=inst)
> +        self.assertEqual(ret, '0')
>   
>   class TracingOnTestCase(unittest.TestCase):
>       def test_ON_OF(self):
> 


Ideally, there must be one more patch that will add an example.
Thanks!

Yordan

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

end of thread, other threads:[~2022-01-25 13:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-24 15:20 [PATCH] trace-cruncher: Add support for event probes Tzvetomir Stoyanov (VMware)
2022-01-25 13:28 ` Yordan Karadzhov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.