Source-Changes-HG archive

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

[src/trunk]: src/sys/kern Vrecycle() cannot wait for the vnode lock. On a le...



details:   https://anonhg.NetBSD.org/src/rev/2e01b32b14df
branches:  trunk
changeset: 821183:2e01b32b14df
user:      hannken <hannken%NetBSD.org@localhost>
date:      Fri Jan 27 10:50:10 2017 +0000

description:
Vrecycle() cannot wait for the vnode lock.  On a leaf file system this lock
will always succeed as we hold the last reference and prevent further
references.  On layered file systems waiting for the lock would open a can of
deadlocks as the lower vnodes may have other active references.

diffstat:

 sys/kern/vfs_mount.c |  41 +++++++++++++++++++++++------------------
 sys/kern/vfs_vnode.c |  18 ++++++++++++++----
 2 files changed, 37 insertions(+), 22 deletions(-)

diffs (113 lines):

diff -r bf4046fb5eb3 -r 2e01b32b14df sys/kern/vfs_mount.c
--- a/sys/kern/vfs_mount.c      Fri Jan 27 10:48:51 2017 +0000
+++ b/sys/kern/vfs_mount.c      Fri Jan 27 10:50:10 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_mount.c,v 1.46 2017/01/27 10:46:18 hannken Exp $   */
+/*     $NetBSD: vfs_mount.c,v 1.47 2017/01/27 10:50:10 hannken Exp $   */
 
 /*-
  * Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.46 2017/01/27 10:46:18 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.47 2017/01/27 10:50:10 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -551,30 +551,35 @@
 {
        vnode_t *vp;
        struct vnode_iterator *marker;
-       int busy, error, when;
+       int busy, error, when, retries = 2;
 
-       busy = error = when = 0;
+       do {
+               busy = error = when = 0;
 
-       /* First, flush out any vnode references from deferred vrele list. */
-       vfs_drainvnodes();
+               /*
+                * First, flush out any vnode references from the
+                * deferred vrele list.
+                */
+               vfs_drainvnodes();
 
-       vfs_vnode_iterator_init(mp, &marker);
+               vfs_vnode_iterator_init(mp, &marker);
 
-       while ((vp = vflushnext(marker, &when)) != NULL) {
-               error = vflush_one(vp, skipvp, flags);
-               if (error == EBUSY) {
-                       error = 0;
-                       busy++;
+               while ((vp = vflushnext(marker, &when)) != NULL) {
+                       error = vflush_one(vp, skipvp, flags);
+                       if (error == EBUSY) {
+                               error = 0;
+                               busy++;
 #ifdef DEBUG
-                       if (busyprt)
-                               vprint("vflush: busy vnode", vp);
+                               if (busyprt && retries == 0)
+                                       vprint("vflush: busy vnode", vp);
 #endif
-               } else if (error != 0) {
-                       break;
+                       } else if (error != 0) {
+                               break;
+                       }
                }
-       }
 
-       vfs_vnode_iterator_destroy(marker);
+               vfs_vnode_iterator_destroy(marker);
+       } while (error == 0 && busy > 0 && retries-- > 0);
 
        if (error)
                return error;
diff -r bf4046fb5eb3 -r 2e01b32b14df sys/kern/vfs_vnode.c
--- a/sys/kern/vfs_vnode.c      Fri Jan 27 10:48:51 2017 +0000
+++ b/sys/kern/vfs_vnode.c      Fri Jan 27 10:50:10 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_vnode.c,v 1.72 2017/01/11 09:08:58 hannken Exp $   */
+/*     $NetBSD: vfs_vnode.c,v 1.73 2017/01/27 10:50:10 hannken Exp $   */
 
 /*-
  * Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -156,7 +156,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.72 2017/01/11 09:08:58 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.73 2017/01/27 10:50:10 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -872,12 +872,22 @@
        VSTATE_CHANGE(vp, VS_ACTIVE, VS_BLOCKED);
        mutex_exit(vp->v_interlock);
 
-       error = vn_lock(vp, LK_EXCLUSIVE);
-       KASSERT(error == 0);
+       /*
+        * On a leaf file system this lock will always succeed as we hold
+        * the last reference and prevent further references.
+        * On layered file systems waiting for the lock would open a can of
+        * deadlocks as the lower vnodes may have other active references.
+        */
+       error = vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT);
 
        mutex_enter(vp->v_interlock);
        VSTATE_CHANGE(vp, VS_BLOCKED, VS_ACTIVE);
 
+       if (error) {
+               mutex_exit(vp->v_interlock);
+               return false;
+       }
+
        KASSERT(vp->v_usecount == 1);
        vcache_reclaim(vp);
        vrelel(vp, 0);



Home | Main Index | Thread Index | Old Index