Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Oct 2021 07:44:25 GMT
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 7259ca31048e - main - fifos: delegate unhandled kqueue filters to underlying filesystem
Message-ID:  <202110120744.19C7iPe1009454@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=7259ca31048e5ced8e7f90657a3d7084aeafdf51

commit 7259ca31048e5ced8e7f90657a3d7084aeafdf51
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2021-10-02 05:23:03 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2021-10-12 07:43:07 +0000

    fifos: delegate unhandled kqueue filters to underlying filesystem
    
    This gives the vfs layer a chance to provide handling for EVFILT_VNODE,
    for instance.  Change pipe_specops to use the default vop_kqfilter to
    accommodate fifoops that don't specify the method (i.e. all in-tree).
    
    Based on a patch by Jan Kokemüller.
    
    PR:             225934
    Reviewed by:    kib, markj (both pre-KASSERT)
    Differential Revision:  https://reviews.freebsd.org/D32271
---
 sys/fs/fifofs/fifo_vnops.c          |  1 -
 sys/kern/sys_pipe.c                 |  4 +++
 sys/kern/vfs_subr.c                 |  3 ++
 tests/sys/kqueue/libkqueue/common.h |  2 ++
 tests/sys/kqueue/libkqueue/vnode.c  | 59 +++++++++++++++++++++++++++++++++++++
 5 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index 1b941620b080..d9dc8eee8e60 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -83,7 +83,6 @@ struct vop_vector fifo_specops = {
 	.vop_create =		VOP_PANIC,
 	.vop_getattr =		VOP_EBADF,
 	.vop_ioctl =		VOP_PANIC,
-	.vop_kqfilter =		VOP_PANIC,
 	.vop_link =		VOP_PANIC,
 	.vop_mkdir =		VOP_PANIC,
 	.vop_mknod =		VOP_PANIC,
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 7bd7fea28e76..1d5d7329692e 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -1751,6 +1751,10 @@ pipe_kqfilter(struct file *fp, struct knote *kn)
 		cpipe = PIPE_PEER(cpipe);
 		break;
 	default:
+		if ((cpipe->pipe_type & PIPE_TYPE_NAMED) != 0) {
+			PIPE_UNLOCK(cpipe);
+			return (vnops.fo_kqfilter(fp, kn));
+		}
 		PIPE_UNLOCK(cpipe);
 		return (EINVAL);
 	}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 69ac73bd3954..d4b7ac71eb97 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -6172,6 +6172,9 @@ vfs_kqfilter(struct vop_kqfilter_args *ap)
 	struct knote *kn = ap->a_kn;
 	struct knlist *knl;
 
+	KASSERT(vp->v_type != VFIFO || (kn->kn_filter != EVFILT_READ &&
+	    kn->kn_filter != EVFILT_WRITE),
+	    ("READ/WRITE filter on a FIFO leaked through"));
 	switch (kn->kn_filter) {
 	case EVFILT_READ:
 		kn->kn_fop = &vfsread_filtops;
diff --git a/tests/sys/kqueue/libkqueue/common.h b/tests/sys/kqueue/libkqueue/common.h
index d621a8bf1e00..a92e544910ba 100644
--- a/tests/sys/kqueue/libkqueue/common.h
+++ b/tests/sys/kqueue/libkqueue/common.h
@@ -36,6 +36,8 @@
 #include <stdint.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include <sys/event.h>
diff --git a/tests/sys/kqueue/libkqueue/vnode.c b/tests/sys/kqueue/libkqueue/vnode.c
index 8f4311e90745..b6c0915b2654 100644
--- a/tests/sys/kqueue/libkqueue/vnode.c
+++ b/tests/sys/kqueue/libkqueue/vnode.c
@@ -64,6 +64,64 @@ test_kevent_vnode_note_delete(void)
     success();
 }
 
+static void
+test_kevent_vnode_note_delete_fifo(void)
+{
+    const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE, FIFO)";
+    const char *fifo_path = "./kqueue-fifo.tmp";
+    struct kevent kev;
+    int fd;
+    pid_t pid;
+
+    test_begin(test_id);
+
+    if (mkfifo(fifo_path, 0600) != 0)
+        err(1, "mkfifo");
+
+    pid = fork();
+    if (pid == -1)
+        err(1, "fork");
+
+    if (pid == 0) {
+        char buf[4];
+
+        fd = open(fifo_path, O_RDONLY);
+        if (fd == -1)
+            _exit(1);
+
+        while (read(fd, buf, sizeof(buf)) != 0) {
+        }
+
+        _exit(0);
+    }
+
+    sleep(1);
+    if (waitpid(pid, NULL, WNOHANG) == pid) {
+        unlink(fifo_path);
+        err(1, "open");
+    }
+
+    fd = open(fifo_path, O_WRONLY);
+    if (fd < 0) {
+        unlink(fifo_path);
+        err(1, "open");
+    }
+
+    EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
+    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) {
+        unlink(fifo_path);
+        err(1, "%s", test_id);
+    }
+
+    if (unlink(fifo_path) < 0)
+        err(1, "unlink");
+
+    kevent_cmp(&kev, kevent_get(kqfd));
+    close(fd);
+
+    success();
+}
+
 static void
 test_kevent_vnode_note_write(void)
 {
@@ -261,5 +319,6 @@ test_evfilt_vnode(void)
     test_kevent_vnode_note_attrib();
     test_kevent_vnode_note_rename();
     test_kevent_vnode_note_delete();
+    test_kevent_vnode_note_delete_fifo();
     close(kqfd);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202110120744.19C7iPe1009454>