Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys In vcache_reclaim(), post NOTE_REVOKE immediately after ...



details:   https://anonhg.NetBSD.org/src/rev/6a14e9f70fc3
branches:  trunk
changeset: 368789:6a14e9f70fc3
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Fri Aug 05 05:20:39 2022 +0000

description:
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:

 sys/kern/vfs_vnode.c |  25 ++++++++++++++++---------
 sys/sys/vnode.h      |  26 ++++++++++++++------------
 2 files changed, 30 insertions(+), 21 deletions(-)

diffs (107 lines):

diff -r 5042bc140e12 -r 6a14e9f70fc3 sys/kern/vfs_vnode.c
--- a/sys/kern/vfs_vnode.c      Thu Aug 04 21:11:52 2022 +0000
+++ b/sys/kern/vfs_vnode.c      Fri Aug 05 05:20:39 2022 +0000
@@ -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 @@
        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 @@
         * 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 @@
        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);
 
        /*
diff -r 5042bc140e12 -r 6a14e9f70fc3 sys/sys/vnode.h
--- a/sys/sys/vnode.h   Thu Aug 04 21:11:52 2022 +0000
+++ b/sys/sys/vnode.h   Fri Aug 05 05:20:39 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vnode.h,v 1.302 2022/07/18 04:30:30 thorpej Exp $      */
+/*     $NetBSD: vnode.h,v 1.303 2022/08/05 05:20:39 thorpej Exp $      */
 
 /*-
  * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
@@ -427,24 +427,26 @@
 /*
  * Macro to determine kevent interest on a vnode.
  */
-#define        VN_KEVENT_INTEREST(vp, n)                                       \
+#define        _VN_KEVENT_INTEREST(vp, n)                                      \
        (((vp)->v_klist->vk_interest & (n)) != 0)
 
+static inline bool
+VN_KEVENT_INTEREST(struct vnode *vp, long hint)
+{
+       mutex_enter(vp->v_interlock);
+       bool rv = _VN_KEVENT_INTEREST(vp, hint);
+       mutex_exit(vp->v_interlock);
+       return rv;
+}
+
 static inline void
 VN_KNOTE(struct vnode *vp, long hint)
 {
-       /*
-        * Testing for klist interest unlocked is fine here, as registering
-        * interest in vnode events is inherently racy with respect to other
-        * system activity anyway.  Having knotes attached to vnodes is
-        * actually incredibly rare, so we want to void having to take locks,
-        * etc. in what is the overwhelmingly common case.
-        */
-       if (__predict_false(VN_KEVENT_INTEREST(vp, hint))) {
-               mutex_enter(vp->v_interlock);
+       mutex_enter(vp->v_interlock);
+       if (__predict_false(_VN_KEVENT_INTEREST(vp, hint))) {
                knote(&vp->v_klist->vk_klist, hint);
-               mutex_exit(vp->v_interlock);
        }
+       mutex_exit(vp->v_interlock);
 }
 
 void   vn_knote_attach(struct vnode *, struct knote *);



Home | Main Index | Thread Index | Old Index