vnode.c revision 359754
1/*
2 * Copyright (c) 2009 Mark Heily <mark@heily.com>
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 * $FreeBSD: stable/11/tests/sys/kqueue/libkqueue/vnode.c 359754 2020-04-09 20:38:36Z kevans $
17 */
18
19#include "common.h"
20
21int vnode_fd;
22
23void
24test_kevent_vnode_add(void)
25{
26    const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)";
27    const char *testfile = "./kqueue-test.tmp";
28    struct kevent kev;
29
30    test_begin(test_id);
31
32    system("touch ./kqueue-test.tmp");
33    vnode_fd = open(testfile, O_RDONLY);
34    if (vnode_fd < 0)
35        err(1, "open of %s", testfile);
36    else
37        printf("vnode_fd = %d\n", vnode_fd);
38
39    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD,
40            NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL);
41    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
42        err(1, "%s", test_id);
43
44    success();
45}
46
47void
48test_kevent_vnode_note_delete(void)
49{
50    const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)";
51    struct kevent kev;
52
53    test_begin(test_id);
54
55    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
56    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
57        err(1, "%s", test_id);
58
59    if (unlink("./kqueue-test.tmp") < 0)
60        err(1, "unlink");
61
62    kevent_cmp(&kev, kevent_get(kqfd));
63
64    success();
65}
66
67void
68test_kevent_vnode_note_write(void)
69{
70    const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)";
71    struct kevent kev;
72
73    test_begin(test_id);
74
75    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL);
76    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
77        err(1, "%s", test_id);
78
79    if (system("echo hello >> ./kqueue-test.tmp") < 0)
80        err(1, "system");
81
82    /* BSD kqueue adds NOTE_EXTEND even though it was not requested */
83    /* BSD kqueue removes EV_ENABLE */
84    kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue
85    kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue
86    kevent_cmp(&kev, kevent_get(kqfd));
87
88    success();
89}
90
91void
92test_kevent_vnode_note_attrib(void)
93{
94    const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)";
95    struct kevent kev;
96    int nfds;
97
98    test_begin(test_id);
99
100    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
101    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
102        err(1, "%s", test_id);
103
104    if (system("touch ./kqueue-test.tmp") < 0)
105        err(1, "system");
106
107    nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
108    if (nfds < 1)
109        err(1, "%s", test_id);
110    if (kev.ident != vnode_fd ||
111            kev.filter != EVFILT_VNODE ||
112            kev.fflags != NOTE_ATTRIB)
113        err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
114                test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
115
116    success();
117}
118
119void
120test_kevent_vnode_note_rename(void)
121{
122    const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)";
123    struct kevent kev;
124    int nfds;
125
126    test_begin(test_id);
127
128    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL);
129    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
130        err(1, "%s", test_id);
131
132    if (system("mv ./kqueue-test.tmp ./kqueue-test2.tmp") < 0)
133        err(1, "system");
134
135    nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
136    if (nfds < 1)
137        err(1, "%s", test_id);
138    if (kev.ident != vnode_fd ||
139            kev.filter != EVFILT_VNODE ||
140            kev.fflags != NOTE_RENAME)
141        err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
142                test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
143
144    if (system("mv ./kqueue-test2.tmp ./kqueue-test.tmp") < 0)
145        err(1, "system");
146
147    success();
148}
149
150void
151test_kevent_vnode_del(void)
152{
153    const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)";
154    struct kevent kev;
155
156    test_begin(test_id);
157
158    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
159    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
160        err(1, "%s", test_id);
161
162    success();
163}
164
165void
166test_kevent_vnode_disable_and_enable(void)
167{
168    const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)";
169    struct kevent kev;
170    int nfds;
171
172    test_begin(test_id);
173
174    test_no_kevents();
175
176    /* Add the watch and immediately disable it */
177    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
178    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
179        err(1, "%s", test_id);
180    kev.flags = EV_DISABLE;
181    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
182        err(1, "%s", test_id);
183
184    /* Confirm that the watch is disabled */
185    if (system("touch ./kqueue-test.tmp") < 0)
186        err(1, "system");
187    test_no_kevents();
188
189    /* Re-enable and check again */
190    kev.flags = EV_ENABLE;
191    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
192        err(1, "%s", test_id);
193    if (system("touch ./kqueue-test.tmp") < 0)
194        err(1, "system");
195    nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
196    if (nfds < 1)
197        err(1, "%s", test_id);
198    if (kev.ident != vnode_fd ||
199            kev.filter != EVFILT_VNODE ||
200            kev.fflags != NOTE_ATTRIB)
201        err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
202                test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
203
204    success();
205}
206
207#if HAVE_EV_DISPATCH
208void
209test_kevent_vnode_dispatch(void)
210{
211    const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)";
212    struct kevent kev;
213    int nfds;
214
215    test_begin(test_id);
216
217    test_no_kevents();
218
219    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL);
220    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
221        err(1, "%s", test_id);
222
223    if (system("touch ./kqueue-test.tmp") < 0)
224        err(1, "system");
225
226    nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
227    if (nfds < 1)
228        err(1, "%s", test_id);
229    if (kev.ident != vnode_fd ||
230            kev.filter != EVFILT_VNODE ||
231            kev.fflags != NOTE_ATTRIB)
232        err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
233                test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
234
235    /* Confirm that the watch is disabled automatically */
236    puts("-- checking that watch is disabled");
237    if (system("touch ./kqueue-test.tmp") < 0)
238        err(1, "system");
239    test_no_kevents();
240
241    /* Delete the watch */
242    EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL);
243    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
244        err(1, "remove watch failed: %s", test_id);
245
246    success();
247}
248#endif 	/* HAVE_EV_DISPATCH */
249
250void
251test_evfilt_vnode()
252{
253    kqfd = kqueue();
254    test_kevent_vnode_add();
255    test_kevent_vnode_del();
256    test_kevent_vnode_disable_and_enable();
257#if HAVE_EV_DISPATCH
258    test_kevent_vnode_dispatch();
259#endif
260    test_kevent_vnode_note_write();
261    test_kevent_vnode_note_attrib();
262    test_kevent_vnode_note_rename();
263    test_kevent_vnode_note_delete();
264    close(kqfd);
265}
266