Source-Changes-HG archive

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

[src/trunk]: src/sys/kern vput(): don't drop the vnode lock, carry the hold o...



details:   https://anonhg.NetBSD.org/src/rev/60b0f46a1314
branches:  trunk
changeset: 968324:60b0f46a1314
user:      ad <ad%NetBSD.org@localhost>
date:      Sun Jan 12 17:49:17 2020 +0000

description:
vput(): don't drop the vnode lock, carry the hold over into vrelel() which
might need it anyway.

diffstat:

 sys/kern/vfs_vnode.c |  95 ++++++++++++++++++++++++++++++---------------------
 1 files changed, 56 insertions(+), 39 deletions(-)

diffs (241 lines):

diff -r 5b727c272a87 -r 60b0f46a1314 sys/kern/vfs_vnode.c
--- a/sys/kern/vfs_vnode.c      Sun Jan 12 17:48:42 2020 +0000
+++ b/sys/kern/vfs_vnode.c      Sun Jan 12 17:49:17 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_vnode.c,v 1.106 2020/01/08 12:04:56 ad Exp $       */
+/*     $NetBSD: vfs_vnode.c,v 1.107 2020/01/12 17:49:17 ad Exp $       */
 
 /*-
  * Copyright (c) 1997-2011, 2019 The NetBSD Foundation, Inc.
@@ -146,7 +146,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.106 2020/01/08 12:04:56 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.107 2020/01/12 17:49:17 ad Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -175,8 +175,6 @@
 
 /* Flags to vrelel. */
 #define        VRELEL_ASYNC    0x0001  /* Always defer to vrele thread. */
-#define        VRELEL_FORCE    0x0002  /* Must always succeed. */
-#define        VRELEL_NOINACT  0x0004  /* Don't bother calling VOP_INACTIVE(). */
 
 #define        LRU_VRELE       0
 #define        LRU_FREE        1
@@ -213,7 +211,7 @@
 static void            vcache_init(void);
 static void            vcache_reinit(void);
 static void            vcache_reclaim(vnode_t *);
-static void            vrelel(vnode_t *, int);
+static void            vrelel(vnode_t *, int, int);
 static void            vdrain_thread(void *);
 static void            vnpanic(vnode_t *, const char *, ...)
     __printflike(2, 3);
@@ -530,8 +528,9 @@
                TAILQ_INSERT_TAIL(vip->vi_lrulisthd, vip, vi_lrulist);
                mutex_exit(&vdrain_lock);
 
+               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                mutex_enter(vp->v_interlock);
-               vrelel(vp, VRELEL_FORCE);
+               vrelel(vp, 0, LK_EXCLUSIVE);
 
                mutex_enter(&vdrain_lock);
        }
@@ -573,8 +572,9 @@
 
        if (vcache_vget(vp) == 0) {
                if (!vrecycle(vp)) {
+                       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                        mutex_enter(vp->v_interlock);
-                       vrelel(vp, VRELEL_FORCE);
+                       vrelel(vp, 0, LK_EXCLUSIVE);
                }
        }
        fstrans_done(mp);
@@ -612,8 +612,9 @@
        vdrain_retry = true;
        mutex_exit(&vdrain_lock);
 
+       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
        mutex_enter(vp->v_interlock);
-       vrelel(vp, VRELEL_FORCE);
+       vrelel(vp, 0, LK_EXCLUSIVE);
        fstrans_done(mp);
 
        mutex_enter(&vdrain_lock);
@@ -674,9 +675,16 @@
 void
 vput(vnode_t *vp)
 {
+       int lktype;
 
-       VOP_UNLOCK(vp);
-       vrele(vp);
+       if ((vp->v_vflag & VV_LOCKSWORK) == 0) {
+               lktype = LK_EXCLUSIVE;
+       } else {
+               lktype = VOP_ISLOCKED(vp);
+               KASSERT(lktype != LK_NONE);
+       }
+       mutex_enter(vp->v_interlock);
+       vrelel(vp, 0, lktype);
 }
 
 /*
@@ -684,10 +692,9 @@
  * routine and either return to freelist or free to the pool.
  */
 static void
-vrelel(vnode_t *vp, int flags)
+vrelel(vnode_t *vp, int flags, int lktype)
 {
        const bool async = ((flags & VRELEL_ASYNC) != 0);
-       const bool force = ((flags & VRELEL_FORCE) != 0);
        bool recycle, defer;
        int error;
 
@@ -703,6 +710,9 @@
         * and unlock.
         */
        if (vp->v_usecount > 1) {
+               if (lktype != LK_NONE) {
+                       VOP_UNLOCK(vp);
+               }
                vp->v_usecount--;
                mutex_exit(vp->v_interlock);
                return;
@@ -723,39 +733,42 @@
         * Defer vnode release to vdrain_thread if caller requests
         * it explicitly, is the pagedaemon or the lock failed.
         */
+       defer = false;
        if ((curlwp == uvm.pagedaemon_lwp) || async) {
                defer = true;
-       } else if (force) {
-               mutex_exit(vp->v_interlock);
-               error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-               defer = (error != 0);
-               mutex_enter(vp->v_interlock);
-       } else {
-               error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOWAIT);
-               defer = (error != 0);
+       } else if (lktype == LK_SHARED) {
+               /* Excellent chance of getting, if the last ref. */
+               error = vn_lock(vp, LK_UPGRADE | LK_RETRY |
+                   LK_NOWAIT);
+               if (error != 0) {
+                       defer = true;
+               } else {
+                       lktype = LK_EXCLUSIVE;
+               }
+       } else if (lktype == LK_NONE) {
+               /* Excellent chance of getting, if the last ref. */
+               error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY |
+                   LK_NOWAIT);
+               if (error != 0) {
+                       defer = true;
+               } else {
+                       lktype = LK_EXCLUSIVE;
+               }
        }
        KASSERT(mutex_owned(vp->v_interlock));
-       KASSERT(! (force && defer));
        if (defer) {
                /*
                 * Defer reclaim to the kthread; it's not safe to
                 * clean it here.  We donate it our last reference.
                 */
+               if (lktype != LK_NONE) {
+                       VOP_UNLOCK(vp);
+               }
                lru_requeue(vp, &lru_list[LRU_VRELE]);
                mutex_exit(vp->v_interlock);
                return;
        }
-
-       /*
-        * If the node got another reference while we
-        * released the interlock, don't try to inactivate it yet.
-        */
-       if (vp->v_usecount > 1) {
-               vp->v_usecount--;
-               VOP_UNLOCK(vp);
-               mutex_exit(vp->v_interlock);
-               return;
-       }
+       KASSERT(lktype == LK_EXCLUSIVE);
 
        /*
         * If not clean, deactivate the vnode, but preserve
@@ -839,7 +852,7 @@
 {
 
        mutex_enter(vp->v_interlock);
-       vrelel(vp, 0);
+       vrelel(vp, 0, LK_NONE);
 }
 
 /*
@@ -850,7 +863,7 @@
 {
 
        mutex_enter(vp->v_interlock);
-       vrelel(vp, VRELEL_ASYNC);
+       vrelel(vp, VRELEL_ASYNC, LK_NONE);
 }
 
 /*
@@ -921,7 +934,7 @@
        /* If the vnode is already clean we're done. */
        if (VSTATE_GET(vp) != VS_LOADED) {
                VSTATE_ASSERT(vp, VS_RECLAIMED);
-               vrelel(vp, 0);
+               vrelel(vp, 0, LK_NONE);
                return true;
        }
 
@@ -947,7 +960,7 @@
 
        KASSERT(vp->v_usecount == 1);
        vcache_reclaim(vp);
-       vrelel(vp, 0);
+       vrelel(vp, 0, LK_NONE);
 
        return true;
 }
@@ -1026,16 +1039,20 @@
 void
 vgone(vnode_t *vp)
 {
+       int lktype;
 
        KASSERT(vp->v_mount == dead_rootmount || fstrans_is_owner(vp->v_mount));
 
        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+       lktype = LK_EXCLUSIVE;
        mutex_enter(vp->v_interlock);
        VSTATE_WAIT_STABLE(vp);
-       if (VSTATE_GET(vp) == VS_LOADED)
+       if (VSTATE_GET(vp) == VS_LOADED) { 
                vcache_reclaim(vp);
+               lktype = LK_NONE;
+       }
        VSTATE_ASSERT(vp, VS_RECLAIMED);
-       vrelel(vp, 0);
+       vrelel(vp, 0, lktype);
 }
 
 static inline uint32_t
@@ -1164,7 +1181,7 @@
        vp->v_op = dead_vnodeop_p;
        VSTATE_CHANGE(vp, VS_LOADING, VS_RECLAIMED);
        mutex_exit(&vcache_lock);
-       vrelel(vp, 0);
+       vrelel(vp, 0, LK_NONE);
 }
 
 /*



Home | Main Index | Thread Index | Old Index