xref: /src/tests/sys/kqueue/libkqueue/vnode.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
160a396a4SRobert Watson /*
260a396a4SRobert Watson  * Copyright (c) 2009 Mark Heily <mark@heily.com>
360a396a4SRobert Watson  *
460a396a4SRobert Watson  * Permission to use, copy, modify, and distribute this software for any
560a396a4SRobert Watson  * purpose with or without fee is hereby granted, provided that the above
660a396a4SRobert Watson  * copyright notice and this permission notice appear in all copies.
760a396a4SRobert Watson  *
860a396a4SRobert Watson  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
960a396a4SRobert Watson  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1060a396a4SRobert Watson  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1160a396a4SRobert Watson  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1260a396a4SRobert Watson  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1360a396a4SRobert Watson  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1460a396a4SRobert Watson  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1560a396a4SRobert Watson  */
1660a396a4SRobert Watson 
1760a396a4SRobert Watson #include "common.h"
1860a396a4SRobert Watson 
1960a396a4SRobert Watson int vnode_fd;
2060a396a4SRobert Watson 
21c9c283bdSAlex Richardson static void
test_kevent_vnode_add(void)2260a396a4SRobert Watson test_kevent_vnode_add(void)
2360a396a4SRobert Watson {
2460a396a4SRobert Watson     const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)";
25f2ee07cfSJulio Merino     const char *testfile = "./kqueue-test.tmp";
2660a396a4SRobert Watson     struct kevent kev;
2760a396a4SRobert Watson 
2860a396a4SRobert Watson     test_begin(test_id);
2960a396a4SRobert Watson 
30f2ee07cfSJulio Merino     system("touch ./kqueue-test.tmp");
3160a396a4SRobert Watson     vnode_fd = open(testfile, O_RDONLY);
3260a396a4SRobert Watson     if (vnode_fd < 0)
3360a396a4SRobert Watson         err(1, "open of %s", testfile);
3460a396a4SRobert Watson     else
3560a396a4SRobert Watson         printf("vnode_fd = %d\n", vnode_fd);
3660a396a4SRobert Watson 
3760a396a4SRobert Watson     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD,
3860a396a4SRobert Watson             NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL);
3960a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
4060a396a4SRobert Watson         err(1, "%s", test_id);
4160a396a4SRobert Watson 
4260a396a4SRobert Watson     success();
4360a396a4SRobert Watson }
4460a396a4SRobert Watson 
45c9c283bdSAlex Richardson static void
test_kevent_vnode_note_delete(void)4660a396a4SRobert Watson test_kevent_vnode_note_delete(void)
4760a396a4SRobert Watson {
4860a396a4SRobert Watson     const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)";
4960a396a4SRobert Watson     struct kevent kev;
5060a396a4SRobert Watson 
5160a396a4SRobert Watson     test_begin(test_id);
5260a396a4SRobert Watson 
5360a396a4SRobert Watson     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
5460a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
5560a396a4SRobert Watson         err(1, "%s", test_id);
5660a396a4SRobert Watson 
57f2ee07cfSJulio Merino     if (unlink("./kqueue-test.tmp") < 0)
5860a396a4SRobert Watson         err(1, "unlink");
5960a396a4SRobert Watson 
6060a396a4SRobert Watson     kevent_cmp(&kev, kevent_get(kqfd));
6160a396a4SRobert Watson 
6260a396a4SRobert Watson     success();
6360a396a4SRobert Watson }
6460a396a4SRobert Watson 
65c9c283bdSAlex Richardson static void
test_kevent_vnode_note_delete_fifo(void)667259ca31SKyle Evans test_kevent_vnode_note_delete_fifo(void)
677259ca31SKyle Evans {
687259ca31SKyle Evans     const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE, FIFO)";
697259ca31SKyle Evans     const char *fifo_path = "./kqueue-fifo.tmp";
707259ca31SKyle Evans     struct kevent kev;
717259ca31SKyle Evans     int fd;
727259ca31SKyle Evans     pid_t pid;
737259ca31SKyle Evans 
747259ca31SKyle Evans     test_begin(test_id);
757259ca31SKyle Evans 
767259ca31SKyle Evans     if (mkfifo(fifo_path, 0600) != 0)
777259ca31SKyle Evans         err(1, "mkfifo");
787259ca31SKyle Evans 
797259ca31SKyle Evans     pid = fork();
807259ca31SKyle Evans     if (pid == -1)
817259ca31SKyle Evans         err(1, "fork");
827259ca31SKyle Evans 
837259ca31SKyle Evans     if (pid == 0) {
847259ca31SKyle Evans         char buf[4];
857259ca31SKyle Evans 
867259ca31SKyle Evans         fd = open(fifo_path, O_RDONLY);
877259ca31SKyle Evans         if (fd == -1)
887259ca31SKyle Evans             _exit(1);
897259ca31SKyle Evans 
907259ca31SKyle Evans         while (read(fd, buf, sizeof(buf)) != 0) {
917259ca31SKyle Evans         }
927259ca31SKyle Evans 
937259ca31SKyle Evans         _exit(0);
947259ca31SKyle Evans     }
957259ca31SKyle Evans 
967259ca31SKyle Evans     sleep(1);
977259ca31SKyle Evans     if (waitpid(pid, NULL, WNOHANG) == pid) {
987259ca31SKyle Evans         unlink(fifo_path);
997259ca31SKyle Evans         err(1, "open");
1007259ca31SKyle Evans     }
1017259ca31SKyle Evans 
1027259ca31SKyle Evans     fd = open(fifo_path, O_WRONLY);
1037259ca31SKyle Evans     if (fd < 0) {
1047259ca31SKyle Evans         unlink(fifo_path);
1057259ca31SKyle Evans         err(1, "open");
1067259ca31SKyle Evans     }
1077259ca31SKyle Evans 
1087259ca31SKyle Evans     EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
1097259ca31SKyle Evans     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) {
1107259ca31SKyle Evans         unlink(fifo_path);
1117259ca31SKyle Evans         err(1, "%s", test_id);
1127259ca31SKyle Evans     }
1137259ca31SKyle Evans 
1147259ca31SKyle Evans     if (unlink(fifo_path) < 0)
1157259ca31SKyle Evans         err(1, "unlink");
1167259ca31SKyle Evans 
1177259ca31SKyle Evans     kevent_cmp(&kev, kevent_get(kqfd));
1187259ca31SKyle Evans     close(fd);
1197259ca31SKyle Evans 
1207259ca31SKyle Evans     success();
1217259ca31SKyle Evans }
1227259ca31SKyle Evans 
1237259ca31SKyle Evans static void
test_kevent_vnode_note_write(void)12460a396a4SRobert Watson test_kevent_vnode_note_write(void)
12560a396a4SRobert Watson {
12660a396a4SRobert Watson     const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)";
12760a396a4SRobert Watson     struct kevent kev;
12860a396a4SRobert Watson 
12960a396a4SRobert Watson     test_begin(test_id);
13060a396a4SRobert Watson 
13160a396a4SRobert Watson     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL);
13260a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
13360a396a4SRobert Watson         err(1, "%s", test_id);
13460a396a4SRobert Watson 
135f2ee07cfSJulio Merino     if (system("echo hello >> ./kqueue-test.tmp") < 0)
13660a396a4SRobert Watson         err(1, "system");
13760a396a4SRobert Watson 
13860a396a4SRobert Watson     /* BSD kqueue adds NOTE_EXTEND even though it was not requested */
13960a396a4SRobert Watson     /* BSD kqueue removes EV_ENABLE */
14060a396a4SRobert Watson     kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue
14160a396a4SRobert Watson     kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue
14260a396a4SRobert Watson     kevent_cmp(&kev, kevent_get(kqfd));
14360a396a4SRobert Watson 
14460a396a4SRobert Watson     success();
14560a396a4SRobert Watson }
14660a396a4SRobert Watson 
147c9c283bdSAlex Richardson static void
test_kevent_vnode_note_attrib(void)14860a396a4SRobert Watson test_kevent_vnode_note_attrib(void)
14960a396a4SRobert Watson {
15060a396a4SRobert Watson     const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)";
15160a396a4SRobert Watson     struct kevent kev;
15260a396a4SRobert Watson     int nfds;
15360a396a4SRobert Watson 
15460a396a4SRobert Watson     test_begin(test_id);
15560a396a4SRobert Watson 
15660a396a4SRobert Watson     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
15760a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
15860a396a4SRobert Watson         err(1, "%s", test_id);
15960a396a4SRobert Watson 
160f2ee07cfSJulio Merino     if (system("touch ./kqueue-test.tmp") < 0)
16160a396a4SRobert Watson         err(1, "system");
16260a396a4SRobert Watson 
16360a396a4SRobert Watson     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
16460a396a4SRobert Watson     if (nfds < 1)
16560a396a4SRobert Watson         err(1, "%s", test_id);
166c9c283bdSAlex Richardson     if (kev.ident != (uintptr_t)vnode_fd ||
16760a396a4SRobert Watson             kev.filter != EVFILT_VNODE ||
16860a396a4SRobert Watson             kev.fflags != NOTE_ATTRIB)
16960a396a4SRobert Watson         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
17060a396a4SRobert Watson                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
17160a396a4SRobert Watson 
17260a396a4SRobert Watson     success();
17360a396a4SRobert Watson }
17460a396a4SRobert Watson 
175c9c283bdSAlex Richardson static void
test_kevent_vnode_note_rename(void)17660a396a4SRobert Watson test_kevent_vnode_note_rename(void)
17760a396a4SRobert Watson {
17860a396a4SRobert Watson     const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)";
17960a396a4SRobert Watson     struct kevent kev;
18060a396a4SRobert Watson     int nfds;
18160a396a4SRobert Watson 
18260a396a4SRobert Watson     test_begin(test_id);
18360a396a4SRobert Watson 
18460a396a4SRobert Watson     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL);
18560a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
18660a396a4SRobert Watson         err(1, "%s", test_id);
18760a396a4SRobert Watson 
188f2ee07cfSJulio Merino     if (system("mv ./kqueue-test.tmp ./kqueue-test2.tmp") < 0)
18960a396a4SRobert Watson         err(1, "system");
19060a396a4SRobert Watson 
19160a396a4SRobert Watson     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
19260a396a4SRobert Watson     if (nfds < 1)
19360a396a4SRobert Watson         err(1, "%s", test_id);
194c9c283bdSAlex Richardson     if (kev.ident != (uintptr_t)vnode_fd ||
19560a396a4SRobert Watson             kev.filter != EVFILT_VNODE ||
19660a396a4SRobert Watson             kev.fflags != NOTE_RENAME)
19760a396a4SRobert Watson         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
19860a396a4SRobert Watson                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
19960a396a4SRobert Watson 
200f2ee07cfSJulio Merino     if (system("mv ./kqueue-test2.tmp ./kqueue-test.tmp") < 0)
20160a396a4SRobert Watson         err(1, "system");
20260a396a4SRobert Watson 
20360a396a4SRobert Watson     success();
20460a396a4SRobert Watson }
20560a396a4SRobert Watson 
206c9c283bdSAlex Richardson static void
test_kevent_vnode_del(void)20760a396a4SRobert Watson test_kevent_vnode_del(void)
20860a396a4SRobert Watson {
20960a396a4SRobert Watson     const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)";
21060a396a4SRobert Watson     struct kevent kev;
21160a396a4SRobert Watson 
21260a396a4SRobert Watson     test_begin(test_id);
21360a396a4SRobert Watson 
21460a396a4SRobert Watson     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
21560a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
21660a396a4SRobert Watson         err(1, "%s", test_id);
21760a396a4SRobert Watson 
21860a396a4SRobert Watson     success();
21960a396a4SRobert Watson }
22060a396a4SRobert Watson 
221c9c283bdSAlex Richardson static void
test_kevent_vnode_disable_and_enable(void)22260a396a4SRobert Watson test_kevent_vnode_disable_and_enable(void)
22360a396a4SRobert Watson {
22460a396a4SRobert Watson     const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)";
22560a396a4SRobert Watson     struct kevent kev;
22660a396a4SRobert Watson     int nfds;
22760a396a4SRobert Watson 
22860a396a4SRobert Watson     test_begin(test_id);
22960a396a4SRobert Watson 
23060a396a4SRobert Watson     test_no_kevents();
23160a396a4SRobert Watson 
23260a396a4SRobert Watson     /* Add the watch and immediately disable it */
23360a396a4SRobert Watson     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
23460a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
23560a396a4SRobert Watson         err(1, "%s", test_id);
23660a396a4SRobert Watson     kev.flags = EV_DISABLE;
23760a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
23860a396a4SRobert Watson         err(1, "%s", test_id);
23960a396a4SRobert Watson 
24060a396a4SRobert Watson     /* Confirm that the watch is disabled */
241f2ee07cfSJulio Merino     if (system("touch ./kqueue-test.tmp") < 0)
24260a396a4SRobert Watson         err(1, "system");
24360a396a4SRobert Watson     test_no_kevents();
24460a396a4SRobert Watson 
24560a396a4SRobert Watson     /* Re-enable and check again */
24660a396a4SRobert Watson     kev.flags = EV_ENABLE;
24760a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
24860a396a4SRobert Watson         err(1, "%s", test_id);
249f2ee07cfSJulio Merino     if (system("touch ./kqueue-test.tmp") < 0)
25060a396a4SRobert Watson         err(1, "system");
25160a396a4SRobert Watson     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
25260a396a4SRobert Watson     if (nfds < 1)
25360a396a4SRobert Watson         err(1, "%s", test_id);
254c9c283bdSAlex Richardson     if (kev.ident != (uintptr_t)vnode_fd ||
25560a396a4SRobert Watson             kev.filter != EVFILT_VNODE ||
25660a396a4SRobert Watson             kev.fflags != NOTE_ATTRIB)
25760a396a4SRobert Watson         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
25860a396a4SRobert Watson                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
25960a396a4SRobert Watson 
26060a396a4SRobert Watson     success();
26160a396a4SRobert Watson }
26260a396a4SRobert Watson 
26360a396a4SRobert Watson #if HAVE_EV_DISPATCH
264c9c283bdSAlex Richardson static void
test_kevent_vnode_dispatch(void)26560a396a4SRobert Watson test_kevent_vnode_dispatch(void)
26660a396a4SRobert Watson {
26760a396a4SRobert Watson     const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)";
26860a396a4SRobert Watson     struct kevent kev;
26960a396a4SRobert Watson     int nfds;
27060a396a4SRobert Watson 
27160a396a4SRobert Watson     test_begin(test_id);
27260a396a4SRobert Watson 
27360a396a4SRobert Watson     test_no_kevents();
27460a396a4SRobert Watson 
27560a396a4SRobert Watson     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL);
27660a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
27760a396a4SRobert Watson         err(1, "%s", test_id);
27860a396a4SRobert Watson 
279f2ee07cfSJulio Merino     if (system("touch ./kqueue-test.tmp") < 0)
28060a396a4SRobert Watson         err(1, "system");
28160a396a4SRobert Watson 
28260a396a4SRobert Watson     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
28360a396a4SRobert Watson     if (nfds < 1)
28460a396a4SRobert Watson         err(1, "%s", test_id);
285c9c283bdSAlex Richardson     if (kev.ident != (uintptr_t)vnode_fd ||
28660a396a4SRobert Watson             kev.filter != EVFILT_VNODE ||
28760a396a4SRobert Watson             kev.fflags != NOTE_ATTRIB)
28860a396a4SRobert Watson         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
28960a396a4SRobert Watson                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
29060a396a4SRobert Watson 
29160a396a4SRobert Watson     /* Confirm that the watch is disabled automatically */
29260a396a4SRobert Watson     puts("-- checking that watch is disabled");
293f2ee07cfSJulio Merino     if (system("touch ./kqueue-test.tmp") < 0)
29460a396a4SRobert Watson         err(1, "system");
29560a396a4SRobert Watson     test_no_kevents();
29660a396a4SRobert Watson 
29760a396a4SRobert Watson     /* Delete the watch */
29860a396a4SRobert Watson     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL);
29960a396a4SRobert Watson     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
30060a396a4SRobert Watson         err(1, "remove watch failed: %s", test_id);
30160a396a4SRobert Watson 
30260a396a4SRobert Watson     success();
30360a396a4SRobert Watson }
30460a396a4SRobert Watson #endif 	/* HAVE_EV_DISPATCH */
30560a396a4SRobert Watson 
30660a396a4SRobert Watson void
test_evfilt_vnode(void)307c9c283bdSAlex Richardson test_evfilt_vnode(void)
30860a396a4SRobert Watson {
30960a396a4SRobert Watson     kqfd = kqueue();
31060a396a4SRobert Watson     test_kevent_vnode_add();
31160a396a4SRobert Watson     test_kevent_vnode_del();
31260a396a4SRobert Watson     test_kevent_vnode_disable_and_enable();
31360a396a4SRobert Watson #if HAVE_EV_DISPATCH
31460a396a4SRobert Watson     test_kevent_vnode_dispatch();
31560a396a4SRobert Watson #endif
31660a396a4SRobert Watson     test_kevent_vnode_note_write();
31760a396a4SRobert Watson     test_kevent_vnode_note_attrib();
31860a396a4SRobert Watson     test_kevent_vnode_note_rename();
31960a396a4SRobert Watson     test_kevent_vnode_note_delete();
3207259ca31SKyle Evans     test_kevent_vnode_note_delete_fifo();
32160a396a4SRobert Watson     close(kqfd);
32260a396a4SRobert Watson }
323