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