]> Git Repo - J-linux.git/blob - tools/testing/selftests/user_events/dyn_test.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / testing / selftests / user_events / dyn_test.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * User Events Dyn Events Test Program
4  *
5  * Copyright (c) 2021 Beau Belgrave <[email protected]>
6  */
7
8 #include <errno.h>
9 #include <linux/user_events.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16
17 #include "../kselftest_harness.h"
18 #include "user_events_selftests.h"
19
20 const char *dyn_file = "/sys/kernel/tracing/dynamic_events";
21 const char *abi_file = "/sys/kernel/tracing/user_events_data";
22 const char *enable_file = "/sys/kernel/tracing/events/user_events/__test_event/enable";
23
24 static int event_delete(void)
25 {
26         int fd = open(abi_file, O_RDWR);
27         int ret;
28
29         if (fd < 0)
30                 return -1;
31
32         ret = ioctl(fd, DIAG_IOCSDEL, "__test_event");
33
34         close(fd);
35
36         return ret;
37 }
38
39 static bool wait_for_delete(void)
40 {
41         int i;
42
43         for (i = 0; i < 1000; ++i) {
44                 int fd = open(enable_file, O_RDONLY);
45
46                 if (fd == -1)
47                         return true;
48
49                 close(fd);
50                 usleep(1000);
51         }
52
53         return false;
54 }
55
56 static int reg_event(int fd, int *check, int bit, const char *value)
57 {
58         struct user_reg reg = {0};
59
60         reg.size = sizeof(reg);
61         reg.name_args = (__u64)value;
62         reg.enable_bit = bit;
63         reg.enable_addr = (__u64)check;
64         reg.enable_size = sizeof(*check);
65
66         if (ioctl(fd, DIAG_IOCSREG, &reg) == -1)
67                 return -1;
68
69         return 0;
70 }
71
72 static int unreg_event(int fd, int *check, int bit)
73 {
74         struct user_unreg unreg = {0};
75
76         unreg.size = sizeof(unreg);
77         unreg.disable_bit = bit;
78         unreg.disable_addr = (__u64)check;
79
80         return ioctl(fd, DIAG_IOCSUNREG, &unreg);
81 }
82
83 static int parse_dyn(const char *value)
84 {
85         int fd = open(dyn_file, O_RDWR | O_APPEND);
86         int len = strlen(value);
87         int ret;
88
89         if (fd == -1)
90                 return -1;
91
92         ret = write(fd, value, len);
93
94         if (ret == len)
95                 ret = 0;
96         else
97                 ret = -1;
98
99         close(fd);
100
101         if (ret == 0)
102                 event_delete();
103
104         return ret;
105 }
106
107 static int parse_abi(int *check, const char *value)
108 {
109         int fd = open(abi_file, O_RDWR);
110         int ret;
111
112         if (fd == -1)
113                 return -1;
114
115         /* Until we have persist flags via dynamic events, use the base name */
116         if (value[0] != 'u' || value[1] != ':') {
117                 close(fd);
118                 return -1;
119         }
120
121         ret = reg_event(fd, check, 31, value + 2);
122
123         if (ret != -1) {
124                 if (unreg_event(fd, check, 31) == -1)
125                         printf("WARN: Couldn't unreg event\n");
126         }
127
128         close(fd);
129
130         return ret;
131 }
132
133 static int parse(int *check, const char *value)
134 {
135         int abi_ret = parse_abi(check, value);
136         int dyn_ret = parse_dyn(value);
137
138         /* Ensure both ABI and DYN parse the same way */
139         if (dyn_ret != abi_ret)
140                 return -1;
141
142         return dyn_ret;
143 }
144
145 static int check_match(int *check, const char *first, const char *second, bool *match)
146 {
147         int fd = open(abi_file, O_RDWR);
148         int ret = -1;
149
150         if (fd == -1)
151                 return -1;
152
153         if (reg_event(fd, check, 31, first) == -1)
154                 goto cleanup;
155
156         if (reg_event(fd, check, 30, second) == -1) {
157                 if (errno == EADDRINUSE) {
158                         /* Name is in use, with different fields */
159                         *match = false;
160                         ret = 0;
161                 }
162
163                 goto cleanup;
164         }
165
166         *match = true;
167         ret = 0;
168 cleanup:
169         unreg_event(fd, check, 31);
170         unreg_event(fd, check, 30);
171
172         close(fd);
173
174         wait_for_delete();
175
176         return ret;
177 }
178
179 #define TEST_MATCH(x, y) \
180 do { \
181         bool match; \
182         ASSERT_NE(-1, check_match(&self->check, x, y, &match)); \
183         ASSERT_EQ(true, match); \
184 } while (0)
185
186 #define TEST_NMATCH(x, y) \
187 do { \
188         bool match; \
189         ASSERT_NE(-1, check_match(&self->check, x, y, &match)); \
190         ASSERT_EQ(false, match); \
191 } while (0)
192
193 #define TEST_PARSE(x) ASSERT_NE(-1, parse(&self->check, x))
194
195 #define TEST_NPARSE(x) ASSERT_EQ(-1, parse(&self->check, x))
196
197 FIXTURE(user) {
198         int check;
199         bool umount;
200 };
201
202 FIXTURE_SETUP(user) {
203         USER_EVENT_FIXTURE_SETUP(return, self->umount);
204 }
205
206 FIXTURE_TEARDOWN(user) {
207         USER_EVENT_FIXTURE_TEARDOWN(self->umount);
208
209         wait_for_delete();
210 }
211
212 TEST_F(user, basic_types) {
213         /* All should work */
214         TEST_PARSE("u:__test_event u64 a");
215         TEST_PARSE("u:__test_event u32 a");
216         TEST_PARSE("u:__test_event u16 a");
217         TEST_PARSE("u:__test_event u8 a");
218         TEST_PARSE("u:__test_event char a");
219         TEST_PARSE("u:__test_event unsigned char a");
220         TEST_PARSE("u:__test_event int a");
221         TEST_PARSE("u:__test_event unsigned int a");
222         TEST_PARSE("u:__test_event short a");
223         TEST_PARSE("u:__test_event unsigned short a");
224         TEST_PARSE("u:__test_event char[20] a");
225         TEST_PARSE("u:__test_event unsigned char[20] a");
226         TEST_PARSE("u:__test_event char[0x14] a");
227         TEST_PARSE("u:__test_event unsigned char[0x14] a");
228         /* Bad size format should fail */
229         TEST_NPARSE("u:__test_event char[aa] a");
230         /* Large size should fail */
231         TEST_NPARSE("u:__test_event char[9999] a");
232         /* Long size string should fail */
233         TEST_NPARSE("u:__test_event char[0x0000000000001] a");
234 }
235
236 TEST_F(user, loc_types) {
237         /* All should work */
238         TEST_PARSE("u:__test_event __data_loc char[] a");
239         TEST_PARSE("u:__test_event __data_loc unsigned char[] a");
240         TEST_PARSE("u:__test_event __rel_loc char[] a");
241         TEST_PARSE("u:__test_event __rel_loc unsigned char[] a");
242 }
243
244 TEST_F(user, size_types) {
245         /* Should work */
246         TEST_PARSE("u:__test_event struct custom a 20");
247         /* Size not specified on struct should fail */
248         TEST_NPARSE("u:__test_event struct custom a");
249         /* Size specified on non-struct should fail */
250         TEST_NPARSE("u:__test_event char a 20");
251 }
252
253 TEST_F(user, matching) {
254         /* Single name matches */
255         TEST_MATCH("__test_event u32 a",
256                    "__test_event u32 a");
257
258         /* Multiple names match */
259         TEST_MATCH("__test_event u32 a; u32 b",
260                    "__test_event u32 a; u32 b");
261
262         /* Multiple names match with dangling ; */
263         TEST_MATCH("__test_event u32 a; u32 b",
264                    "__test_event u32 a; u32 b;");
265
266         /* Single name doesn't match */
267         TEST_NMATCH("__test_event u32 a",
268                     "__test_event u32 b");
269
270         /* Multiple names don't match */
271         TEST_NMATCH("__test_event u32 a; u32 b",
272                     "__test_event u32 b; u32 a");
273
274         /* Types don't match */
275         TEST_NMATCH("__test_event u64 a; u64 b",
276                     "__test_event u32 a; u32 b");
277
278         /* Struct name and size matches */
279         TEST_MATCH("__test_event struct my_struct a 20",
280                    "__test_event struct my_struct a 20");
281
282         /* Struct name don't match */
283         TEST_NMATCH("__test_event struct my_struct a 20",
284                     "__test_event struct my_struct b 20");
285
286         /* Struct size don't match */
287         TEST_NMATCH("__test_event struct my_struct a 20",
288                     "__test_event struct my_struct a 21");
289 }
290
291 int main(int argc, char **argv)
292 {
293         return test_harness_run(argc, argv);
294 }
This page took 0.043409 seconds and 4 git commands to generate.