Skip to content

Commit 89ed424

Browse files
Divya Indirostedt
authored andcommitted
tracing: Sample module to demonstrate kernel access to Ftrace instances.
This is a sample module to demonstrate the use of the newly introduced and exported APIs to access Ftrace instances from within the kernel. Newly introduced APIs used here - 1. Create/Lookup a trace array with the given name. struct trace_array *trace_array_get_by_name(const char *name) 2. Destroy/Remove a trace array. int trace_array_destroy(struct trace_array *tr) 4. Enable/Disable trace events: int trace_array_set_clr_event(struct trace_array *tr, const char *system, const char *event, bool enable); Exported APIs - 1. trace_printk equivalent for instances. int trace_array_printk(struct trace_array *tr, unsigned long ip, const char *fmt, ...); 2. Helper function. void trace_printk_init_buffers(void); 3. To decrement the reference counter. void trace_array_put(struct trace_array *tr) Sample output(contents of /sys/kernel/tracing/instances/sample-instance) NOTE: Tracing disabled after ~5 sec) _-----=> irqs-off / _----=> need-resched | / _---=> hardirq/softirq || / _--=> preempt-depth ||| / delay TASK-PID CPU# |||| TIMESTAMP FUNCTION | | | |||| | | sample-instance-1452 [002] .... 49.430948: simple_thread: trace_array_printk: count=0 sample-instance-1452 [002] .... 49.430951: sample_event: count value=0 at jiffies=4294716608 sample-instance-1452 [002] .... 50.454847: simple_thread: trace_array_printk: count=1 sample-instance-1452 [002] .... 50.454849: sample_event: count value=1 at jiffies=4294717632 sample-instance-1452 [002] .... 51.478748: simple_thread: trace_array_printk: count=2 sample-instance-1452 [002] .... 51.478750: sample_event: count value=2 at jiffies=4294718656 sample-instance-1452 [002] .... 52.502652: simple_thread: trace_array_printk: count=3 sample-instance-1452 [002] .... 52.502655: sample_event: count value=3 at jiffies=4294719680 sample-instance-1452 [002] .... 53.526533: simple_thread: trace_array_printk: count=4 sample-instance-1452 [002] .... 53.526535: sample_event: count value=4 at jiffies=4294720704 sample-instance-1452 [002] .... 54.550438: simple_thread: trace_array_printk: count=5 sample-instance-1452 [002] .... 55.574336: simple_thread: trace_array_printk: count=6 Link: http://lkml.kernel.org/r/[email protected] Reviewed-by: Aruna Ramakrishna <[email protected]> Signed-off-by: Divya Indi <[email protected]> [ Moved to samples/ftrace ] Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 2887978 commit 89ed424

File tree

5 files changed

+226
-0
lines changed

5 files changed

+226
-0
lines changed

samples/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ config SAMPLE_FTRACE_DIRECT
2727
This builds an ftrace direct function example
2828
that hooks to wake_up_process and prints the parameters.
2929

30+
config SAMPLE_TRACE_ARRAY
31+
tristate "Build sample module for kernel access to Ftrace instancess"
32+
depends on EVENT_TRACING && m
33+
help
34+
This builds a module that demonstrates the use of various APIs to
35+
access Ftrace instances from within the kernel.
36+
3037
config SAMPLE_KOBJECT
3138
tristate "Build kobject examples"
3239
help

samples/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ subdir-$(CONFIG_SAMPLE_SECCOMP) += seccomp
1818
obj-$(CONFIG_SAMPLE_TRACE_EVENTS) += trace_events/
1919
obj-$(CONFIG_SAMPLE_TRACE_PRINTK) += trace_printk/
2020
obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace/
21+
obj-$(CONFIG_SAMPLE_TRACE_ARRAY) += ftrace/
2122
obj-$(CONFIG_VIDEO_PCI_SKELETON) += v4l/
2223
obj-y += vfio-mdev/
2324
subdir-$(CONFIG_SAMPLE_VFS) += vfs

samples/ftrace/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct.o
44
obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-too.o
55
obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-modify.o
6+
7+
CFLAGS_sample-trace-array.o := -I$(src)
8+
obj-$(CONFIG_SAMPLE_TRACE_ARRAY) += sample-trace-array.o

samples/ftrace/sample-trace-array.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
#include <linux/module.h>
3+
#include <linux/kthread.h>
4+
#include <linux/trace.h>
5+
#include <linux/trace_events.h>
6+
#include <linux/timer.h>
7+
#include <linux/err.h>
8+
#include <linux/jiffies.h>
9+
10+
/*
11+
* Any file that uses trace points, must include the header.
12+
* But only one file, must include the header by defining
13+
* CREATE_TRACE_POINTS first. This will make the C code that
14+
* creates the handles for the trace points.
15+
*/
16+
#define CREATE_TRACE_POINTS
17+
#include "sample-trace-array.h"
18+
19+
struct trace_array *tr;
20+
static void mytimer_handler(struct timer_list *unused);
21+
static struct task_struct *simple_tsk;
22+
23+
/*
24+
* mytimer: Timer setup to disable tracing for event "sample_event". This
25+
* timer is only for the purposes of the sample module to demonstrate access of
26+
* Ftrace instances from within kernel.
27+
*/
28+
static DEFINE_TIMER(mytimer, mytimer_handler);
29+
30+
static void mytimer_handler(struct timer_list *unused)
31+
{
32+
/*
33+
* Disable tracing for event "sample_event".
34+
*/
35+
trace_array_set_clr_event(tr, "sample-subsystem", "sample_event",
36+
false);
37+
}
38+
39+
static void simple_thread_func(int count)
40+
{
41+
set_current_state(TASK_INTERRUPTIBLE);
42+
schedule_timeout(HZ);
43+
44+
/*
45+
* Printing count value using trace_array_printk() - trace_printk()
46+
* equivalent for the instance buffers.
47+
*/
48+
trace_array_printk(tr, _THIS_IP_, "trace_array_printk: count=%d\n",
49+
count);
50+
/*
51+
* Tracepoint for event "sample_event". This will print the
52+
* current value of count and current jiffies.
53+
*/
54+
trace_sample_event(count, jiffies);
55+
}
56+
57+
static int simple_thread(void *arg)
58+
{
59+
int count = 0;
60+
unsigned long delay = msecs_to_jiffies(5000);
61+
62+
/*
63+
* Enable tracing for "sample_event".
64+
*/
65+
trace_array_set_clr_event(tr, "sample-subsystem", "sample_event", true);
66+
67+
/*
68+
* Adding timer - mytimer. This timer will disable tracing after
69+
* delay seconds.
70+
*
71+
*/
72+
add_timer(&mytimer);
73+
mod_timer(&mytimer, jiffies+delay);
74+
75+
while (!kthread_should_stop())
76+
simple_thread_func(count++);
77+
78+
del_timer(&mytimer);
79+
80+
/*
81+
* trace_array_put() decrements the reference counter associated with
82+
* the trace array - "tr". We are done using the trace array, hence
83+
* decrement the reference counter so that it can be destroyed using
84+
* trace_array_destroy().
85+
*/
86+
trace_array_put(tr);
87+
88+
return 0;
89+
}
90+
91+
static int __init sample_trace_array_init(void)
92+
{
93+
/*
94+
* Return a pointer to the trace array with name "sample-instance" if it
95+
* exists, else create a new trace array.
96+
*
97+
* NOTE: This function increments the reference counter
98+
* associated with the trace array - "tr".
99+
*/
100+
tr = trace_array_get_by_name("sample-instance");
101+
102+
if (!tr)
103+
return -1;
104+
/*
105+
* If context specific per-cpu buffers havent already been allocated.
106+
*/
107+
trace_printk_init_buffers();
108+
109+
simple_tsk = kthread_run(simple_thread, NULL, "sample-instance");
110+
if (IS_ERR(simple_tsk))
111+
return -1;
112+
return 0;
113+
}
114+
115+
static void __exit sample_trace_array_exit(void)
116+
{
117+
kthread_stop(simple_tsk);
118+
119+
/*
120+
* We are unloading our module and no longer require the trace array.
121+
* Remove/destroy "tr" using trace_array_destroy()
122+
*/
123+
trace_array_destroy(tr);
124+
}
125+
126+
module_init(sample_trace_array_init);
127+
module_exit(sample_trace_array_exit);
128+
129+
MODULE_AUTHOR("Divya Indi");
130+
MODULE_DESCRIPTION("Sample module for kernel access to Ftrace instances");
131+
MODULE_LICENSE("GPL");

samples/ftrace/sample-trace-array.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
/*
4+
* If TRACE_SYSTEM is defined, that will be the directory created
5+
* in the ftrace directory under /sys/kernel/tracing/events/<system>
6+
*
7+
* The define_trace.h below will also look for a file name of
8+
* TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here.
9+
* In this case, it would look for sample-trace.h
10+
*
11+
* If the header name will be different than the system name
12+
* (as in this case), then you can override the header name that
13+
* define_trace.h will look up by defining TRACE_INCLUDE_FILE
14+
*
15+
* This file is called sample-trace-array.h but we want the system
16+
* to be called "sample-subsystem". Therefore we must define the name of this
17+
* file:
18+
*
19+
* #define TRACE_INCLUDE_FILE sample-trace-array
20+
*
21+
* As we do in the bottom of this file.
22+
*
23+
* Notice that TRACE_SYSTEM should be defined outside of #if
24+
* protection, just like TRACE_INCLUDE_FILE.
25+
*/
26+
#undef TRACE_SYSTEM
27+
#define TRACE_SYSTEM sample-subsystem
28+
29+
/*
30+
* TRACE_SYSTEM is expected to be a C valid variable (alpha-numeric
31+
* and underscore), although it may start with numbers. If for some
32+
* reason it is not, you need to add the following lines:
33+
*/
34+
#undef TRACE_SYSTEM_VAR
35+
#define TRACE_SYSTEM_VAR sample_subsystem
36+
37+
/*
38+
* But the above is only needed if TRACE_SYSTEM is not alpha-numeric
39+
* and underscored. By default, TRACE_SYSTEM_VAR will be equal to
40+
* TRACE_SYSTEM. As TRACE_SYSTEM_VAR must be alpha-numeric, if
41+
* TRACE_SYSTEM is not, then TRACE_SYSTEM_VAR must be defined with
42+
* only alpha-numeric and underscores.
43+
*
44+
* The TRACE_SYSTEM_VAR is only used internally and not visible to
45+
* user space.
46+
*/
47+
48+
/*
49+
* Notice that this file is not protected like a normal header.
50+
* We also must allow for rereading of this file. The
51+
*
52+
* || defined(TRACE_HEADER_MULTI_READ)
53+
*
54+
* serves this purpose.
55+
*/
56+
#if !defined(_SAMPLE_TRACE_ARRAY_H) || defined(TRACE_HEADER_MULTI_READ)
57+
#define _SAMPLE_TRACE_ARRAY_H
58+
59+
#include <linux/tracepoint.h>
60+
TRACE_EVENT(sample_event,
61+
62+
TP_PROTO(int count, unsigned long time),
63+
64+
TP_ARGS(count, time),
65+
66+
TP_STRUCT__entry(
67+
__field(int, count)
68+
__field(unsigned long, time)
69+
),
70+
71+
TP_fast_assign(
72+
__entry->count = count;
73+
__entry->time = time;
74+
),
75+
76+
TP_printk("count value=%d at jiffies=%lu", __entry->count,
77+
__entry->time)
78+
);
79+
#endif
80+
81+
#undef TRACE_INCLUDE_PATH
82+
#define TRACE_INCLUDE_PATH .
83+
#define TRACE_INCLUDE_FILE sample-trace-array
84+
#include <trace/define_trace.h>

0 commit comments

Comments
 (0)