Source-Changes-HG archive

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

[src/trunk]: src/sys Fix assorted bugs around shutdown/reboot/panic time.



details:   https://anonhg.NetBSD.org/src/rev/dfcc55d33e76
branches:  trunk
changeset: 487649:dfcc55d33e76
user:      sommerfeld <sommerfeld%NetBSD.org@localhost>
date:      Sat Jun 10 18:44:43 2000 +0000

description:
Fix assorted bugs around shutdown/reboot/panic time.
 - add a new global variable, doing_shutdown, which is nonzero if
vfs_shutdown() or panic() have been called.
- in panic, set RB_NOSYNC if doing_shutdown is already set on entry
so we don't reenter vfs_shutdown if we panic'ed there.
 - in vfs_shutdown, don't use proc0's process for sys_sync unless
curproc is NULL.
 - in lockmgr, attribute successful locks to proc0 if doing_shutdown
&& curproc==NULL, and  panic if we can't get the lock right away; avoids the
spurious lockmgr DIAGNOSTIC panic from the ddb reboot command.
 - in subr_pool, deal with curproc==NULL in the doing_shutdown case.
 - in mfs_strategy, bitbucket writes if doing_shutdown, so we don't
wedge waiting for the mfs process.
 - in ltsleep, treat ((curproc == NULL) && doing_shutdown) like the
panicstr case.

Appears to fix: kern/9239, kern/10187, kern/9367.
May also fix kern/10122.

diffstat:

 sys/kern/kern_lock.c  |  42 +++++++++++++++++++++++++++++++++++++-----
 sys/kern/kern_synch.c |  13 ++++++++++---
 sys/kern/subr_pool.c  |   5 +++--
 sys/kern/subr_prf.c   |  10 ++++++----
 sys/kern/vfs_subr.c   |  30 +++++++++++++-----------------
 sys/sys/mount.h       |   4 ++--
 sys/sys/systm.h       |   3 ++-
 7 files changed, 73 insertions(+), 34 deletions(-)

diffs (272 lines):

diff -r 22e1e7eed846 -r dfcc55d33e76 sys/kern/kern_lock.c
--- a/sys/kern/kern_lock.c      Sat Jun 10 18:31:11 2000 +0000
+++ b/sys/kern/kern_lock.c      Sat Jun 10 18:44:43 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_lock.c,v 1.31 2000/06/08 05:50:59 thorpej Exp $   */
+/*     $NetBSD: kern_lock.c,v 1.32 2000/06/10 18:44:43 sommerfeld Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -322,6 +322,21 @@
 }
 
 /*
+ * XXX XXX kludge around another kludge..
+ *
+ * vfs_shutdown() may be called from interrupt context, either as a result
+ * of a panic, or from the debugger.   It proceeds to call
+ * sys_sync(&proc0, ...), pretending its running on behalf of proc0
+ *
+ * We would like to make an attempt to sync the filesystems in this case, so
+ * if this happens, we treat attempts to acquire locks specially.
+ * All locks are acquired on behalf of proc0.
+ *
+ * If we've already paniced, we don't block waiting for locks, but
+ * just barge right ahead since we're already going down in flames.
+ */
+
+/*
  * Set, change, or release a lock.
  *
  * Shared requests increment the shared count. Exclusive requests set the
@@ -339,6 +354,7 @@
        int extflags;
        cpuid_t cpu_id;
        struct proc *p = curproc;
+       int lock_shutdown_noblock = 0;
 
        error = 0;
 
@@ -359,10 +375,19 @@
        if (extflags & LK_SPIN)
                pid = LK_KERNPROC;
        else {
-#ifdef DIAGNOSTIC /* { */
-               if (p == NULL)
-                       panic("lockmgr: no context");
-#endif /* } */
+               if (p == NULL) {
+                       if (!doing_shutdown) {
+#ifdef DIAGNOSTIC
+                               panic("lockmgr: no context");
+#endif
+                       } else {
+                               p = &proc0;
+                               if (panicstr && (!(flags & LK_NOWAIT))) {
+                                       flags |= LK_NOWAIT;
+                                       lock_shutdown_noblock = 1;
+                               }
+                       }
+               }
                pid = p->p_pid;
        }
        cpu_id = cpu_number();
@@ -637,6 +662,13 @@
                lkp->lk_flags &= ~LK_WAITDRAIN;
                wakeup_one((void *)&lkp->lk_flags);
        }
+       /*
+        * Note that this panic will be a recursive panic, since
+        * we only set lock_shutdown_noblock above if panicstr != NULL.
+        */
+       if (error && lock_shutdown_noblock)
+               panic("lockmgr: deadlock (see previous panic)");
+       
        simple_unlock(&lkp->lk_interlock);
        return (error);
 }
diff -r 22e1e7eed846 -r dfcc55d33e76 sys/kern/kern_synch.c
--- a/sys/kern/kern_synch.c     Sat Jun 10 18:31:11 2000 +0000
+++ b/sys/kern/kern_synch.c     Sat Jun 10 18:44:43 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_synch.c,v 1.77 2000/06/08 05:50:37 thorpej Exp $  */
+/*     $NetBSD: kern_synch.c,v 1.78 2000/06/10 18:44:44 sommerfeld Exp $       */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -355,15 +355,18 @@
        int catch = priority & PCATCH;
        int relock = (priority & PNORELOCK) == 0;
 #if 0 /* XXXSMP */
-       int dobiglock = (p->p_flags & P_BIGLOCK) != 0;
+       int dobiglock;
 #endif
 
        /*
         * XXXSMP
         * This is probably bogus.  Figure out what the right
         * thing to do here really is.
+        * Note that not sleeping if ltsleep is called with curproc == NULL 
+        * in the shutdown case is disgusting but partly necessary given
+        * how shutdown (barely) works.
         */
-       if (cold || panicstr) {
+       if (cold || (doing_shutdown && (panicstr || (p == NULL)))) {
                /*
                 * After a panic, or during autoconfiguration,
                 * just give interrupts a chance, then just return;
@@ -378,6 +381,10 @@
                return (0);
        }
 
+#if 0 /* XXXSMP */
+       dobiglock = (p->p_flags & P_BIGLOCK) != 0;
+#endif
+
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_CSW))
                ktrcsw(p, 1, 0);
diff -r 22e1e7eed846 -r dfcc55d33e76 sys/kern/subr_pool.c
--- a/sys/kern/subr_pool.c      Sat Jun 10 18:31:11 2000 +0000
+++ b/sys/kern/subr_pool.c      Sat Jun 10 18:44:43 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_pool.c,v 1.36 2000/05/31 15:29:42 pk Exp $        */
+/*     $NetBSD: subr_pool.c,v 1.37 2000/06/10 18:44:44 sommerfeld Exp $        */
 
 /*-
  * Copyright (c) 1997, 1999 The NetBSD Foundation, Inc.
@@ -594,7 +594,8 @@
        }
 #endif
 
-       if (__predict_false(curproc == NULL && (flags & PR_WAITOK) != 0))
+       if (__predict_false(curproc == NULL && doing_shutdown == 0 &&
+                           (flags & PR_WAITOK) != 0))
                panic("pool_get: must have NOWAIT");
 
        simple_lock(&pp->pr_slock);
diff -r 22e1e7eed846 -r dfcc55d33e76 sys/kern/subr_prf.c
--- a/sys/kern/subr_prf.c       Sat Jun 10 18:31:11 2000 +0000
+++ b/sys/kern/subr_prf.c       Sat Jun 10 18:44:43 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_prf.c,v 1.73 2000/05/29 23:10:03 jhawk Exp $      */
+/*     $NetBSD: subr_prf.c,v 1.74 2000/06/10 18:44:44 sommerfeld Exp $ */
 
 /*-
  * Copyright (c) 1986, 1988, 1991, 1993
@@ -146,6 +146,7 @@
 extern int log_open;   /* subr_log: is /dev/klog open? */
 const  char *panicstr; /* arg to first call to panic (used as a flag
                           to indicate that panic has already been called). */
+int    doing_shutdown; /* set to indicate shutdown in progress */
 
 /*
  * v_putc: routine to putc on virtual console
@@ -193,11 +194,12 @@
        va_list ap;
 
        bootopt = RB_AUTOBOOT | RB_DUMP;
-       if (panicstr)
+       if (doing_shutdown)
                bootopt |= RB_NOSYNC;
-       else
+       if (!panicstr)
                panicstr = fmt;
-
+       doing_shutdown = 1;
+       
        va_start(ap, fmt);
        printf("panic: ");
        vprintf(fmt, ap);
diff -r 22e1e7eed846 -r dfcc55d33e76 sys/kern/vfs_subr.c
--- a/sys/kern/vfs_subr.c       Sat Jun 10 18:31:11 2000 +0000
+++ b/sys/kern/vfs_subr.c       Sat Jun 10 18:44:43 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_subr.c,v 1.127 2000/06/10 18:27:01 assar Exp $     */
+/*     $NetBSD: vfs_subr.c,v 1.128 2000/06/10 18:44:44 sommerfeld Exp $        */
 
 /*-
  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -2290,23 +2290,11 @@
  * will avoid needing to worry about dependencies.
  */
 void
-vfs_unmountall()
+vfs_unmountall(p)
+       struct proc *p;
 {
        struct mount *mp, *nmp;
        int allerror, error;
-       struct proc *p = curproc;       /* XXX */
-
-       /*
-        * Unmounting a file system blocks the requesting process.
-        * However, it's possible for this routine to be called when
-        * curproc is NULL (e.g. panic situation, or via the debugger).
-        * If we get stuck in this situation, just abort, since any
-        * attempts to sleep will fault.
-        */
-       if (p == NULL) {
-               printf("vfs_unmountall: no context, aborting\n");
-               return;
-       }
 
        for (allerror = 0,
             mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
@@ -2335,13 +2323,21 @@
 {
        struct buf *bp;
        int iter, nbusy, dcount, s;
+       struct proc *p = curproc;
 
+       /* XXX we're certainly not running in proc0's context! */
+       if (p == NULL)
+               p = &proc0;
+       
        printf("syncing disks... ");
 
        /* XXX Should suspend scheduling. */
        (void) spl0();
 
-       sys_sync(&proc0, (void *)0, (register_t *)0);
+       /* avoid coming back this way again if we panic. */
+       doing_shutdown = 1;
+
+       sys_sync(p, (void *)0, (register_t *)0);
 
        /* Wait for sync to finish. */
        dcount = 10000;
@@ -2406,7 +2402,7 @@
        vnshutdown();
 #endif
        /* Unmount file systems. */
-       vfs_unmountall();
+       vfs_unmountall(p);
 }
 
 /*
diff -r 22e1e7eed846 -r dfcc55d33e76 sys/sys/mount.h
--- a/sys/sys/mount.h   Sat Jun 10 18:31:11 2000 +0000
+++ b/sys/sys/mount.h   Sat Jun 10 18:44:43 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mount.h,v 1.84 2000/06/10 18:27:04 assar Exp $ */
+/*     $NetBSD: mount.h,v 1.85 2000/06/10 18:44:44 sommerfeld Exp $    */
 
 /*
  * Copyright (c) 1989, 1991, 1993
@@ -422,7 +422,7 @@
 int    vfs_mountroot __P((void));
 void   vfs_shutdown __P((void));           /* unmount and sync file systems */
 void   vfs_unlock __P((struct mount *));   /* unlock a vfs */
-void   vfs_unmountall __P((void));         /* unmount file systems */
+void   vfs_unmountall __P((struct proc *));        /* unmount file systems */
 int    vfs_busy __P((struct mount *, int, struct simplelock *));
 int    vfs_rootmountalloc __P((char *, char *, struct mount **));
 void   vfs_unbusy __P((struct mount *));
diff -r 22e1e7eed846 -r dfcc55d33e76 sys/sys/systm.h
--- a/sys/sys/systm.h   Sat Jun 10 18:31:11 2000 +0000
+++ b/sys/sys/systm.h   Sat Jun 10 18:44:43 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: systm.h,v 1.110 2000/05/28 05:49:06 thorpej Exp $      */
+/*     $NetBSD: systm.h,v 1.111 2000/06/10 18:44:45 sommerfeld Exp $   */
 
 /*-
  * Copyright (c) 1982, 1988, 1991, 1993
@@ -87,6 +87,7 @@
 
 extern int securelevel;                /* system security level */
 extern const char *panicstr;   /* panic message */
+extern int doing_shutdown;     /* shutting down */
 
 extern char copyright[];       /* system copyright */
 extern char cpu_model[];       /* machine/cpu model name */



Home | Main Index | Thread Index | Old Index