Source-Changes-HG archive

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

[src/trunk]: src/sys/kern Change vrelel() to mark the vnode as changing after...



details:   https://anonhg.NetBSD.org/src/rev/94899ce8c37e
branches:  trunk
changeset: 324994:94899ce8c37e
user:      hannken <hannken%NetBSD.org@localhost>
date:      Fri Nov 29 14:58:55 2013 +0000

description:
Change vrelel() to mark the vnode as changing after it has aquired
the vnode lock but before it calls VOP_INACTIVE().

Should fix the race between layer_node_find() trying to vget(, LK_NOWAIT)
a locked vnode when vrelel() marked it as changing and wants its lock.

PR kern/48411 (repeatable SMP crashes in amd64-current)

diffstat:

 sys/kern/vfs_vnode.c |  38 ++++++++++++++++++++++++--------------
 1 files changed, 24 insertions(+), 14 deletions(-)

diffs (102 lines):

diff -r 08bbdb963857 -r 94899ce8c37e sys/kern/vfs_vnode.c
--- a/sys/kern/vfs_vnode.c      Fri Nov 29 14:51:36 2013 +0000
+++ b/sys/kern/vfs_vnode.c      Fri Nov 29 14:58:55 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_vnode.c,v 1.26 2013/11/23 13:46:22 hannken Exp $   */
+/*     $NetBSD: vfs_vnode.c,v 1.27 2013/11/29 14:58:55 hannken Exp $   */
 
 /*-
  * Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -116,7 +116,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.26 2013/11/23 13:46:22 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.27 2013/11/29 14:58:55 hannken Exp $");
 
 #define _VFS_VNODE_PRIVATE
 
@@ -606,10 +606,6 @@
        }
 
        KASSERT((vp->v_iflag & VI_XLOCK) == 0);
-       if ((flags & VRELEL_CHANGING_SET) == 0) {
-               KASSERT((vp->v_iflag & VI_CHANGING) == 0);
-               vp->v_iflag |= VI_CHANGING;
-       }
 
 #ifdef DIAGNOSTIC
        if ((vp->v_type == VBLK || vp->v_type == VCHR) &&
@@ -654,13 +650,14 @@
                         */
                        if (__predict_false(vtryrele(vp))) {
                                VOP_UNLOCK(vp);
-                               KASSERT((vp->v_iflag & VI_CHANGING) != 0);
-                               vp->v_iflag &= ~VI_CHANGING;
-                               cv_broadcast(&vp->v_cv);
+                               if ((flags & VRELEL_CHANGING_SET) != 0) {
+                                       KASSERT((vp->v_iflag & VI_CHANGING) != 0);
+                                       vp->v_iflag &= ~VI_CHANGING;
+                                       cv_broadcast(&vp->v_cv);
+                               }
                                mutex_exit(vp->v_interlock);
                                return;
                        }
-                       mutex_exit(vp->v_interlock);
                        defer = false;
                } else if ((vp->v_iflag & VI_LAYER) != 0) {
                        /* 
@@ -675,10 +672,10 @@
                        error = vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT);
                        if (error != 0) {
                                defer = true;
-                               mutex_enter(vp->v_interlock);
                        } else {
                                defer = false;
                        }
+                       mutex_enter(vp->v_interlock);
                }
 
                if (defer) {
@@ -687,18 +684,26 @@
                         * clean it here.  We donate it our last reference.
                         */
                        KASSERT(mutex_owned(vp->v_interlock));
-                       KASSERT((vp->v_iflag & VI_CHANGING) != 0);
-                       vp->v_iflag &= ~VI_CHANGING;
+                       if ((flags & VRELEL_CHANGING_SET) != 0) {
+                               KASSERT((vp->v_iflag & VI_CHANGING) != 0);
+                               vp->v_iflag &= ~VI_CHANGING;
+                               cv_broadcast(&vp->v_cv);
+                       }
                        mutex_enter(&vrele_lock);
                        TAILQ_INSERT_TAIL(&vrele_list, vp, v_freelist);
                        if (++vrele_pending > (desiredvnodes >> 8))
                                cv_signal(&vrele_cv); 
                        mutex_exit(&vrele_lock);
-                       cv_broadcast(&vp->v_cv);
                        mutex_exit(vp->v_interlock);
                        return;
                }
 
+               if ((flags & VRELEL_CHANGING_SET) == 0) {
+                       KASSERT((vp->v_iflag & VI_CHANGING) == 0);
+                       vp->v_iflag |= VI_CHANGING;
+               }
+               mutex_exit(vp->v_interlock);
+
                /*
                 * The vnode can gain another reference while being
                 * deactivated.  If VOP_INACTIVE() indicates that
@@ -739,6 +744,11 @@
                        vclean(vp);
                }
                KASSERT(vp->v_usecount > 0);
+       } else { /* vnode was already clean */
+               if ((flags & VRELEL_CHANGING_SET) == 0) {
+                       KASSERT((vp->v_iflag & VI_CHANGING) == 0);
+                       vp->v_iflag |= VI_CHANGING;
+               }
        }
 
        if (atomic_dec_uint_nv(&vp->v_usecount) != 0) {



Home | Main Index | Thread Index | Old Index