~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/user_events/dyn_test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * User Events Dyn Events Test Program
  4  *
  5  * Copyright (c) 2021 Beau Belgrave <beaub@linux.microsoft.com>
  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 }
295 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php