summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_vnode.c
diff options
context:
space:
mode:
authorthorpej <thorpej@NetBSD.org>2022-08-05 05:20:39 +0000
committerthorpej <thorpej@NetBSD.org>2022-08-05 05:20:39 +0000
commit80c847fb084fa65c7d4e85f583d37db62ed4f75d (patch)
tree690db7da9e52882cda2fdeaf410c79d3ec07b2d8 /sys/kern/vfs_vnode.c
parenta3cd42a2fe5818649eb2c492c43a17aa8cc4a301 (diff)
In vcache_reclaim(), post NOTE_REVOKE immediately after changing the
vnode state to VS_RECLAIMING, before we actually call VOP_RECLAIM(), which will release the reference on the lower node of a stacked FS vnode, which is likely to free the upper node's v_klist backing store. Acquire the vnode interlock when checking for kevent interest now, because the vp->v_klist pointer is now volatile. PR kern/56950
Diffstat (limited to 'sys/kern/vfs_vnode.c')
-rw-r--r--sys/kern/vfs_vnode.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/sys/kern/vfs_vnode.c b/sys/kern/vfs_vnode.c
index 35fee856840..0b6c12be101 100644
--- a/sys/kern/vfs_vnode.c
+++ b/sys/kern/vfs_vnode.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_vnode.c,v 1.144 2022/07/18 04:30:30 thorpej Exp $ */
+/* $NetBSD: vfs_vnode.c,v 1.145 2022/08/05 05:20:39 thorpej Exp $ */
/*-
* Copyright (c) 1997-2011, 2019, 2020 The NetBSD Foundation, Inc.
@@ -148,7 +148,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.144 2022/07/18 04:30:30 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.145 2022/08/05 05:20:39 thorpej Exp $");
#ifdef _KERNEL_OPT
#include "opt_pax.h"
@@ -1455,8 +1455,7 @@ vcache_free(vnode_impl_t *vip)
mutex_obj_free(vp->v_interlock);
rw_destroy(&vip->vi_lock);
uvm_obj_destroy(&vp->v_uobj, true);
- KASSERT(vp->v_klist == &vip->vi_klist ||
- SLIST_EMPTY(&vip->vi_klist.vk_klist));
+ KASSERT(vp->v_klist == &vip->vi_klist);
klist_fini(&vip->vi_klist.vk_klist);
cv_destroy(&vp->v_cv);
cache_vnode_fini(vp);
@@ -1830,6 +1829,19 @@ vcache_reclaim(vnode_t *vp)
* while we clean it out.
*/
VSTATE_CHANGE(vp, VS_BLOCKED, VS_RECLAIMING);
+
+ /*
+ * Send NOTE_REVOKE now, before we call VOP_RECLAIM(),
+ * because VOP_RECLAIM() could cause vp->v_klist to
+ * become invalid. Don't check for interest in NOTE_REVOKE
+ * here; it's always posted because it sets EV_EOF.
+ *
+ * Once it's been posted, reset vp->v_klist to point to
+ * our own local storage, in case we were sharing with
+ * someone else.
+ */
+ KNOTE(&vp->v_klist->vk_klist, NOTE_REVOKE);
+ vp->v_klist = &vip->vi_klist;
mutex_exit(vp->v_interlock);
rw_enter(vp->v_uobj.vmobjlock, RW_WRITER);
@@ -1916,11 +1928,6 @@ vcache_reclaim(vnode_t *vp)
vp->v_op = dead_vnodeop_p;
VSTATE_CHANGE(vp, VS_RECLAIMING, VS_RECLAIMED);
vp->v_tag = VT_NON;
- /*
- * Don't check for interest in NOTE_REVOKE; it's always posted
- * because it sets EV_EOF.
- */
- KNOTE(&vp->v_klist->vk_klist, NOTE_REVOKE);
mutex_exit(vp->v_interlock);
/*