diff options
| author | thorpej <thorpej@NetBSD.org> | 2022-08-05 05:20:39 +0000 |
|---|---|---|
| committer | thorpej <thorpej@NetBSD.org> | 2022-08-05 05:20:39 +0000 |
| commit | 80c847fb084fa65c7d4e85f583d37db62ed4f75d (patch) | |
| tree | 690db7da9e52882cda2fdeaf410c79d3ec07b2d8 /sys/kern/vfs_vnode.c | |
| parent | a3cd42a2fe5818649eb2c492c43a17aa8cc4a301 (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.c | 25 |
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); /* |
