This patch moves kernel locking a step deeper when attaching file event
filters, letting filt_fileattach() run without the kernel lock.

filt_fileattach() calls fp->f_ops->fo_kqfilter(). The f_ops field is
immutable, and the pointed fileops structs are constant.

There are five instances of fo_kqfilter: dmabuf_kqfilter,
kqueue_kqfilter, pipe_kqfilter, soo_kqfilter, and vn_kqfilter. Of these,
dmabuf_kqfilter has no side effects, and vn_kqfilter needs the kernel
lock to call the vnode operation. The rest should be MP-safe.

OK?

Index: kern/kern_event.c
===================================================================
RCS file: src/sys/kern/kern_event.c,v
retrieving revision 1.170
diff -u -p -r1.170 kern_event.c
--- kern/kern_event.c   6 Nov 2021 05:48:47 -0000       1.170
+++ kern/kern_event.c   11 Nov 2021 16:00:55 -0000
@@ -159,7 +160,7 @@ const struct filterops proc_filtops = {
 };
 
 const struct filterops file_filtops = {
-       .f_flags        = FILTEROP_ISFD,
+       .f_flags        = FILTEROP_ISFD | FILTEROP_MPSAFE,
        .f_attach       = filt_fileattach,
        .f_detach       = NULL,
        .f_event        = NULL,
Index: kern/vfs_vnops.c
===================================================================
RCS file: src/sys/kern/vfs_vnops.c,v
retrieving revision 1.118
diff -u -p -r1.118 vfs_vnops.c
--- kern/vfs_vnops.c    25 Oct 2021 10:24:54 -0000      1.118
+++ kern/vfs_vnops.c    11 Nov 2021 16:00:55 -0000
@@ -629,7 +629,12 @@ vn_closefile(struct file *fp, struct pro
 int
 vn_kqfilter(struct file *fp, struct knote *kn)
 {
-       return (VOP_KQFILTER(fp->f_data, fp->f_flag, kn));
+       int error;
+
+       KERNEL_LOCK();
+       error = VOP_KQFILTER(fp->f_data, fp->f_flag, kn);
+       KERNEL_UNLOCK();
+       return (error);
 }
 
 int

Reply via email to