summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2020-02-05 17:03:14 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2020-02-05 17:03:14 +0000
commit92471b81023c503b7adaa22949e708bf98fc4b2b (patch)
tree085c6f88e86a1c2bb8b0ba7c1593b5fe8a1c658d /sys/kern
parent0c2e71d12ead5b088e54c5bb23b99bf102f7c7c6 (diff)
Move kernel locking inside knote_fdclose() from finishdup() and
fdrelease(). This makes the upper layer of file descriptor closing free of KERNEL_LOCK() when the process does not use kqueue. The kernel locking around fdremove() and knote_fdclose() is no longer needed because kqueue_register() checks if there has been a race with file descriptor close. Moreover, the locking became ineffective against these races when filterops callbacks were allowed to sleep. OK anton@, mpi@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_descrip.c14
-rw-r--r--sys/kern/kern_event.c9
2 files changed, 8 insertions, 15 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 9a35e7c1e13..3a55ab9bfd1 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_descrip.c,v 1.197 2020/02/01 08:57:27 anton Exp $ */
+/* $OpenBSD: kern_descrip.c,v 1.198 2020/02/05 17:03:13 visa Exp $ */
/* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */
/*
@@ -667,9 +667,6 @@ finishdup(struct proc *p, struct file *fp, int old, int new,
fd_used(fdp, new);
}
- /* Prevent race with kevent. */
- KERNEL_LOCK();
-
/*
* Use `fd_fplock' to synchronize with fd_getfile() so that
* the function no longer creates a new reference to the old file.
@@ -686,8 +683,6 @@ finishdup(struct proc *p, struct file *fp, int old, int new,
closef(oldfp, p);
}
- KERNEL_UNLOCK();
-
return (0);
}
@@ -740,7 +735,6 @@ fdrelease(struct proc *p, int fd)
{
struct filedesc *fdp = p->p_fd;
struct file *fp;
- int error;
fdpassertlocked(fdp);
@@ -749,14 +743,10 @@ fdrelease(struct proc *p, int fd)
fdpunlock(fdp);
return (EBADF);
}
- /* Prevent race with kevent. */
- KERNEL_LOCK();
fdremove(fdp, fd);
knote_fdclose(p, fd);
fdpunlock(fdp);
- error = closef(fp, p);
- KERNEL_UNLOCK();
- return (error);
+ return (closef(fp, p));
}
/*
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index b84a674e38b..0e3e48452c8 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_event.c,v 1.121 2020/01/18 08:59:48 visa Exp $ */
+/* $OpenBSD: kern_event.c,v 1.122 2020/02/05 17:03:13 visa Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
@@ -1217,8 +1217,6 @@ knote_fdclose(struct proc *p, int fd)
struct kqueue *kq;
struct klist *list;
- KERNEL_ASSERT_LOCKED();
-
/*
* fdplock can be ignored if the file descriptor table is being freed
* because no other thread can access the fdp.
@@ -1226,6 +1224,10 @@ knote_fdclose(struct proc *p, int fd)
if (fdp->fd_refcnt != 0)
fdpassertlocked(fdp);
+ if (LIST_EMPTY(&fdp->fd_kqlist))
+ return;
+
+ KERNEL_LOCK();
LIST_FOREACH(kq, &fdp->fd_kqlist, kq_next) {
if (fd >= kq->kq_knlistsize)
continue;
@@ -1233,6 +1235,7 @@ knote_fdclose(struct proc *p, int fd)
list = &kq->kq_knlist[fd];
knote_remove(p, list);
}
+ KERNEL_UNLOCK();
}
/*