xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/kcmp/kcmp_test.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #define _GNU_SOURCE
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <stdio.h>
5*4882a593Smuzhiyun #include <stdlib.h>
6*4882a593Smuzhiyun #include <signal.h>
7*4882a593Smuzhiyun #include <limits.h>
8*4882a593Smuzhiyun #include <unistd.h>
9*4882a593Smuzhiyun #include <errno.h>
10*4882a593Smuzhiyun #include <string.h>
11*4882a593Smuzhiyun #include <fcntl.h>
12*4882a593Smuzhiyun #include <linux/unistd.h>
13*4882a593Smuzhiyun #include <linux/kcmp.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <sys/syscall.h>
16*4882a593Smuzhiyun #include <sys/types.h>
17*4882a593Smuzhiyun #include <sys/stat.h>
18*4882a593Smuzhiyun #include <sys/wait.h>
19*4882a593Smuzhiyun #include <sys/epoll.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #include "../kselftest.h"
22*4882a593Smuzhiyun 
sys_kcmp(int pid1,int pid2,int type,unsigned long fd1,unsigned long fd2)23*4882a593Smuzhiyun static long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);
26*4882a593Smuzhiyun }
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static const unsigned int duped_num = 64;
29*4882a593Smuzhiyun 
main(int argc,char ** argv)30*4882a593Smuzhiyun int main(int argc, char **argv)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun 	const char kpath[] = "kcmp-test-file";
33*4882a593Smuzhiyun 	struct kcmp_epoll_slot epoll_slot;
34*4882a593Smuzhiyun 	struct epoll_event ev;
35*4882a593Smuzhiyun 	int pid1, pid2;
36*4882a593Smuzhiyun 	int pipefd[2];
37*4882a593Smuzhiyun 	int fd1, fd2;
38*4882a593Smuzhiyun 	int epollfd;
39*4882a593Smuzhiyun 	int status;
40*4882a593Smuzhiyun 	int fddup;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	fd1 = open(kpath, O_RDWR | O_CREAT | O_TRUNC, 0644);
43*4882a593Smuzhiyun 	pid1 = getpid();
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	if (fd1 < 0) {
46*4882a593Smuzhiyun 		perror("Can't create file");
47*4882a593Smuzhiyun 		ksft_exit_fail();
48*4882a593Smuzhiyun 	}
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	if (pipe(pipefd)) {
51*4882a593Smuzhiyun 		perror("Can't create pipe");
52*4882a593Smuzhiyun 		ksft_exit_fail();
53*4882a593Smuzhiyun 	}
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	epollfd = epoll_create1(0);
56*4882a593Smuzhiyun 	if (epollfd < 0) {
57*4882a593Smuzhiyun 		perror("epoll_create1 failed");
58*4882a593Smuzhiyun 		ksft_exit_fail();
59*4882a593Smuzhiyun 	}
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	memset(&ev, 0xff, sizeof(ev));
62*4882a593Smuzhiyun 	ev.events = EPOLLIN | EPOLLOUT;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) {
65*4882a593Smuzhiyun 		perror("epoll_ctl failed");
66*4882a593Smuzhiyun 		ksft_exit_fail();
67*4882a593Smuzhiyun 	}
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	fddup = dup2(pipefd[1], duped_num);
70*4882a593Smuzhiyun 	if (fddup < 0) {
71*4882a593Smuzhiyun 		perror("dup2 failed");
72*4882a593Smuzhiyun 		ksft_exit_fail();
73*4882a593Smuzhiyun 	}
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) {
76*4882a593Smuzhiyun 		perror("epoll_ctl failed");
77*4882a593Smuzhiyun 		ksft_exit_fail();
78*4882a593Smuzhiyun 	}
79*4882a593Smuzhiyun 	close(fddup);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	pid2 = fork();
82*4882a593Smuzhiyun 	if (pid2 < 0) {
83*4882a593Smuzhiyun 		perror("fork failed");
84*4882a593Smuzhiyun 		ksft_exit_fail();
85*4882a593Smuzhiyun 	}
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (!pid2) {
88*4882a593Smuzhiyun 		int pid2 = getpid();
89*4882a593Smuzhiyun 		int ret;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 		fd2 = open(kpath, O_RDWR, 0644);
92*4882a593Smuzhiyun 		if (fd2 < 0) {
93*4882a593Smuzhiyun 			perror("Can't open file");
94*4882a593Smuzhiyun 			ksft_exit_fail();
95*4882a593Smuzhiyun 		}
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 		/* An example of output and arguments */
98*4882a593Smuzhiyun 		printf("pid1: %6d pid2: %6d FD: %2ld FILES: %2ld VM: %2ld "
99*4882a593Smuzhiyun 		       "FS: %2ld SIGHAND: %2ld IO: %2ld SYSVSEM: %2ld "
100*4882a593Smuzhiyun 		       "INV: %2ld\n",
101*4882a593Smuzhiyun 		       pid1, pid2,
102*4882a593Smuzhiyun 		       sys_kcmp(pid1, pid2, KCMP_FILE,		fd1, fd2),
103*4882a593Smuzhiyun 		       sys_kcmp(pid1, pid2, KCMP_FILES,		0, 0),
104*4882a593Smuzhiyun 		       sys_kcmp(pid1, pid2, KCMP_VM,		0, 0),
105*4882a593Smuzhiyun 		       sys_kcmp(pid1, pid2, KCMP_FS,		0, 0),
106*4882a593Smuzhiyun 		       sys_kcmp(pid1, pid2, KCMP_SIGHAND,	0, 0),
107*4882a593Smuzhiyun 		       sys_kcmp(pid1, pid2, KCMP_IO,		0, 0),
108*4882a593Smuzhiyun 		       sys_kcmp(pid1, pid2, KCMP_SYSVSEM,	0, 0),
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 			/* This one should fail */
111*4882a593Smuzhiyun 		       sys_kcmp(pid1, pid2, KCMP_TYPES + 1,	0, 0));
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 		/* This one should return same fd */
114*4882a593Smuzhiyun 		ret = sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd1);
115*4882a593Smuzhiyun 		if (ret) {
116*4882a593Smuzhiyun 			printf("FAIL: 0 expected but %d returned (%s)\n",
117*4882a593Smuzhiyun 				ret, strerror(errno));
118*4882a593Smuzhiyun 			ksft_inc_fail_cnt();
119*4882a593Smuzhiyun 			ret = -1;
120*4882a593Smuzhiyun 		} else {
121*4882a593Smuzhiyun 			printf("PASS: 0 returned as expected\n");
122*4882a593Smuzhiyun 			ksft_inc_pass_cnt();
123*4882a593Smuzhiyun 		}
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 		/* Compare with self */
126*4882a593Smuzhiyun 		ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0);
127*4882a593Smuzhiyun 		if (ret) {
128*4882a593Smuzhiyun 			printf("FAIL: 0 expected but %d returned (%s)\n",
129*4882a593Smuzhiyun 				ret, strerror(errno));
130*4882a593Smuzhiyun 			ksft_inc_fail_cnt();
131*4882a593Smuzhiyun 			ret = -1;
132*4882a593Smuzhiyun 		} else {
133*4882a593Smuzhiyun 			printf("PASS: 0 returned as expected\n");
134*4882a593Smuzhiyun 			ksft_inc_pass_cnt();
135*4882a593Smuzhiyun 		}
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 		/* Compare epoll target */
138*4882a593Smuzhiyun 		epoll_slot = (struct kcmp_epoll_slot) {
139*4882a593Smuzhiyun 			.efd	= epollfd,
140*4882a593Smuzhiyun 			.tfd	= duped_num,
141*4882a593Smuzhiyun 			.toff	= 0,
142*4882a593Smuzhiyun 		};
143*4882a593Smuzhiyun 		ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1],
144*4882a593Smuzhiyun 			       (unsigned long)(void *)&epoll_slot);
145*4882a593Smuzhiyun 		if (ret) {
146*4882a593Smuzhiyun 			printf("FAIL: 0 expected but %d returned (%s)\n",
147*4882a593Smuzhiyun 				ret, strerror(errno));
148*4882a593Smuzhiyun 			ksft_inc_fail_cnt();
149*4882a593Smuzhiyun 			ret = -1;
150*4882a593Smuzhiyun 		} else {
151*4882a593Smuzhiyun 			printf("PASS: 0 returned as expected\n");
152*4882a593Smuzhiyun 			ksft_inc_pass_cnt();
153*4882a593Smuzhiyun 		}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 		ksft_print_cnts();
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 		if (ret)
158*4882a593Smuzhiyun 			ksft_exit_fail();
159*4882a593Smuzhiyun 		else
160*4882a593Smuzhiyun 			ksft_exit_pass();
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	waitpid(pid2, &status, P_ALL);
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	return ksft_exit_pass();
166*4882a593Smuzhiyun }
167