Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Fix the locking around EVFILT_FS. Previously, the code ...
details: https://anonhg.NetBSD.org/src/rev/d3cb64b5b5d7
branches: trunk
changeset: 1023822:d3cb64b5b5d7
user: thorpej <thorpej%NetBSD.org@localhost>
date: Sun Sep 26 21:29:38 2021 +0000
description:
Fix the locking around EVFILT_FS. Previously, the code would walk the
fs_klist and take the kqueue_misc_lock inside the event callback.
However, that list can be modified by the attach and detach callbacks,
which could result in the walker stepping right off a cliff.
Instead, we give the fs_klist it's own lock, and hold it while we
call knote(), using the NOTE_SUBMIT protocol. Also, fs_filtops
into vfs_syscalls.c so all of the locking logic is contained in one
file (there is precedence with sig_filtops). fs_filtops is now marked
MPSAFE.
diffstat:
sys/kern/kern_event.c | 56 ++---------------------------------
sys/kern/vfs_init.c | 7 +++-
sys/kern/vfs_syscalls.c | 75 +++++++++++++++++++++++++++++++++++++++++++++---
sys/sys/event.h | 6 +--
4 files changed, 80 insertions(+), 64 deletions(-)
diffs (263 lines):
diff -r 61b83b6461eb -r d3cb64b5b5d7 sys/kern/kern_event.c
--- a/sys/kern/kern_event.c Sun Sep 26 21:23:31 2021 +0000
+++ b/sys/kern/kern_event.c Sun Sep 26 21:29:38 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_event.c,v 1.123 2021/09/26 18:13:58 thorpej Exp $ */
+/* $NetBSD: kern_event.c,v 1.124 2021/09/26 21:29:38 thorpej Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.123 2021/09/26 18:13:58 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.124 2021/09/26 21:29:38 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -108,9 +108,6 @@
static int filt_timerattach(struct knote *);
static void filt_timerdetach(struct knote *);
static int filt_timer(struct knote *, long hint);
-static int filt_fsattach(struct knote *kn);
-static void filt_fsdetach(struct knote *kn);
-static int filt_fs(struct knote *kn, long hint);
static int filt_userattach(struct knote *);
static void filt_userdetach(struct knote *);
static int filt_user(struct knote *, long hint);
@@ -163,13 +160,6 @@
.f_event = filt_timer,
};
-static const struct filterops fs_filtops = {
- .f_flags = 0,
- .f_attach = filt_fsattach,
- .f_detach = filt_fsdetach,
- .f_event = filt_fs,
-};
-
static const struct filterops user_filtops = {
.f_flags = FILTEROP_MPSAFE,
.f_attach = filt_userattach,
@@ -184,7 +174,8 @@
#define KN_HASHSIZE 64 /* XXX should be tunable */
#define KN_HASH(val, mask) (((val) ^ (val >> 8)) & (mask))
-extern const struct filterops sig_filtops;
+extern const struct filterops fs_filtops; /* vfs_syscalls.c */
+extern const struct filterops sig_filtops; /* kern_sig.c */
#define KQ_FLUX_WAKEUP(kq) cv_broadcast(&kq->kq_cv)
@@ -823,45 +814,6 @@
return rv;
}
-/*
- * Filter event method for EVFILT_FS.
- */
-struct klist fs_klist = SLIST_HEAD_INITIALIZER(&fs_klist);
-
-static int
-filt_fsattach(struct knote *kn)
-{
-
- mutex_enter(&kqueue_misc_lock);
- kn->kn_flags |= EV_CLEAR;
- SLIST_INSERT_HEAD(&fs_klist, kn, kn_selnext);
- mutex_exit(&kqueue_misc_lock);
-
- return 0;
-}
-
-static void
-filt_fsdetach(struct knote *kn)
-{
-
- mutex_enter(&kqueue_misc_lock);
- SLIST_REMOVE(&fs_klist, kn, knote, kn_selnext);
- mutex_exit(&kqueue_misc_lock);
-}
-
-static int
-filt_fs(struct knote *kn, long hint)
-{
- int rv;
-
- mutex_enter(&kqueue_misc_lock);
- kn->kn_fflags |= hint;
- rv = (kn->kn_fflags != 0);
- mutex_exit(&kqueue_misc_lock);
-
- return rv;
-}
-
static int
filt_userattach(struct knote *kn)
{
diff -r 61b83b6461eb -r d3cb64b5b5d7 sys/kern/vfs_init.c
--- a/sys/kern/vfs_init.c Sun Sep 26 21:23:31 2021 +0000
+++ b/sys/kern/vfs_init.c Sun Sep 26 21:29:38 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_init.c,v 1.52 2021/02/04 21:07:06 jdolecek Exp $ */
+/* $NetBSD: vfs_init.c,v 1.53 2021/09/26 21:29:38 thorpej Exp $ */
/*-
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_init.c,v 1.52 2021/02/04 21:07:06 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_init.c,v 1.53 2021/09/26 21:29:38 thorpej Exp $");
#include <sys/param.h>
#include <sys/mount.h>
@@ -455,6 +455,9 @@
* included in the kernel.
*/
module_init_class(MODULE_CLASS_VFS);
+
+ extern kmutex_t fs_klist_lock;
+ mutex_init(&fs_klist_lock, MUTEX_DEFAULT, IPL_NONE);
}
/*
diff -r 61b83b6461eb -r d3cb64b5b5d7 sys/kern/vfs_syscalls.c
--- a/sys/kern/vfs_syscalls.c Sun Sep 26 21:23:31 2021 +0000
+++ b/sys/kern/vfs_syscalls.c Sun Sep 26 21:29:38 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_syscalls.c,v 1.552 2021/09/11 10:08:55 riastradh Exp $ */
+/* $NetBSD: vfs_syscalls.c,v 1.553 2021/09/26 21:29:38 thorpej Exp $ */
/*-
* Copyright (c) 2008, 2009, 2019, 2020 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.552 2021/09/11 10:08:55 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.553 2021/09/26 21:29:38 thorpej Exp $");
#ifdef _KERNEL_OPT
#include "opt_fileassoc.h"
@@ -165,6 +165,63 @@
const u_int nmountcompatnames = __arraycount(mountcompatnames);
+/*
+ * Filter event method for EVFILT_FS.
+ */
+static struct klist fs_klist = SLIST_HEAD_INITIALIZER(&fs_klist);
+kmutex_t fs_klist_lock;
+
+CTASSERT((NOTE_SUBMIT & VQ_MOUNT) == 0);
+CTASSERT((NOTE_SUBMIT & VQ_UNMOUNT) == 0);
+
+static int
+filt_fsattach(struct knote *kn)
+{
+ mutex_enter(&fs_klist_lock);
+ kn->kn_flags |= EV_CLEAR;
+ SLIST_INSERT_HEAD(&fs_klist, kn, kn_selnext);
+ mutex_exit(&fs_klist_lock);
+
+ return 0;
+}
+
+static void
+filt_fsdetach(struct knote *kn)
+{
+ mutex_enter(&fs_klist_lock);
+ SLIST_REMOVE(&fs_klist, kn, knote, kn_selnext);
+ mutex_exit(&fs_klist_lock);
+}
+
+static int
+filt_fs(struct knote *kn, long hint)
+{
+ int rv;
+
+ if (hint & NOTE_SUBMIT) {
+ KASSERT(mutex_owned(&fs_klist_lock));
+ kn->kn_fflags |= hint & ~NOTE_SUBMIT;
+ } else {
+ mutex_enter(&fs_klist_lock);
+ }
+
+ rv = (kn->kn_fflags != 0);
+
+ if ((hint & NOTE_SUBMIT) == 0) {
+ mutex_exit(&fs_klist_lock);
+ }
+
+ return rv;
+}
+
+/* referenced in kern_event.c */
+const struct filterops fs_filtops = {
+ .f_flags = FILTEROP_MPSAFE,
+ .f_attach = filt_fsattach,
+ .f_detach = filt_fsdetach,
+ .f_event = filt_fs,
+};
+
static int
fd_nameiat(struct lwp *l, int fdat, struct nameidata *ndp)
{
@@ -553,8 +610,11 @@
&data_len);
vfsopsrele = false;
}
- if (!error)
- KNOTE(&fs_klist, VQ_MOUNT);
+ if (!error) {
+ mutex_enter(&fs_klist_lock);
+ KNOTE(&fs_klist, NOTE_SUBMIT | VQ_MOUNT);
+ mutex_exit(&fs_klist_lock);
+ }
done:
if (vfsopsrele)
@@ -633,8 +693,11 @@
vrele(vp);
error = dounmount(mp, SCARG(uap, flags), l);
vfs_rele(mp);
- if (!error)
- KNOTE(&fs_klist, VQ_UNMOUNT);
+ if (!error) {
+ mutex_enter(&fs_klist_lock);
+ KNOTE(&fs_klist, NOTE_SUBMIT | VQ_UNMOUNT);
+ mutex_exit(&fs_klist_lock);
+ }
return error;
}
diff -r 61b83b6461eb -r d3cb64b5b5d7 sys/sys/event.h
--- a/sys/sys/event.h Sun Sep 26 21:23:31 2021 +0000
+++ b/sys/sys/event.h Sun Sep 26 21:29:38 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: event.h,v 1.42 2021/09/26 03:12:50 thorpej Exp $ */
+/* $NetBSD: event.h,v 1.43 2021/09/26 21:29:39 thorpej Exp $ */
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon%FreeBSD.org@localhost>
@@ -271,7 +271,7 @@
#define kn_data kn_kevent.data
};
-#include <sys/systm.h> /* for copyin_t */
+#include <sys/systm.h> /* for copyin_t */
struct lwp;
struct timespec;
@@ -307,8 +307,6 @@
int filt_seltrue(struct knote *, long);
extern const struct filterops seltrue_filtops;
-extern struct klist fs_klist; /* EVFILT_FS */
-
#else /* !_KERNEL */
#include <sys/cdefs.h>
Home |
Main Index |
Thread Index |
Old Index