Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/kcmp/kcmp_test.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0
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>
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>
19
#include <sys/epoll.h>
20
21
#include "../kselftest.h"
22
23
static long sys_kcmp(int pid1, int pid2, int type, unsigned long fd1, unsigned long fd2)
24
{
25
return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);
26
}
27
28
static const unsigned int duped_num = 64;
29
30
int main(int argc, char **argv)
31
{
32
const char kpath[] = "kcmp-test-file";
33
struct kcmp_epoll_slot epoll_slot;
34
struct epoll_event ev;
35
int pid1, pid2;
36
int pipefd[2];
37
int fd1, fd2;
38
int epollfd;
39
int status;
40
int fddup;
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");
47
ksft_exit_fail();
48
}
49
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
81
pid2 = fork();
82
if (pid2 < 0) {
83
perror("fork failed");
84
ksft_exit_fail();
85
}
86
87
if (!pid2) {
88
int pid2 = getpid();
89
int ret;
90
91
ksft_print_header();
92
ksft_set_plan(3);
93
94
fd2 = open(kpath, O_RDWR);
95
if (fd2 < 0) {
96
perror("Can't open file");
97
ksft_exit_fail();
98
}
99
100
/* An example of output and arguments */
101
printf("pid1: %6d pid2: %6d FD: %2ld FILES: %2ld VM: %2ld "
102
"FS: %2ld SIGHAND: %2ld IO: %2ld SYSVSEM: %2ld "
103
"INV: %2ld\n",
104
pid1, pid2,
105
sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd2),
106
sys_kcmp(pid1, pid2, KCMP_FILES, 0, 0),
107
sys_kcmp(pid1, pid2, KCMP_VM, 0, 0),
108
sys_kcmp(pid1, pid2, KCMP_FS, 0, 0),
109
sys_kcmp(pid1, pid2, KCMP_SIGHAND, 0, 0),
110
sys_kcmp(pid1, pid2, KCMP_IO, 0, 0),
111
sys_kcmp(pid1, pid2, KCMP_SYSVSEM, 0, 0),
112
113
/* This one should fail */
114
sys_kcmp(pid1, pid2, KCMP_TYPES + 1, 0, 0));
115
116
/* This one should return same fd */
117
ret = sys_kcmp(pid1, pid2, KCMP_FILE, fd1, fd1);
118
if (ret) {
119
printf("FAIL: 0 expected but %d returned (%s)\n",
120
ret, strerror(errno));
121
ksft_inc_fail_cnt();
122
ret = -1;
123
} else {
124
printf("PASS: 0 returned as expected\n");
125
ksft_inc_pass_cnt();
126
}
127
128
/* Compare with self */
129
ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0);
130
if (ret) {
131
printf("FAIL: 0 expected but %d returned (%s)\n",
132
ret, strerror(errno));
133
ksft_inc_fail_cnt();
134
ret = -1;
135
} else {
136
printf("PASS: 0 returned as expected\n");
137
ksft_inc_pass_cnt();
138
}
139
140
/* Compare epoll target */
141
epoll_slot = (struct kcmp_epoll_slot) {
142
.efd = epollfd,
143
.tfd = duped_num,
144
.toff = 0,
145
};
146
ret = sys_kcmp(pid1, pid1, KCMP_EPOLL_TFD, pipefd[1],
147
(unsigned long)(void *)&epoll_slot);
148
if (ret) {
149
printf("FAIL: 0 expected but %d returned (%s)\n",
150
ret, strerror(errno));
151
ksft_inc_fail_cnt();
152
ret = -1;
153
} else {
154
printf("PASS: 0 returned as expected\n");
155
ksft_inc_pass_cnt();
156
}
157
158
159
if (ret)
160
ksft_exit_fail();
161
else
162
ksft_exit_pass();
163
}
164
165
waitpid(pid2, &status, P_ALL);
166
167
return 0;
168
}
169
170