diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2020-02-05 17:03:14 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2020-02-05 17:03:14 +0000 |
commit | 92471b81023c503b7adaa22949e708bf98fc4b2b (patch) | |
tree | 085c6f88e86a1c2bb8b0ba7c1593b5fe8a1c658d /sys/kern | |
parent | 0c2e71d12ead5b088e54c5bb23b99bf102f7c7c6 (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.c | 14 | ||||
-rw-r--r-- | sys/kern/kern_event.c | 9 |
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(); } /* |