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