brintos

brintos / linux-shallow public Read only

0
0
Text · 6.1 KiB · bdf9ab1 Raw
295 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * User Events Dyn Events Test Program4 *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 20const char *dyn_file = "/sys/kernel/tracing/dynamic_events";21const char *abi_file = "/sys/kernel/tracing/user_events_data";22const char *enable_file = "/sys/kernel/tracing/events/user_events/__test_event/enable";23 24static 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 39static 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 56static 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 72static 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 83static 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	else97		ret = -1;98 99	close(fd);100 101	if (ret == 0)102		event_delete();103 104	return ret;105}106 107static 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 133static 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 145static 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;168cleanup: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) \180do { \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) \187do { \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 197FIXTURE(user) {198	int check;199	bool umount;200};201 202FIXTURE_SETUP(user) {203	USER_EVENT_FIXTURE_SETUP(return, self->umount);204}205 206FIXTURE_TEARDOWN(user) {207	USER_EVENT_FIXTURE_TEARDOWN(self->umount);208 209	wait_for_delete();210}211 212TEST_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 236TEST_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 244TEST_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 253TEST_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 291int main(int argc, char **argv)292{293	return test_harness_run(argc, argv);294}295