diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-03-04 14:00:05 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-03-04 14:00:05 -0500 |
commit | 0bbdb4258bd116d8cd5d209e8d5b29bae516e5b3 (patch) | |
tree | c607302701f7a7942f2e76391fdb406ec86628d5 /samples | |
parent | bd624d75db21ea5402f9ecf4450b311794d80352 (diff) | |
parent | 13a7a6ac0a11197edcd0f756a035f472b42cdf8b (diff) |
Merge tag 'v4.0-rc2' into timers/core, to refresh the tree before pulling more changes
Diffstat (limited to 'samples')
-rw-r--r-- | samples/Kconfig | 7 | ||||
-rw-r--r-- | samples/Makefile | 2 | ||||
-rw-r--r-- | samples/bpf/test_maps.c | 4 | ||||
-rw-r--r-- | samples/livepatch/Makefile | 1 | ||||
-rw-r--r-- | samples/livepatch/livepatch-sample.c | 91 | ||||
-rw-r--r-- | samples/seccomp/bpf-fancy.c | 4 | ||||
-rw-r--r-- | samples/seccomp/bpf-helper.c | 6 | ||||
-rw-r--r-- | samples/trace_events/trace-events-sample.c | 80 | ||||
-rw-r--r-- | samples/trace_events/trace-events-sample.h | 328 |
9 files changed, 505 insertions, 18 deletions
diff --git a/samples/Kconfig b/samples/Kconfig index 6181c2cc9ca0..224ebb46bed5 100644 --- a/samples/Kconfig +++ b/samples/Kconfig | |||
@@ -63,4 +63,11 @@ config SAMPLE_RPMSG_CLIENT | |||
63 | to communicate with an AMP-configured remote processor over | 63 | to communicate with an AMP-configured remote processor over |
64 | the rpmsg bus. | 64 | the rpmsg bus. |
65 | 65 | ||
66 | config SAMPLE_LIVEPATCH | ||
67 | tristate "Build live patching sample -- loadable modules only" | ||
68 | depends on LIVEPATCH && m | ||
69 | help | ||
70 | Builds a sample live patch that replaces the procfs handler | ||
71 | for /proc/cmdline to print "this has been live patched". | ||
72 | |||
66 | endif # SAMPLES | 73 | endif # SAMPLES |
diff --git a/samples/Makefile b/samples/Makefile index 1a60c62e2045..f00257bcc5a7 100644 --- a/samples/Makefile +++ b/samples/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # Makefile for Linux samples code | 1 | # Makefile for Linux samples code |
2 | 2 | ||
3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ \ | 3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ |
4 | hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ | 4 | hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ |
diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c index e286b42307f3..6299ee95cd11 100644 --- a/samples/bpf/test_maps.c +++ b/samples/bpf/test_maps.c | |||
@@ -69,9 +69,9 @@ static void test_hashmap_sanity(int i, void *data) | |||
69 | 69 | ||
70 | /* iterate over two elements */ | 70 | /* iterate over two elements */ |
71 | assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 && | 71 | assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 && |
72 | next_key == 2); | 72 | (next_key == 1 || next_key == 2)); |
73 | assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 && | 73 | assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 && |
74 | next_key == 1); | 74 | (next_key == 1 || next_key == 2)); |
75 | assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 && | 75 | assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 && |
76 | errno == ENOENT); | 76 | errno == ENOENT); |
77 | 77 | ||
diff --git a/samples/livepatch/Makefile b/samples/livepatch/Makefile new file mode 100644 index 000000000000..10319d7ea0b1 --- /dev/null +++ b/samples/livepatch/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-sample.o | |||
diff --git a/samples/livepatch/livepatch-sample.c b/samples/livepatch/livepatch-sample.c new file mode 100644 index 000000000000..fb8c8614e728 --- /dev/null +++ b/samples/livepatch/livepatch-sample.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * livepatch-sample.c - Kernel Live Patching Sample Module | ||
3 | * | ||
4 | * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/livepatch.h> | ||
23 | |||
24 | /* | ||
25 | * This (dumb) live patch overrides the function that prints the | ||
26 | * kernel boot cmdline when /proc/cmdline is read. | ||
27 | * | ||
28 | * Example: | ||
29 | * | ||
30 | * $ cat /proc/cmdline | ||
31 | * <your cmdline> | ||
32 | * | ||
33 | * $ insmod livepatch-sample.ko | ||
34 | * $ cat /proc/cmdline | ||
35 | * this has been live patched | ||
36 | * | ||
37 | * $ echo 0 > /sys/kernel/livepatch/livepatch_sample/enabled | ||
38 | * $ cat /proc/cmdline | ||
39 | * <your cmdline> | ||
40 | */ | ||
41 | |||
42 | #include <linux/seq_file.h> | ||
43 | static int livepatch_cmdline_proc_show(struct seq_file *m, void *v) | ||
44 | { | ||
45 | seq_printf(m, "%s\n", "this has been live patched"); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static struct klp_func funcs[] = { | ||
50 | { | ||
51 | .old_name = "cmdline_proc_show", | ||
52 | .new_func = livepatch_cmdline_proc_show, | ||
53 | }, { } | ||
54 | }; | ||
55 | |||
56 | static struct klp_object objs[] = { | ||
57 | { | ||
58 | /* name being NULL means vmlinux */ | ||
59 | .funcs = funcs, | ||
60 | }, { } | ||
61 | }; | ||
62 | |||
63 | static struct klp_patch patch = { | ||
64 | .mod = THIS_MODULE, | ||
65 | .objs = objs, | ||
66 | }; | ||
67 | |||
68 | static int livepatch_init(void) | ||
69 | { | ||
70 | int ret; | ||
71 | |||
72 | ret = klp_register_patch(&patch); | ||
73 | if (ret) | ||
74 | return ret; | ||
75 | ret = klp_enable_patch(&patch); | ||
76 | if (ret) { | ||
77 | WARN_ON(klp_unregister_patch(&patch)); | ||
78 | return ret; | ||
79 | } | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void livepatch_exit(void) | ||
84 | { | ||
85 | WARN_ON(klp_disable_patch(&patch)); | ||
86 | WARN_ON(klp_unregister_patch(&patch)); | ||
87 | } | ||
88 | |||
89 | module_init(livepatch_init); | ||
90 | module_exit(livepatch_exit); | ||
91 | MODULE_LICENSE("GPL"); | ||
diff --git a/samples/seccomp/bpf-fancy.c b/samples/seccomp/bpf-fancy.c index 8eb483aaec46..e8b24f443709 100644 --- a/samples/seccomp/bpf-fancy.c +++ b/samples/seccomp/bpf-fancy.c | |||
@@ -25,7 +25,9 @@ | |||
25 | 25 | ||
26 | int main(int argc, char **argv) | 26 | int main(int argc, char **argv) |
27 | { | 27 | { |
28 | struct bpf_labels l; | 28 | struct bpf_labels l = { |
29 | .count = 0, | ||
30 | }; | ||
29 | static const char msg1[] = "Please type something: "; | 31 | static const char msg1[] = "Please type something: "; |
30 | static const char msg2[] = "You typed: "; | 32 | static const char msg2[] = "You typed: "; |
31 | char buf[256]; | 33 | char buf[256]; |
diff --git a/samples/seccomp/bpf-helper.c b/samples/seccomp/bpf-helper.c index 579cfe331886..05cb4d5ff9f5 100644 --- a/samples/seccomp/bpf-helper.c +++ b/samples/seccomp/bpf-helper.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <stdio.h> | 12 | #include <stdio.h> |
13 | #include <stdlib.h> | ||
13 | #include <string.h> | 14 | #include <string.h> |
14 | 15 | ||
15 | #include "bpf-helper.h" | 16 | #include "bpf-helper.h" |
@@ -63,6 +64,11 @@ __u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label) | |||
63 | { | 64 | { |
64 | struct __bpf_label *begin = labels->labels, *end; | 65 | struct __bpf_label *begin = labels->labels, *end; |
65 | int id; | 66 | int id; |
67 | |||
68 | if (labels->count == BPF_LABELS_MAX) { | ||
69 | fprintf(stderr, "Too many labels\n"); | ||
70 | exit(1); | ||
71 | } | ||
66 | if (labels->count == 0) { | 72 | if (labels->count == 0) { |
67 | begin->label = label; | 73 | begin->label = label; |
68 | begin->location = 0xffffffff; | 74 | begin->location = 0xffffffff; |
diff --git a/samples/trace_events/trace-events-sample.c b/samples/trace_events/trace-events-sample.c index aabc4e970911..880a7d1d27d2 100644 --- a/samples/trace_events/trace-events-sample.c +++ b/samples/trace_events/trace-events-sample.c | |||
@@ -10,12 +10,38 @@ | |||
10 | #define CREATE_TRACE_POINTS | 10 | #define CREATE_TRACE_POINTS |
11 | #include "trace-events-sample.h" | 11 | #include "trace-events-sample.h" |
12 | 12 | ||
13 | static const char *random_strings[] = { | ||
14 | "Mother Goose", | ||
15 | "Snoopy", | ||
16 | "Gandalf", | ||
17 | "Frodo", | ||
18 | "One ring to rule them all" | ||
19 | }; | ||
13 | 20 | ||
14 | static void simple_thread_func(int cnt) | 21 | static void simple_thread_func(int cnt) |
15 | { | 22 | { |
23 | int array[6]; | ||
24 | int len = cnt % 5; | ||
25 | int i; | ||
26 | |||
16 | set_current_state(TASK_INTERRUPTIBLE); | 27 | set_current_state(TASK_INTERRUPTIBLE); |
17 | schedule_timeout(HZ); | 28 | schedule_timeout(HZ); |
18 | trace_foo_bar("hello", cnt); | 29 | |
30 | for (i = 0; i < len; i++) | ||
31 | array[i] = i + 1; | ||
32 | array[i] = 0; | ||
33 | |||
34 | /* Silly tracepoints */ | ||
35 | trace_foo_bar("hello", cnt, array, random_strings[len], | ||
36 | tsk_cpus_allowed(current)); | ||
37 | |||
38 | trace_foo_with_template_simple("HELLO", cnt); | ||
39 | |||
40 | trace_foo_bar_with_cond("Some times print", cnt); | ||
41 | |||
42 | trace_foo_with_template_cond("prints other times", cnt); | ||
43 | |||
44 | trace_foo_with_template_print("I have to be different", cnt); | ||
19 | } | 45 | } |
20 | 46 | ||
21 | static int simple_thread(void *arg) | 47 | static int simple_thread(void *arg) |
@@ -29,6 +55,53 @@ static int simple_thread(void *arg) | |||
29 | } | 55 | } |
30 | 56 | ||
31 | static struct task_struct *simple_tsk; | 57 | static struct task_struct *simple_tsk; |
58 | static struct task_struct *simple_tsk_fn; | ||
59 | |||
60 | static void simple_thread_func_fn(int cnt) | ||
61 | { | ||
62 | set_current_state(TASK_INTERRUPTIBLE); | ||
63 | schedule_timeout(HZ); | ||
64 | |||
65 | /* More silly tracepoints */ | ||
66 | trace_foo_bar_with_fn("Look at me", cnt); | ||
67 | trace_foo_with_template_fn("Look at me too", cnt); | ||
68 | } | ||
69 | |||
70 | static int simple_thread_fn(void *arg) | ||
71 | { | ||
72 | int cnt = 0; | ||
73 | |||
74 | while (!kthread_should_stop()) | ||
75 | simple_thread_func_fn(cnt++); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static DEFINE_MUTEX(thread_mutex); | ||
81 | |||
82 | void foo_bar_reg(void) | ||
83 | { | ||
84 | pr_info("Starting thread for foo_bar_fn\n"); | ||
85 | /* | ||
86 | * We shouldn't be able to start a trace when the module is | ||
87 | * unloading (there's other locks to prevent that). But | ||
88 | * for consistency sake, we still take the thread_mutex. | ||
89 | */ | ||
90 | mutex_lock(&thread_mutex); | ||
91 | simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn"); | ||
92 | mutex_unlock(&thread_mutex); | ||
93 | } | ||
94 | |||
95 | void foo_bar_unreg(void) | ||
96 | { | ||
97 | pr_info("Killing thread for foo_bar_fn\n"); | ||
98 | /* protect against module unloading */ | ||
99 | mutex_lock(&thread_mutex); | ||
100 | if (simple_tsk_fn) | ||
101 | kthread_stop(simple_tsk_fn); | ||
102 | simple_tsk_fn = NULL; | ||
103 | mutex_unlock(&thread_mutex); | ||
104 | } | ||
32 | 105 | ||
33 | static int __init trace_event_init(void) | 106 | static int __init trace_event_init(void) |
34 | { | 107 | { |
@@ -42,6 +115,11 @@ static int __init trace_event_init(void) | |||
42 | static void __exit trace_event_exit(void) | 115 | static void __exit trace_event_exit(void) |
43 | { | 116 | { |
44 | kthread_stop(simple_tsk); | 117 | kthread_stop(simple_tsk); |
118 | mutex_lock(&thread_mutex); | ||
119 | if (simple_tsk_fn) | ||
120 | kthread_stop(simple_tsk_fn); | ||
121 | simple_tsk_fn = NULL; | ||
122 | mutex_unlock(&thread_mutex); | ||
45 | } | 123 | } |
46 | 124 | ||
47 | module_init(trace_event_init); | 125 | module_init(trace_event_init); |
diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h index 476429281389..a2c8b02b6359 100644 --- a/samples/trace_events/trace-events-sample.h +++ b/samples/trace_events/trace-events-sample.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * If TRACE_SYSTEM is defined, that will be the directory created | 2 | * If TRACE_SYSTEM is defined, that will be the directory created |
3 | * in the ftrace directory under /sys/kernel/debug/tracing/events/<system> | 3 | * in the ftrace directory under /sys/kernel/tracing/events/<system> |
4 | * | 4 | * |
5 | * The define_trace.h below will also look for a file name of | 5 | * The define_trace.h below will also look for a file name of |
6 | * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here. | 6 | * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here. |
@@ -54,45 +54,347 @@ | |||
54 | * Here it is simply "foo, bar". | 54 | * Here it is simply "foo, bar". |
55 | * | 55 | * |
56 | * struct: This defines the way the data will be stored in the ring buffer. | 56 | * struct: This defines the way the data will be stored in the ring buffer. |
57 | * There are currently two types of elements. __field and __array. | 57 | * The items declared here become part of a special structure |
58 | * a __field is broken up into (type, name). Where type can be any | 58 | * called "__entry", which can be used in the fast_assign part of the |
59 | * primitive type (integer, long or pointer). __field_struct() can | 59 | * TRACE_EVENT macro. |
60 | * be any static complex data value (struct, union, but not an array). | 60 | * |
61 | * For an array. there are three fields. (type, name, size). The | 61 | * Here are the currently defined types you can use: |
62 | * type of elements in the array, the name of the field and the size | 62 | * |
63 | * of the array. | 63 | * __field : Is broken up into type and name. Where type can be any |
64 | * primitive type (integer, long or pointer). | ||
65 | * | ||
66 | * __field(int, foo) | ||
67 | * | ||
68 | * __entry->foo = 5; | ||
69 | * | ||
70 | * __field_struct : This can be any static complex data type (struct, union | ||
71 | * but not an array). Be careful using complex types, as each | ||
72 | * event is limited in size, and copying large amounts of data | ||
73 | * into the ring buffer can slow things down. | ||
74 | * | ||
75 | * __field_struct(struct bar, foo) | ||
76 | * | ||
77 | * __entry->bar.x = y; | ||
78 | |||
79 | * __array: There are three fields (type, name, size). The type is the | ||
80 | * type of elements in teh array, the name is the name of the array. | ||
81 | * size is the number of items in the array (not the total size). | ||
82 | * | ||
83 | * __array( char, foo, 10) is the same as saying: char foo[10]; | ||
84 | * | ||
85 | * Assigning arrays can be done like any array: | ||
86 | * | ||
87 | * __entry->foo[0] = 'a'; | ||
88 | * | ||
89 | * memcpy(__entry->foo, bar, 10); | ||
90 | * | ||
91 | * __dynamic_array: This is similar to array, but can vary is size from | ||
92 | * instance to instance of the tracepoint being called. | ||
93 | * Like __array, this too has three elements (type, name, size); | ||
94 | * type is the type of the element, name is the name of the array. | ||
95 | * The size is different than __array. It is not a static number, | ||
96 | * but the algorithm to figure out the length of the array for the | ||
97 | * specific instance of tracepoint. Again, size is the numebr of | ||
98 | * items in the array, not the total length in bytes. | ||
99 | * | ||
100 | * __dynamic_array( int, foo, bar) is similar to: int foo[bar]; | ||
101 | * | ||
102 | * Note, unlike arrays, you must use the __get_dynamic_array() macro | ||
103 | * to access the array. | ||
104 | * | ||
105 | * memcpy(__get_dynamic_array(foo), bar, 10); | ||
106 | * | ||
107 | * Notice, that "__entry" is not needed here. | ||
108 | * | ||
109 | * __string: This is a special kind of __dynamic_array. It expects to | ||
110 | * have a nul terminated character array passed to it (it allows | ||
111 | * for NULL too, which would be converted into "(null)"). __string | ||
112 | * takes two paramenter (name, src), where name is the name of | ||
113 | * the string saved, and src is the string to copy into the | ||
114 | * ring buffer. | ||
115 | * | ||
116 | * __string(foo, bar) is similar to: strcpy(foo, bar) | ||
117 | * | ||
118 | * To assign a string, use the helper macro __assign_str(). | ||
119 | * | ||
120 | * __assign_str(foo, bar); | ||
121 | * | ||
122 | * In most cases, the __assign_str() macro will take the same | ||
123 | * parameters as the __string() macro had to declare the string. | ||
124 | * | ||
125 | * __bitmask: This is another kind of __dynamic_array, but it expects | ||
126 | * an array of longs, and the number of bits to parse. It takes | ||
127 | * two parameters (name, nr_bits), where name is the name of the | ||
128 | * bitmask to save, and the nr_bits is the number of bits to record. | ||
129 | * | ||
130 | * __bitmask(target_cpu, nr_cpumask_bits) | ||
131 | * | ||
132 | * To assign a bitmask, use the __assign_bitmask() helper macro. | ||
133 | * | ||
134 | * __assign_bitmask(target_cpus, cpumask_bits(bar), nr_cpumask_bits); | ||
64 | * | 135 | * |
65 | * __array( char, foo, 10) is the same as saying char foo[10]. | ||
66 | * | 136 | * |
67 | * fast_assign: This is a C like function that is used to store the items | 137 | * fast_assign: This is a C like function that is used to store the items |
68 | * into the ring buffer. | 138 | * into the ring buffer. A special variable called "__entry" will be the |
139 | * structure that points into the ring buffer and has the same fields as | ||
140 | * described by the struct part of TRACE_EVENT above. | ||
69 | * | 141 | * |
70 | * printk: This is a way to print out the data in pretty print. This is | 142 | * printk: This is a way to print out the data in pretty print. This is |
71 | * useful if the system crashes and you are logging via a serial line, | 143 | * useful if the system crashes and you are logging via a serial line, |
72 | * the data can be printed to the console using this "printk" method. | 144 | * the data can be printed to the console using this "printk" method. |
145 | * This is also used to print out the data from the trace files. | ||
146 | * Again, the __entry macro is used to access the data from the ring buffer. | ||
147 | * | ||
148 | * Note, __dynamic_array, __string, and __bitmask require special helpers | ||
149 | * to access the data. | ||
150 | * | ||
151 | * For __dynamic_array(int, foo, bar) use __get_dynamic_array(foo) | ||
152 | * Use __get_dynamic_array_len(foo) to get the length of the array | ||
153 | * saved. | ||
154 | * | ||
155 | * For __string(foo, bar) use __get_str(foo) | ||
156 | * | ||
157 | * For __bitmask(target_cpus, nr_cpumask_bits) use __get_bitmask(target_cpus) | ||
158 | * | ||
73 | * | 159 | * |
74 | * Note, that for both the assign and the printk, __entry is the handler | 160 | * Note, that for both the assign and the printk, __entry is the handler |
75 | * to the data structure in the ring buffer, and is defined by the | 161 | * to the data structure in the ring buffer, and is defined by the |
76 | * TP_STRUCT__entry. | 162 | * TP_STRUCT__entry. |
77 | */ | 163 | */ |
164 | |||
165 | /* | ||
166 | * It is OK to have helper functions in the file, but they need to be protected | ||
167 | * from being defined more than once. Remember, this file gets included more | ||
168 | * than once. | ||
169 | */ | ||
170 | #ifndef __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS | ||
171 | #define __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS | ||
172 | static inline int __length_of(const int *list) | ||
173 | { | ||
174 | int i; | ||
175 | |||
176 | if (!list) | ||
177 | return 0; | ||
178 | |||
179 | for (i = 0; list[i]; i++) | ||
180 | ; | ||
181 | return i; | ||
182 | } | ||
183 | #endif | ||
184 | |||
78 | TRACE_EVENT(foo_bar, | 185 | TRACE_EVENT(foo_bar, |
79 | 186 | ||
80 | TP_PROTO(char *foo, int bar), | 187 | TP_PROTO(const char *foo, int bar, const int *lst, |
188 | const char *string, const struct cpumask *mask), | ||
81 | 189 | ||
82 | TP_ARGS(foo, bar), | 190 | TP_ARGS(foo, bar, lst, string, mask), |
83 | 191 | ||
84 | TP_STRUCT__entry( | 192 | TP_STRUCT__entry( |
85 | __array( char, foo, 10 ) | 193 | __array( char, foo, 10 ) |
86 | __field( int, bar ) | 194 | __field( int, bar ) |
195 | __dynamic_array(int, list, __length_of(lst)) | ||
196 | __string( str, string ) | ||
197 | __bitmask( cpus, num_possible_cpus() ) | ||
87 | ), | 198 | ), |
88 | 199 | ||
89 | TP_fast_assign( | 200 | TP_fast_assign( |
90 | strlcpy(__entry->foo, foo, 10); | 201 | strlcpy(__entry->foo, foo, 10); |
91 | __entry->bar = bar; | 202 | __entry->bar = bar; |
203 | memcpy(__get_dynamic_array(list), lst, | ||
204 | __length_of(lst) * sizeof(int)); | ||
205 | __assign_str(str, string); | ||
206 | __assign_bitmask(cpus, cpumask_bits(mask), num_possible_cpus()); | ||
207 | ), | ||
208 | |||
209 | TP_printk("foo %s %d %s %s (%s)", __entry->foo, __entry->bar, | ||
210 | __print_array(__get_dynamic_array(list), | ||
211 | __get_dynamic_array_len(list), | ||
212 | sizeof(int)), | ||
213 | __get_str(str), __get_bitmask(cpus)) | ||
214 | ); | ||
215 | |||
216 | /* | ||
217 | * There may be a case where a tracepoint should only be called if | ||
218 | * some condition is set. Otherwise the tracepoint should not be called. | ||
219 | * But to do something like: | ||
220 | * | ||
221 | * if (cond) | ||
222 | * trace_foo(); | ||
223 | * | ||
224 | * Would cause a little overhead when tracing is not enabled, and that | ||
225 | * overhead, even if small, is not something we want. As tracepoints | ||
226 | * use static branch (aka jump_labels), where no branch is taken to | ||
227 | * skip the tracepoint when not enabled, and a jmp is placed to jump | ||
228 | * to the tracepoint code when it is enabled, having a if statement | ||
229 | * nullifies that optimization. It would be nice to place that | ||
230 | * condition within the static branch. This is where TRACE_EVENT_CONDITION | ||
231 | * comes in. | ||
232 | * | ||
233 | * TRACE_EVENT_CONDITION() is just like TRACE_EVENT, except it adds another | ||
234 | * parameter just after args. Where TRACE_EVENT has: | ||
235 | * | ||
236 | * TRACE_EVENT(name, proto, args, struct, assign, printk) | ||
237 | * | ||
238 | * the CONDITION version has: | ||
239 | * | ||
240 | * TRACE_EVENT_CONDITION(name, proto, args, cond, struct, assign, printk) | ||
241 | * | ||
242 | * Everything is the same as TRACE_EVENT except for the new cond. Think | ||
243 | * of the cond variable as: | ||
244 | * | ||
245 | * if (cond) | ||
246 | * trace_foo_bar_with_cond(); | ||
247 | * | ||
248 | * Except that the logic for the if branch is placed after the static branch. | ||
249 | * That is, the if statement that processes the condition will not be | ||
250 | * executed unless that traecpoint is enabled. Otherwise it still remains | ||
251 | * a nop. | ||
252 | */ | ||
253 | TRACE_EVENT_CONDITION(foo_bar_with_cond, | ||
254 | |||
255 | TP_PROTO(const char *foo, int bar), | ||
256 | |||
257 | TP_ARGS(foo, bar), | ||
258 | |||
259 | TP_CONDITION(!(bar % 10)), | ||
260 | |||
261 | TP_STRUCT__entry( | ||
262 | __string( foo, foo ) | ||
263 | __field( int, bar ) | ||
264 | ), | ||
265 | |||
266 | TP_fast_assign( | ||
267 | __assign_str(foo, foo); | ||
268 | __entry->bar = bar; | ||
269 | ), | ||
270 | |||
271 | TP_printk("foo %s %d", __get_str(foo), __entry->bar) | ||
272 | ); | ||
273 | |||
274 | void foo_bar_reg(void); | ||
275 | void foo_bar_unreg(void); | ||
276 | |||
277 | /* | ||
278 | * Now in the case that some function needs to be called when the | ||
279 | * tracepoint is enabled and/or when it is disabled, the | ||
280 | * TRACE_EVENT_FN() serves this purpose. This is just like TRACE_EVENT() | ||
281 | * but adds two more parameters at the end: | ||
282 | * | ||
283 | * TRACE_EVENT_FN( name, proto, args, struct, assign, printk, reg, unreg) | ||
284 | * | ||
285 | * reg and unreg are functions with the prototype of: | ||
286 | * | ||
287 | * void reg(void) | ||
288 | * | ||
289 | * The reg function gets called before the tracepoint is enabled, and | ||
290 | * the unreg function gets called after the tracepoint is disabled. | ||
291 | * | ||
292 | * Note, reg and unreg are allowed to be NULL. If you only need to | ||
293 | * call a function before enabling, or after disabling, just set one | ||
294 | * function and pass in NULL for the other parameter. | ||
295 | */ | ||
296 | TRACE_EVENT_FN(foo_bar_with_fn, | ||
297 | |||
298 | TP_PROTO(const char *foo, int bar), | ||
299 | |||
300 | TP_ARGS(foo, bar), | ||
301 | |||
302 | TP_STRUCT__entry( | ||
303 | __string( foo, foo ) | ||
304 | __field( int, bar ) | ||
305 | ), | ||
306 | |||
307 | TP_fast_assign( | ||
308 | __assign_str(foo, foo); | ||
309 | __entry->bar = bar; | ||
310 | ), | ||
311 | |||
312 | TP_printk("foo %s %d", __get_str(foo), __entry->bar), | ||
313 | |||
314 | foo_bar_reg, foo_bar_unreg | ||
315 | ); | ||
316 | |||
317 | /* | ||
318 | * Each TRACE_EVENT macro creates several helper functions to produce | ||
319 | * the code to add the tracepoint, create the files in the trace | ||
320 | * directory, hook it to perf, assign the values and to print out | ||
321 | * the raw data from the ring buffer. To prevent too much bloat, | ||
322 | * if there are more than one tracepoint that uses the same format | ||
323 | * for the proto, args, struct, assign and printk, and only the name | ||
324 | * is different, it is highly recommended to use the DECLARE_EVENT_CLASS | ||
325 | * | ||
326 | * DECLARE_EVENT_CLASS() macro creates most of the functions for the | ||
327 | * tracepoint. Then DEFINE_EVENT() is use to hook a tracepoint to those | ||
328 | * functions. This DEFINE_EVENT() is an instance of the class and can | ||
329 | * be enabled and disabled separately from other events (either TRACE_EVENT | ||
330 | * or other DEFINE_EVENT()s). | ||
331 | * | ||
332 | * Note, TRACE_EVENT() itself is simply defined as: | ||
333 | * | ||
334 | * #define TRACE_EVENT(name, proto, args, tstruct, assign, printk) \ | ||
335 | * DEFINE_EVENT_CLASS(name, proto, args, tstruct, assign, printk); \ | ||
336 | * DEFINE_EVENT(name, name, proto, args) | ||
337 | * | ||
338 | * The DEFINE_EVENT() also can be declared with conditions and reg functions: | ||
339 | * | ||
340 | * DEFINE_EVENT_CONDITION(template, name, proto, args, cond); | ||
341 | * DEFINE_EVENT_FN(template, name, proto, args, reg, unreg); | ||
342 | */ | ||
343 | DECLARE_EVENT_CLASS(foo_template, | ||
344 | |||
345 | TP_PROTO(const char *foo, int bar), | ||
346 | |||
347 | TP_ARGS(foo, bar), | ||
348 | |||
349 | TP_STRUCT__entry( | ||
350 | __string( foo, foo ) | ||
351 | __field( int, bar ) | ||
352 | ), | ||
353 | |||
354 | TP_fast_assign( | ||
355 | __assign_str(foo, foo); | ||
356 | __entry->bar = bar; | ||
92 | ), | 357 | ), |
93 | 358 | ||
94 | TP_printk("foo %s %d", __entry->foo, __entry->bar) | 359 | TP_printk("foo %s %d", __get_str(foo), __entry->bar) |
95 | ); | 360 | ); |
361 | |||
362 | /* | ||
363 | * Here's a better way for the previous samples (except, the first | ||
364 | * exmaple had more fields and could not be used here). | ||
365 | */ | ||
366 | DEFINE_EVENT(foo_template, foo_with_template_simple, | ||
367 | TP_PROTO(const char *foo, int bar), | ||
368 | TP_ARGS(foo, bar)); | ||
369 | |||
370 | DEFINE_EVENT_CONDITION(foo_template, foo_with_template_cond, | ||
371 | TP_PROTO(const char *foo, int bar), | ||
372 | TP_ARGS(foo, bar), | ||
373 | TP_CONDITION(!(bar % 8))); | ||
374 | |||
375 | |||
376 | DEFINE_EVENT_FN(foo_template, foo_with_template_fn, | ||
377 | TP_PROTO(const char *foo, int bar), | ||
378 | TP_ARGS(foo, bar), | ||
379 | foo_bar_reg, foo_bar_unreg); | ||
380 | |||
381 | /* | ||
382 | * Anytime two events share basically the same values and have | ||
383 | * the same output, use the DECLARE_EVENT_CLASS() and DEFINE_EVENT() | ||
384 | * when ever possible. | ||
385 | */ | ||
386 | |||
387 | /* | ||
388 | * If the event is similar to the DECLARE_EVENT_CLASS, but you need | ||
389 | * to have a different output, then use DEFINE_EVENT_PRINT() which | ||
390 | * lets you override the TP_printk() of the class. | ||
391 | */ | ||
392 | |||
393 | DEFINE_EVENT_PRINT(foo_template, foo_with_template_print, | ||
394 | TP_PROTO(const char *foo, int bar), | ||
395 | TP_ARGS(foo, bar), | ||
396 | TP_printk("bar %s %d", __get_str(foo), __entry->bar)); | ||
397 | |||
96 | #endif | 398 | #endif |
97 | 399 | ||
98 | /***** NOTICE! The #if protection ends here. *****/ | 400 | /***** NOTICE! The #if protection ends here. *****/ |