Source-Changes-HG archive

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

[src/trunk]: src/sys/kern Bring back Manuel Bouyers patch to resolve races be...



details:   https://anonhg.NetBSD.org/src/rev/6058f919c9f4
branches:  trunk
changeset: 782651:6058f919c9f4
user:      hannken <hannken%NetBSD.org@localhost>
date:      Mon Nov 12 11:00:07 2012 +0000

description:
Bring back Manuel Bouyers patch to resolve races between vget() and vrelel()
resulting in vget() returning dead vnodes.
It is impossible to resolve these races in vn_lock().

Needs pullup to NetBSD-6.

diffstat:

 sys/kern/vfs_vnode.c |  42 ++++++++++++++++++++++++++++++++++++++----
 sys/kern/vfs_vnops.c |  13 ++-----------
 2 files changed, 40 insertions(+), 15 deletions(-)

diffs (125 lines):

diff -r 1c93d8316266 -r 6058f919c9f4 sys/kern/vfs_vnode.c
--- a/sys/kern/vfs_vnode.c      Mon Nov 12 09:03:52 2012 +0000
+++ b/sys/kern/vfs_vnode.c      Mon Nov 12 11:00:07 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_vnode.c,v 1.16 2012/10/12 21:10:55 rmind Exp $     */
+/*     $NetBSD: vfs_vnode.c,v 1.17 2012/11/12 11:00:07 hannken Exp $   */
 
 /*-
  * Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -124,7 +124,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.16 2012/10/12 21:10:55 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.17 2012/11/12 11:00:07 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -564,6 +564,22 @@
                return ENOENT;
        }
 
+       if ((vp->v_iflag & VI_INACTNOW) != 0) {
+               /*
+                * if it's being desactived, wait for it to complete.
+                * Make sure to not return a clean vnode.
+                */
+                if ((flags & LK_NOWAIT) != 0) {
+                       vrelel(vp, 0);
+                       return EBUSY;
+               }
+               vwait(vp, VI_INACTNOW);
+               if ((vp->v_iflag & VI_CLEAN) != 0) {
+                       vrelel(vp, 0);
+                       return ENOENT;
+               }
+       }
+
        /*
         * Ok, we got it in good shape.  Just locking left.
         */
@@ -674,8 +690,12 @@
                        /* The pagedaemon can't wait around; defer. */
                        defer = true;
                } else if (curlwp == vrele_lwp) {
-                       /* We have to try harder. */
-                       vp->v_iflag &= ~VI_INACTREDO;
+                       /*
+                        * We have to try harder. But we can't sleep
+                        * with VI_INACTNOW as vget() may be waiting on it.
+                        */
+                       vp->v_iflag &= ~(VI_INACTREDO|VI_INACTNOW);
+                       cv_broadcast(&vp->v_cv);
                        mutex_exit(vp->v_interlock);
                        error = vn_lock(vp, LK_EXCLUSIVE);
                        if (error != 0) {
@@ -683,6 +703,18 @@
                                vnpanic(vp, "%s: unable to lock %p",
                                    __func__, vp);
                        }
+                       mutex_enter(vp->v_interlock);
+                       /*
+                        * if we did get another reference while
+                        * sleeping, don't try to inactivate it yet.
+                        */
+                       if (__predict_false(vtryrele(vp))) {
+                               VOP_UNLOCK(vp);
+                               mutex_exit(vp->v_interlock);
+                               return;
+                       }
+                       vp->v_iflag |= VI_INACTNOW;
+                       mutex_exit(vp->v_interlock);
                        defer = false;
                } else if ((vp->v_iflag & VI_LAYER) != 0) {
                        /* 
@@ -718,6 +750,7 @@
                        if (++vrele_pending > (desiredvnodes >> 8))
                                cv_signal(&vrele_cv); 
                        mutex_exit(&vrele_lock);
+                       cv_broadcast(&vp->v_cv);
                        mutex_exit(vp->v_interlock);
                        return;
                }
@@ -735,6 +768,7 @@
                VOP_INACTIVE(vp, &recycle);
                mutex_enter(vp->v_interlock);
                vp->v_iflag &= ~VI_INACTNOW;
+               cv_broadcast(&vp->v_cv);
                if (!recycle) {
                        if (vtryrele(vp)) {
                                mutex_exit(vp->v_interlock);
diff -r 1c93d8316266 -r 6058f919c9f4 sys/kern/vfs_vnops.c
--- a/sys/kern/vfs_vnops.c      Mon Nov 12 09:03:52 2012 +0000
+++ b/sys/kern/vfs_vnops.c      Mon Nov 12 11:00:07 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_vnops.c,v 1.185 2012/08/24 05:52:17 dholland Exp $ */
+/*     $NetBSD: vfs_vnops.c,v 1.186 2012/11/12 11:00:07 hannken Exp $  */
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.185 2012/08/24 05:52:17 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.186 2012/11/12 11:00:07 hannken Exp $");
 
 #include "veriexec.h"
 
@@ -807,15 +807,6 @@
                } else {
                        mutex_exit(vp->v_interlock);
                        error = VOP_LOCK(vp, (flags & ~LK_RETRY));
-                       if (error == 0 && (flags & LK_RETRY) == 0) {
-                               mutex_enter(vp->v_interlock);
-                               if ((vp->v_iflag & VI_CLEAN)) {
-                                       mutex_exit(vp->v_interlock);
-                                       VOP_UNLOCK(vp);
-                                       return ENOENT;
-                               }
-                               mutex_exit(vp->v_interlock);
-                       }
                        if (error == 0 || error == EDEADLK || error == EBUSY)
                                return (error);
                }



Home | Main Index | Thread Index | Old Index