Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kqueue/libkqueue/vnode.c
39566 views
1
/*
2
* Copyright (c) 2009 Mark Heily <[email protected]>
3
*
4
* Permission to use, copy, modify, and distribute this software for any
5
* purpose with or without fee is hereby granted, provided that the above
6
* copyright notice and this permission notice appear in all copies.
7
*
8
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
*/
16
17
#include "common.h"
18
19
int vnode_fd;
20
21
static void
22
test_kevent_vnode_add(void)
23
{
24
const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)";
25
const char *testfile = "./kqueue-test.tmp";
26
struct kevent kev;
27
28
test_begin(test_id);
29
30
system("touch ./kqueue-test.tmp");
31
vnode_fd = open(testfile, O_RDONLY);
32
if (vnode_fd < 0)
33
err(1, "open of %s", testfile);
34
else
35
printf("vnode_fd = %d\n", vnode_fd);
36
37
EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD,
38
NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL);
39
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
40
err(1, "%s", test_id);
41
42
success();
43
}
44
45
static void
46
test_kevent_vnode_note_delete(void)
47
{
48
const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)";
49
struct kevent kev;
50
51
test_begin(test_id);
52
53
EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
54
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
55
err(1, "%s", test_id);
56
57
if (unlink("./kqueue-test.tmp") < 0)
58
err(1, "unlink");
59
60
kevent_cmp(&kev, kevent_get(kqfd));
61
62
success();
63
}
64
65
static void
66
test_kevent_vnode_note_delete_fifo(void)
67
{
68
const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE, FIFO)";
69
const char *fifo_path = "./kqueue-fifo.tmp";
70
struct kevent kev;
71
int fd;
72
pid_t pid;
73
74
test_begin(test_id);
75
76
if (mkfifo(fifo_path, 0600) != 0)
77
err(1, "mkfifo");
78
79
pid = fork();
80
if (pid == -1)
81
err(1, "fork");
82
83
if (pid == 0) {
84
char buf[4];
85
86
fd = open(fifo_path, O_RDONLY);
87
if (fd == -1)
88
_exit(1);
89
90
while (read(fd, buf, sizeof(buf)) != 0) {
91
}
92
93
_exit(0);
94
}
95
96
sleep(1);
97
if (waitpid(pid, NULL, WNOHANG) == pid) {
98
unlink(fifo_path);
99
err(1, "open");
100
}
101
102
fd = open(fifo_path, O_WRONLY);
103
if (fd < 0) {
104
unlink(fifo_path);
105
err(1, "open");
106
}
107
108
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
109
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) {
110
unlink(fifo_path);
111
err(1, "%s", test_id);
112
}
113
114
if (unlink(fifo_path) < 0)
115
err(1, "unlink");
116
117
kevent_cmp(&kev, kevent_get(kqfd));
118
close(fd);
119
120
success();
121
}
122
123
static void
124
test_kevent_vnode_note_write(void)
125
{
126
const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)";
127
struct kevent kev;
128
129
test_begin(test_id);
130
131
EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL);
132
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
133
err(1, "%s", test_id);
134
135
if (system("echo hello >> ./kqueue-test.tmp") < 0)
136
err(1, "system");
137
138
/* BSD kqueue adds NOTE_EXTEND even though it was not requested */
139
/* BSD kqueue removes EV_ENABLE */
140
kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue
141
kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue
142
kevent_cmp(&kev, kevent_get(kqfd));
143
144
success();
145
}
146
147
static void
148
test_kevent_vnode_note_attrib(void)
149
{
150
const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)";
151
struct kevent kev;
152
int nfds;
153
154
test_begin(test_id);
155
156
EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
157
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
158
err(1, "%s", test_id);
159
160
if (system("touch ./kqueue-test.tmp") < 0)
161
err(1, "system");
162
163
nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
164
if (nfds < 1)
165
err(1, "%s", test_id);
166
if (kev.ident != (uintptr_t)vnode_fd ||
167
kev.filter != EVFILT_VNODE ||
168
kev.fflags != NOTE_ATTRIB)
169
err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
170
test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
171
172
success();
173
}
174
175
static void
176
test_kevent_vnode_note_rename(void)
177
{
178
const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)";
179
struct kevent kev;
180
int nfds;
181
182
test_begin(test_id);
183
184
EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL);
185
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
186
err(1, "%s", test_id);
187
188
if (system("mv ./kqueue-test.tmp ./kqueue-test2.tmp") < 0)
189
err(1, "system");
190
191
nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
192
if (nfds < 1)
193
err(1, "%s", test_id);
194
if (kev.ident != (uintptr_t)vnode_fd ||
195
kev.filter != EVFILT_VNODE ||
196
kev.fflags != NOTE_RENAME)
197
err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
198
test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
199
200
if (system("mv ./kqueue-test2.tmp ./kqueue-test.tmp") < 0)
201
err(1, "system");
202
203
success();
204
}
205
206
static void
207
test_kevent_vnode_del(void)
208
{
209
const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)";
210
struct kevent kev;
211
212
test_begin(test_id);
213
214
EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
215
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
216
err(1, "%s", test_id);
217
218
success();
219
}
220
221
static void
222
test_kevent_vnode_disable_and_enable(void)
223
{
224
const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)";
225
struct kevent kev;
226
int nfds;
227
228
test_begin(test_id);
229
230
test_no_kevents();
231
232
/* Add the watch and immediately disable it */
233
EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
234
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
235
err(1, "%s", test_id);
236
kev.flags = EV_DISABLE;
237
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
238
err(1, "%s", test_id);
239
240
/* Confirm that the watch is disabled */
241
if (system("touch ./kqueue-test.tmp") < 0)
242
err(1, "system");
243
test_no_kevents();
244
245
/* Re-enable and check again */
246
kev.flags = EV_ENABLE;
247
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
248
err(1, "%s", test_id);
249
if (system("touch ./kqueue-test.tmp") < 0)
250
err(1, "system");
251
nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
252
if (nfds < 1)
253
err(1, "%s", test_id);
254
if (kev.ident != (uintptr_t)vnode_fd ||
255
kev.filter != EVFILT_VNODE ||
256
kev.fflags != NOTE_ATTRIB)
257
err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
258
test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
259
260
success();
261
}
262
263
#if HAVE_EV_DISPATCH
264
static void
265
test_kevent_vnode_dispatch(void)
266
{
267
const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)";
268
struct kevent kev;
269
int nfds;
270
271
test_begin(test_id);
272
273
test_no_kevents();
274
275
EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL);
276
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
277
err(1, "%s", test_id);
278
279
if (system("touch ./kqueue-test.tmp") < 0)
280
err(1, "system");
281
282
nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
283
if (nfds < 1)
284
err(1, "%s", test_id);
285
if (kev.ident != (uintptr_t)vnode_fd ||
286
kev.filter != EVFILT_VNODE ||
287
kev.fflags != NOTE_ATTRIB)
288
err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
289
test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
290
291
/* Confirm that the watch is disabled automatically */
292
puts("-- checking that watch is disabled");
293
if (system("touch ./kqueue-test.tmp") < 0)
294
err(1, "system");
295
test_no_kevents();
296
297
/* Delete the watch */
298
EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL);
299
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
300
err(1, "remove watch failed: %s", test_id);
301
302
success();
303
}
304
#endif /* HAVE_EV_DISPATCH */
305
306
void
307
test_evfilt_vnode(void)
308
{
309
kqfd = kqueue();
310
test_kevent_vnode_add();
311
test_kevent_vnode_del();
312
test_kevent_vnode_disable_and_enable();
313
#if HAVE_EV_DISPATCH
314
test_kevent_vnode_dispatch();
315
#endif
316
test_kevent_vnode_note_write();
317
test_kevent_vnode_note_attrib();
318
test_kevent_vnode_note_rename();
319
test_kevent_vnode_note_delete();
320
test_kevent_vnode_note_delete_fifo();
321
close(kqfd);
322
}
323
324