Source-Changes-HG archive

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

[src/trunk]: src/sys/miscfs/union Fix PR5146: reboot with working directory i...



details:   https://anonhg.NetBSD.org/src/rev/223fbe0314cc
branches:  trunk
changeset: 475093:223fbe0314cc
user:      sommerfeld <sommerfeld%NetBSD.org@localhost>
date:      Sun Aug 01 00:00:57 1999 +0000

description:
Fix PR5146: reboot with working directory in unionfs causes
"panic: lockmgr: using decommisioned lock"
(only if DIAGNOSTIC)

The problem turned out to be due to the way LK_DRAIN was (not) handled
in union_lock; it just got passed through to the lock on the upper
vnode (which got marked as decommissioned, instead of that happening
to the union vnode.  When the upper vnode was next locked (typically
when it was released), it went kaboom.

diffstat:

 sys/miscfs/union/union.h       |   4 +++-
 sys/miscfs/union/union_vnops.c |  40 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 41 insertions(+), 3 deletions(-)

diffs (107 lines):

diff -r 2adc2e83ec33 -r 223fbe0314cc sys/miscfs/union/union.h
--- a/sys/miscfs/union/union.h  Sat Jul 31 23:56:15 1999 +0000
+++ b/sys/miscfs/union/union.h  Sun Aug 01 00:00:57 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: union.h,v 1.10 1997/05/05 07:14:02 mycroft Exp $       */
+/*     $NetBSD: union.h,v 1.11 1999/08/01 00:00:57 sommerfeld Exp $    */
 
 /*
  * Copyright (c) 1994 The Regents of the University of California.
@@ -92,6 +92,8 @@
 #define UN_ULOCK       0x04            /* Upper node is locked */
 #define UN_KLOCK       0x08            /* Keep upper node locked on vput */
 #define UN_CACHED      0x10            /* In union cache */
+#define UN_DRAINING    0x20            /* upper node lock is draining */
+#define UN_DRAINED     0x40            /* upper node lock is drained */
 
 extern int union_allocvp __P((struct vnode **, struct mount *,
                                struct vnode *, struct vnode *,
diff -r 2adc2e83ec33 -r 223fbe0314cc sys/miscfs/union/union_vnops.c
--- a/sys/miscfs/union/union_vnops.c    Sat Jul 31 23:56:15 1999 +0000
+++ b/sys/miscfs/union/union_vnops.c    Sun Aug 01 00:00:57 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: union_vnops.c,v 1.44 1999/03/25 13:05:42 bouyer Exp $  */
+/*     $NetBSD: union_vnops.c,v 1.45 1999/08/01 00:00:57 sommerfeld Exp $      */
 
 /*
  * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
@@ -1595,7 +1595,9 @@
        int flags = ap->a_flags;
        struct union_node *un;
        int error;
-
+#ifdef DIAGNOSTIC
+       int drain = 0;
+#endif
 
        genfs_nolock(ap);
        /*
@@ -1609,6 +1611,31 @@
         */
        flags &= ~LK_INTERLOCK;
 
+       un = VTOUNION(vp);
+#ifdef DIAGNOSTIC
+       if (un->un_flags & (UN_DRAINING|UN_DRAINED)) {
+               if (un->un_flags & UN_DRAINED)
+                       panic("union: %p: warning: locking decommissioned lock\n", vp);
+               if ((flags & LK_TYPE_MASK) != LK_RELEASE)
+                       panic("union: %p: non-release on draining lock: %d\n",
+                           vp, flags & LK_TYPE_MASK);
+               un->un_flags &= ~UN_DRAINING;
+               if ((flags & LK_REENABLE) == 0)
+                       un->un_flags |= UN_DRAINED;
+       }
+#endif
+       
+       /*
+        * Don't pass DRAIN through to sub-vnode lock; keep track of
+        * DRAIN state at this level, and just get an exclusive lock
+        * on the underlying vnode.
+        */
+       if ((flags & LK_TYPE_MASK) == LK_DRAIN) {
+#ifdef DIAGNOSTIC
+               drain = 1;
+#endif
+               flags = LK_EXCLUSIVE | (flags & ~LK_TYPE_MASK);
+       }
 start:
        un = VTOUNION(vp);
 
@@ -1633,6 +1660,7 @@
 #endif
        }
 
+       /* XXX ignores LK_NOWAIT */
        if (un->un_flags & UN_LOCKED) {
 #ifdef DIAGNOSTIC
                if (curproc && un->un_pid == curproc->p_pid &&
@@ -1649,6 +1677,8 @@
                un->un_pid = curproc->p_pid;
        else
                un->un_pid = -1;
+       if (drain)
+               un->un_flags |= UN_DRAINING;
 #endif
 
        un->un_flags |= UN_LOCKED;
@@ -1682,6 +1712,8 @@
        if (curproc && un->un_pid != curproc->p_pid &&
                        curproc->p_pid > -1 && un->un_pid > -1)
                panic("union: unlocking other process's union node");
+       if (un->un_flags & UN_DRAINED)
+               panic("union: %p: warning: unlocking decommissioned lock\n", ap->a_vp);                 
 #endif
 
        un->un_flags &= ~UN_LOCKED;
@@ -1698,6 +1730,10 @@
 
 #ifdef DIAGNOSTIC
        un->un_pid = 0;
+       if (un->un_flags & UN_DRAINING) {
+               un->un_flags |= UN_DRAINED;
+               un->un_flags &= ~UN_DRAINING;
+       }
 #endif
        genfs_nounlock(ap);
 



Home | Main Index | Thread Index | Old Index