Module Name: src Committed By: dyoung Date: Fri Jun 26 23:40:27 UTC 2009
Modified Files: src/sys/arch/i386/i386: machdep.c src/sys/arch/sparc64/sparc64: machdep.c Log Message: During a normal shutdown, gracefully tear down arbitrary stacks of filesystems and (pseudo-)devices, according to the algorithm at A3 and A4, below. Proposed and discussed at <http://mail-index.netbsd.org/tech-kern/2009/04/20/msg004864.html>. No objections. During an emergency shutdown (e.g., shutdown -n, or after a panic), shutdown is simple as always: filesystems are not sync'd or unmounted, and devices are not detached. It was necessary to change the order of operations during shutdown, but the new order is more sensible: if a core dump is desired, then cpu_reboot(9) dumps it first. cpu_reboot(9) does not call legacy shutdown hooks any longer: they can interfere with device detachment and PMF shutdown, and very few legacy hooks remain. Here is the old order of operations: B1 sync filesystems and TOD clock B2 unmount filesystems B3 dump core B4 detach devices B5 run legacy shutdown hooks B6 run PMF shutdown hooks B7 suspend interrupts B8 MD reboot/shutdown/powerdown And here is the new order: A1 dump core A2 sync filesystems and TOD clock A3 unmount one or more filesystems OR detach one or more devices OR forcefully unmount one filesystem OR skip to 5 A4 repeat at 3 A5 run PMF shutdown hooks A6 suspend interrupts A7 MD reboot/shutdown/powerdown Tested on Dell Dimension 3000, Dell PowerEdge 1950, Sun Fire V120, Soekris net4521 and net4801. VS: ---------------------------------------------------------------------- To generate a diff of this commit: cvs rdiff -u -r1.668 -r1.669 src/sys/arch/i386/i386/machdep.c cvs rdiff -u -r1.242 -r1.243 src/sys/arch/sparc64/sparc64/machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/i386/i386/machdep.c diff -u src/sys/arch/i386/i386/machdep.c:1.668 src/sys/arch/i386/i386/machdep.c:1.669 --- src/sys/arch/i386/i386/machdep.c:1.668 Wed Apr 1 03:56:54 2009 +++ src/sys/arch/i386/i386/machdep.c Fri Jun 26 23:40:27 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.668 2009/04/01 03:56:54 tls Exp $ */ +/* $NetBSD: machdep.c,v 1.669 2009/06/26 23:40:27 dyoung Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009 @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.668 2009/04/01 03:56:54 tls Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.669 2009/06/26 23:40:27 dyoung Exp $"); #include "opt_beep.h" #include "opt_compat_ibcs2.h" @@ -862,12 +862,28 @@ tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC); } -int waittime = -1; +static void +maybe_dump(int howto) +{ + int s; + + /* Disable interrupts. */ + s = splhigh(); + + /* Do a dump if requested. */ + if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) + dumpsys(); + + splx(s); +} void cpu_reboot(int howto, char *bootstr) { - int s = 0; /* XXX gcc */ + static bool syncdone = false; + struct lwp *l; + + l = (curlwp == NULL) ? &lwp0 : curlwp; if (cold) { howto |= RB_HALT; @@ -875,34 +891,43 @@ } boothowto = howto; - if ((howto & RB_NOSYNC) == 0 && waittime < 0) { - waittime = 0; - vfs_shutdown(); - /* - * If we've been adjusting the clock, the todr - * will be out of synch; adjust it now. - */ - if (time_adjusted != 0) - resettodr(); - } - /* Disable interrupts. */ - s = splhigh(); - - /* Do a dump if requested. */ - if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) - dumpsys(); + /* XXX used to dump after vfs_shutdown() and before + * detaching devices / shutdown hooks / pmf_system_shutdown(). + */ + maybe_dump(howto); -haltsys: - doshutdownhooks(); + /* + * If we've panic'd, don't make the situation potentially + * worse by syncing or unmounting the file systems. + */ + if ((howto & RB_NOSYNC) == 0 && panicstr == NULL) { + if (!syncdone) { + syncdone = true; + /* XXX used to force unmount as well, here */ + vfs_sync_all(l); + /* + * If we've been adjusting the clock, the todr + * will be out of synch; adjust it now. + * + * XXX used to do this after unmounting all + * filesystems with vfs_shutdown(). + */ + if (time_adjusted != 0) + resettodr(); + } - if (!cold) { - splx(s); + while (vfs_unmountall1(l, false, false) || + config_detach_all(boothowto) || + vfs_unmount_forceone(l)) + ; /* do nothing */ + } else + suspendsched(); - pmf_system_shutdown(boothowto); + pmf_system_shutdown(boothowto); - splhigh(); - } + splhigh(); +haltsys: if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { #ifdef XEN Index: src/sys/arch/sparc64/sparc64/machdep.c diff -u src/sys/arch/sparc64/sparc64/machdep.c:1.242 src/sys/arch/sparc64/sparc64/machdep.c:1.243 --- src/sys/arch/sparc64/sparc64/machdep.c:1.242 Thu May 21 08:13:43 2009 +++ src/sys/arch/sparc64/sparc64/machdep.c Fri Jun 26 23:40:27 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.242 2009/05/21 08:13:43 jnemeth Exp $ */ +/* $NetBSD: machdep.c,v 1.243 2009/06/26 23:40:27 dyoung Exp $ */ /*- * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.242 2009/05/21 08:13:43 jnemeth Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.243 2009/06/26 23:40:27 dyoung Exp $"); #include "opt_ddb.h" #include "opt_multiprocessor.h" @@ -560,14 +560,31 @@ struct pcb dumppcb; +static void +maybe_dump(int howto) +{ + int s; + + /* Disable interrupts. */ + s = splhigh(); + + /* Do a dump if requested. */ + if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) + dumpsys(); + + splx(s); +} + void cpu_reboot(int howto, char *user_boot_string) { static bool syncdone = false; int i; static char str[128]; + struct lwp *l; + + l = (curlwp == NULL) ? &lwp0 : curlwp; - /* If system is cold, just halt. */ if (cold) { howto |= RB_HALT; goto haltsys; @@ -577,34 +594,47 @@ fb_unblank(); #endif boothowto = howto; + + /* If rebooting and a dump is requested, do it. + * + * XXX used to dump after vfs_shutdown() and before + * detaching devices / shutdown hooks / pmf_system_shutdown(). + */ + maybe_dump(howto); + if ((howto & RB_NOSYNC) == 0 && !syncdone) { extern struct lwp lwp0; - /* XXX protect against curlwp->p_stats.foo refs in sync() */ - if (curlwp == NULL) - curlwp = &lwp0; + if (!syncdone) { syncdone = true; vfs_shutdown(); + /* XXX used to force unmount as well, here */ + vfs_sync_all(l); + /* + * If we've been adjusting the clock, the todr + * will be out of synch; adjust it now. + * + * resettodr will only do this only if inittodr() + * has already been called. + * + * XXX used to do this after unmounting all + * filesystems with vfs_shutdown(). + */ + resettodr(); + } - /* - * If we've been adjusting the clock, the todr - * will be out of synch; adjust it now. - * resettodr will only do this only if inittodr() - * has already been called. - */ - resettodr(); - } - (void) splhigh(); /* ??? */ + while (vfs_unmountall1(l, false, false) || + config_detach_all(boothowto) || + vfs_unmount_forceone(l)) + ; /* do nothing */ + } else + suspendsched(); - /* If rebooting and a dump is requested, do it. */ - if (howto & RB_DUMP) - dumpsys(); + pmf_system_shutdown(boothowto); -haltsys: - /* Run any shutdown hooks. */ - doshutdownhooks(); + splhigh(); - pmf_system_shutdown(boothowto); +haltsys: #ifdef MULTIPROCESSOR /* Stop all secondary cpus */