117658Sjulian/*- 217658Sjulian * Copyright (c) 1986, 1988, 1991, 1993 317658Sjulian * The Regents of the University of California. All rights reserved. 417658Sjulian * (c) UNIX System Laboratories, Inc. 517658Sjulian * All or some portions of this file are derived from material licensed 617658Sjulian * to the University of California by American Telephone and Telegraph 717658Sjulian * Co. or Unix System Laboratories, Inc. and are reproduced herein with 817658Sjulian * the permission of UNIX System Laboratories, Inc. 917658Sjulian * 1017658Sjulian * Redistribution and use in source and binary forms, with or without 1117658Sjulian * modification, are permitted provided that the following conditions 1217658Sjulian * are met: 1317658Sjulian * 1. Redistributions of source code must retain the above copyright 1417658Sjulian * notice, this list of conditions and the following disclaimer. 1517658Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1617658Sjulian * notice, this list of conditions and the following disclaimer in the 1717658Sjulian * documentation and/or other materials provided with the distribution. 1817658Sjulian * 4. Neither the name of the University nor the names of its contributors 1917658Sjulian * may be used to endorse or promote products derived from this software 2017658Sjulian * without specific prior written permission. 2117658Sjulian * 2217658Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2317658Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2417658Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2517658Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2617658Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2717658Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2817658Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2917658Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3017658Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3117658Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3217658Sjulian * SUCH DAMAGE. 3317658Sjulian * 3417658Sjulian * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94 3517658Sjulian */ 3617658Sjulian 37116182Sobrien#include <sys/cdefs.h> 38116182Sobrien__FBSDID("$FreeBSD$"); 39116182Sobrien 40174921Srwatson#include "opt_ddb.h" 41131927Smarcel#include "opt_kdb.h" 4228976Sbde#include "opt_panic.h" 43134649Sscottl#include "opt_sched.h" 44221173Sattilio#include "opt_watchdog.h" 4517658Sjulian 4617658Sjulian#include <sys/param.h> 4717658Sjulian#include <sys/systm.h> 4860041Sphk#include <sys/bio.h> 4931275Sbde#include <sys/buf.h> 5078767Sjhb#include <sys/conf.h> 5178767Sjhb#include <sys/cons.h> 5278767Sjhb#include <sys/eventhandler.h> 53293743Strasz#include <sys/filedesc.h> 54193066Sjamie#include <sys/jail.h> 55131927Smarcel#include <sys/kdb.h> 5617658Sjulian#include <sys/kernel.h> 57183527Speter#include <sys/kerneldump.h> 5855539Sluoqi#include <sys/kthread.h> 59243980Salfred#include <sys/ktr.h> 6089601Ssobomax#include <sys/malloc.h> 6121776Sbde#include <sys/mount.h> 62164033Srwatson#include <sys/priv.h> 6378767Sjhb#include <sys/proc.h> 6478767Sjhb#include <sys/reboot.h> 6578767Sjhb#include <sys/resourcevar.h> 66248084Sattilio#include <sys/rwlock.h> 67137263Speter#include <sys/sched.h> 68206878Sattilio#include <sys/smp.h> 6917658Sjulian#include <sys/sysctl.h> 7017658Sjulian#include <sys/sysproto.h> 71225448Sattilio#include <sys/vnode.h> 72221173Sattilio#include <sys/watchdog.h> 7317658Sjulian 74174921Srwatson#include <ddb/ddb.h> 75174921Srwatson 76118990Smarcel#include <machine/cpu.h> 7794169Sphk#include <machine/pcb.h> 7891778Sjake#include <machine/smp.h> 7917658Sjulian 80163606Srwatson#include <security/mac/mac_framework.h> 81163606Srwatson 82157628Spjd#include <vm/vm.h> 83157628Spjd#include <vm/vm_object.h> 84157628Spjd#include <vm/vm_page.h> 85157628Spjd#include <vm/vm_pager.h> 86157628Spjd#include <vm/swap_pager.h> 87157628Spjd 8817658Sjulian#include <sys/signalvar.h> 8917658Sjulian 9017658Sjulian#ifndef PANIC_REBOOT_WAIT_TIME 9117658Sjulian#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */ 9217658Sjulian#endif 93260431Scpercivastatic int panic_reboot_wait_time = PANIC_REBOOT_WAIT_TIME; 94260431ScpercivaSYSCTL_INT(_kern, OID_AUTO, panic_reboot_wait_time, CTLFLAG_RW | CTLFLAG_TUN, 95260431Scperciva &panic_reboot_wait_time, 0, 96260431Scperciva "Seconds to wait before rebooting after a panic"); 97260431ScpercivaTUNABLE_INT("kern.panic_reboot_wait_time", &panic_reboot_wait_time); 9817658Sjulian 9917658Sjulian/* 10017658Sjulian * Note that stdarg.h and the ANSI style va_start macro is used for both 10117658Sjulian * ANSI and traditional C compilers. 10217658Sjulian */ 10317658Sjulian#include <machine/stdarg.h> 10417658Sjulian 105131927Smarcel#ifdef KDB 106131927Smarcel#ifdef KDB_UNATTENDED 10742135Smsmithint debugger_on_panic = 0; 10817658Sjulian#else 10942135Smsmithint debugger_on_panic = 1; 11017658Sjulian#endif 111228475SobrienSYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, 112228487Sobrien CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_TUN, 113228487Sobrien &debugger_on_panic, 0, "Run debugger on kernel panic"); 114213322SavgTUNABLE_INT("debug.debugger_on_panic", &debugger_on_panic); 115103647Sjhb 116131927Smarcel#ifdef KDB_TRACE 117213322Savgstatic int trace_on_panic = 1; 118103647Sjhb#else 119213322Savgstatic int trace_on_panic = 0; 12017658Sjulian#endif 121228475SobrienSYSCTL_INT(_debug, OID_AUTO, trace_on_panic, 122228487Sobrien CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_TUN, 123228487Sobrien &trace_on_panic, 0, "Print stack trace on kernel panic"); 124213322SavgTUNABLE_INT("debug.trace_on_panic", &trace_on_panic); 125131927Smarcel#endif /* KDB */ 12617658Sjulian 127213322Savgstatic int sync_on_panic = 0; 128213322SavgSYSCTL_INT(_kern, OID_AUTO, sync_on_panic, CTLFLAG_RW | CTLFLAG_TUN, 12985202Speter &sync_on_panic, 0, "Do a sync before rebooting from a panic"); 130213322SavgTUNABLE_INT("kern.sync_on_panic", &sync_on_panic); 13185202Speter 132227309Sedstatic SYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, 133227309Sed "Shutdown environment"); 13443436Smsmith 135225448Sattilio#ifndef DIAGNOSTIC 136225448Sattiliostatic int show_busybufs; 137225448Sattilio#else 138225448Sattiliostatic int show_busybufs = 1; 139225448Sattilio#endif 140225448SattilioSYSCTL_INT(_kern_shutdown, OID_AUTO, show_busybufs, CTLFLAG_RW, 141225448Sattilio &show_busybufs, 0, ""); 142225448Sattilio 143289032Scpercivaint suspend_blocked = 0; 144289032ScpercivaSYSCTL_INT(_kern, OID_AUTO, suspend_blocked, CTLFLAG_RW, 145289032Scperciva &suspend_blocked, 0, "Block suspend due to a pending shutdown"); 146289032Scperciva 14717658Sjulian/* 14817658Sjulian * Variable panicstr contains argument to first call to panic; used as flag 14917658Sjulian * to indicate that the kernel has already called panic. 15017658Sjulian */ 15117658Sjulianconst char *panicstr; 15217658Sjulian 15393496Sphkint dumping; /* system is dumping */ 154155383Sjeffint rebooting; /* system is rebooting */ 15593496Sphkstatic struct dumperinfo dumper; /* our selected dumper */ 15667093Sps 157131927Smarcel/* Context information for dump-debuggers. */ 158131927Smarcelstatic struct pcb dumppcb; /* Registers. */ 159235777Shartilwpid_t dumptid; /* Thread ID. */ 160131927Smarcel 161293743Straszstatic struct cdevsw reroot_cdevsw = { 162293743Strasz .d_version = D_VERSION, 163293743Strasz .d_name = "reroot", 164293743Strasz}; 165293743Strasz 16665395Speterstatic void poweroff_wait(void *, int); 16765395Speterstatic void shutdown_halt(void *junk, int howto); 16865395Speterstatic void shutdown_panic(void *junk, int howto); 16965395Speterstatic void shutdown_reset(void *junk, int howto); 170293743Straszstatic int kern_reroot(void); 17117658Sjulian 17250107Smsmith/* register various local shutdown events */ 173110859Salfredstatic void 17450107Smsmithshutdown_conf(void *unused) 17550107Smsmith{ 176110859Salfred 177110859Salfred EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL, 178214279Sbrucec SHUTDOWN_PRI_FIRST); 179110859Salfred EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL, 180110859Salfred SHUTDOWN_PRI_LAST + 100); 181110859Salfred EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL, 182110859Salfred SHUTDOWN_PRI_LAST + 100); 183110859Salfred EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL, 184110859Salfred SHUTDOWN_PRI_LAST + 200); 18550107Smsmith} 18648868Sphk 187177253SrwatsonSYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL); 18850107Smsmith 18917658Sjulian/* 190293743Strasz * The only reason this exists is to create the /dev/reroot/ directory, 191293743Strasz * used by reroot code in init(8) as a mountpoint for tmpfs. 192293743Strasz */ 193293743Straszstatic void 194293743Straszreroot_conf(void *unused) 195293743Strasz{ 196293743Strasz int error; 197293743Strasz struct cdev *cdev; 198293743Strasz 199293743Strasz error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, &cdev, 200293743Strasz &reroot_cdevsw, NULL, UID_ROOT, GID_WHEEL, 0600, "reroot/reroot"); 201293743Strasz if (error != 0) { 202293743Strasz printf("%s: failed to create device node, error %d", 203293743Strasz __func__, error); 204293743Strasz } 205293743Strasz} 206293743Strasz 207293743StraszSYSINIT(reroot_conf, SI_SUB_DEVFS, SI_ORDER_ANY, reroot_conf, NULL); 208293743Strasz 209293743Strasz/* 210167211Srwatson * The system call that results in a reboot. 21117658Sjulian */ 21282749Sdillon/* ARGSUSED */ 21317658Sjulianint 214225617Skmacysys_reboot(struct thread *td, struct reboot_args *uap) 21517658Sjulian{ 21617658Sjulian int error; 21717658Sjulian 218106024Srwatson error = 0; 219106024Srwatson#ifdef MAC 220172930Srwatson error = mac_system_check_reboot(td->td_ucred, uap->opt); 221106024Srwatson#endif 222106024Srwatson if (error == 0) 223164033Srwatson error = priv_check(td, PRIV_REBOOT); 224106024Srwatson if (error == 0) { 225293743Strasz if (uap->opt & RB_REROOT) { 226293743Strasz error = kern_reroot(); 227293743Strasz } else { 228293743Strasz mtx_lock(&Giant); 229293743Strasz kern_reboot(uap->opt); 230293743Strasz mtx_unlock(&Giant); 231293743Strasz } 232106024Srwatson } 23382749Sdillon return (error); 23417658Sjulian} 23517658Sjulian 23617658Sjulian/* 23717658Sjulian * Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC 23817658Sjulian */ 23965268Smsmithstatic int shutdown_howto = 0; 24065268Smsmith 24117658Sjulianvoid 24265268Smsmithshutdown_nice(int howto) 24317658Sjulian{ 244110859Salfred 24565268Smsmith shutdown_howto = howto; 246110859Salfred 24717658Sjulian /* Send a signal to init(8) and have it shutdown the world */ 24817658Sjulian if (initproc != NULL) { 24973913Sjhb PROC_LOCK(initproc); 250225617Skmacy kern_psignal(initproc, SIGINT); 25173913Sjhb PROC_UNLOCK(initproc); 25217658Sjulian } else { 25317658Sjulian /* No init(8) running, so simply reboot */ 254214004Smarcel kern_reboot(RB_NOSYNC); 25517658Sjulian } 25617658Sjulian return; 25717658Sjulian} 25817658Sjulianstatic int waittime = -1; 25917658Sjulian 26054233Sphkstatic void 26165395Speterprint_uptime(void) 26254233Sphk{ 26354233Sphk int f; 26454233Sphk struct timespec ts; 26554233Sphk 26654233Sphk getnanouptime(&ts); 26754233Sphk printf("Uptime: "); 26854233Sphk f = 0; 26954233Sphk if (ts.tv_sec >= 86400) { 27065764Sjhb printf("%ldd", (long)ts.tv_sec / 86400); 27154233Sphk ts.tv_sec %= 86400; 27254233Sphk f = 1; 27354233Sphk } 27454233Sphk if (f || ts.tv_sec >= 3600) { 27565764Sjhb printf("%ldh", (long)ts.tv_sec / 3600); 27654233Sphk ts.tv_sec %= 3600; 27754233Sphk f = 1; 27854233Sphk } 27954233Sphk if (f || ts.tv_sec >= 60) { 28065764Sjhb printf("%ldm", (long)ts.tv_sec / 60); 28154233Sphk ts.tv_sec %= 60; 28254233Sphk f = 1; 28354233Sphk } 28465764Sjhb printf("%lds\n", (long)ts.tv_sec); 28554233Sphk} 28654233Sphk 287222801Smarcelint 288222801Smarceldoadump(boolean_t textdump) 28994169Sphk{ 290222801Smarcel boolean_t coredump; 291110859Salfred 292222801Smarcel if (dumping) 293222801Smarcel return (EBUSY); 294222801Smarcel if (dumper.dumper == NULL) 295222801Smarcel return (ENXIO); 296132412Sjulian 29794169Sphk savectx(&dumppcb); 298131927Smarcel dumptid = curthread->td_tid; 29994169Sphk dumping++; 300222801Smarcel 301222801Smarcel coredump = TRUE; 302174921Srwatson#ifdef DDB 303222801Smarcel if (textdump && textdump_pending) { 304222801Smarcel coredump = FALSE; 305174921Srwatson textdump_dumpsys(&dumper); 306222801Smarcel } 307174921Srwatson#endif 308222801Smarcel if (coredump) 309174921Srwatson dumpsys(&dumper); 310222801Smarcel 311176788Sru dumping--; 312222801Smarcel return (0); 31394169Sphk} 31494169Sphk 315149875Struckmanstatic int 316149875Struckmanisbufbusy(struct buf *bp) 317149875Struckman{ 318149875Struckman if (((bp->b_flags & (B_INVAL | B_PERSISTENT)) == 0 && 319175486Sattilio BUF_ISLOCKED(bp)) || 320149875Struckman ((bp->b_flags & (B_DELWRI | B_INVAL)) == B_DELWRI)) 321149875Struckman return (1); 322149875Struckman return (0); 323149875Struckman} 324149875Struckman 32517658Sjulian/* 326137329Snjl * Shutdown the system cleanly to prepare for reboot, halt, or power off. 32717658Sjulian */ 328214004Smarcelvoid 329214004Smarcelkern_reboot(int howto) 33017658Sjulian{ 331133763Struckman static int first_buf_printf = 1; 33217658Sjulian 333137375Smarcel#if defined(SMP) 334137329Snjl /* 335137329Snjl * Bind us to CPU 0 so that all shutdown code runs there. Some 336137329Snjl * systems don't shutdown properly (i.e., ACPI power off) if we 337137329Snjl * run on another processor. 338137329Snjl */ 339228424Savg if (!SCHEDULER_STOPPED()) { 340228424Savg thread_lock(curthread); 341228424Savg sched_bind(curthread, 0); 342228424Savg thread_unlock(curthread); 343228424Savg KASSERT(PCPU_GET(cpuid) == 0, ("boot: not running on cpu 0")); 344228424Savg } 345137263Speter#endif 346155383Sjeff /* We're in the process of rebooting. */ 347155383Sjeff rebooting = 1; 348137263Speter 34965268Smsmith /* collect extra flags that shutdown_nice might have set */ 35065268Smsmith howto |= shutdown_howto; 35165268Smsmith 35282119Sjhb /* We are out of the debugger now. */ 353131927Smarcel kdb_active = 0; 35482119Sjhb 35527997Sjulian /* 35627997Sjulian * Do any callouts that should be done BEFORE syncing the filesystems. 35727997Sjulian */ 35850107Smsmith EVENTHANDLER_INVOKE(shutdown_pre_sync, howto); 35927997Sjulian 36027997Sjulian /* 36127997Sjulian * Now sync filesystems 36227997Sjulian */ 36317658Sjulian if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { 36417658Sjulian register struct buf *bp; 36565707Sjasone int iter, nbusy, pbusy; 366131481Sjhb#ifndef PREEMPTION 36765707Sjasone int subiter; 368131481Sjhb#endif 36917658Sjulian 37017658Sjulian waittime = 0; 37117658Sjulian 372221173Sattilio wdog_kern_pat(WD_LASTVAL); 373225617Skmacy sys_sync(curthread, NULL); 37417658Sjulian 37534266Sjulian /* 37634266Sjulian * With soft updates, some buffers that are 37734266Sjulian * written will be remarked as dirty until other 37834266Sjulian * buffers are written. 37934266Sjulian */ 38065707Sjasone for (iter = pbusy = 0; iter < 20; iter++) { 38117658Sjulian nbusy = 0; 382149875Struckman for (bp = &buf[nbuf]; --bp >= buf; ) 383149875Struckman if (isbufbusy(bp)) 38417658Sjulian nbusy++; 385133763Struckman if (nbusy == 0) { 386133763Struckman if (first_buf_printf) 387136115Sphk printf("All buffers synced."); 38817658Sjulian break; 389133763Struckman } 390133763Struckman if (first_buf_printf) { 391133763Struckman printf("Syncing disks, buffers remaining... "); 392133763Struckman first_buf_printf = 0; 393133763Struckman } 39417658Sjulian printf("%d ", nbusy); 39565707Sjasone if (nbusy < pbusy) 39665707Sjasone iter = 0; 39765707Sjasone pbusy = nbusy; 398236503Savg 399221173Sattilio wdog_kern_pat(WD_LASTVAL); 400225617Skmacy sys_sync(curthread, NULL); 401131481Sjhb 402131481Sjhb#ifdef PREEMPTION 403131481Sjhb /* 404131481Sjhb * Drop Giant and spin for a while to allow 405131481Sjhb * interrupt threads to run. 406131481Sjhb */ 407131481Sjhb DROP_GIANT(); 40834266Sjulian DELAY(50000 * iter); 409131481Sjhb PICKUP_GIANT(); 410131481Sjhb#else 411131481Sjhb /* 412131481Sjhb * Drop Giant and context switch several times to 413131481Sjhb * allow interrupt threads to run. 414131481Sjhb */ 415131481Sjhb DROP_GIANT(); 416131481Sjhb for (subiter = 0; subiter < 50 * iter; subiter++) { 417170307Sjeff thread_lock(curthread); 418131481Sjhb mi_switch(SW_VOL, NULL); 419170307Sjeff thread_unlock(curthread); 420131481Sjhb DELAY(1000); 421131481Sjhb } 422131481Sjhb PICKUP_GIANT(); 423131481Sjhb#endif 42417658Sjulian } 425133418Snjl printf("\n"); 42641137Smsmith /* 42741137Smsmith * Count only busy local buffers to prevent forcing 42841137Smsmith * a fsck if we're just a client of a wedged NFS server 42941137Smsmith */ 43041137Smsmith nbusy = 0; 43141137Smsmith for (bp = &buf[nbuf]; --bp >= buf; ) { 432149875Struckman if (isbufbusy(bp)) { 433137186Sphk#if 0 434137186Sphk/* XXX: This is bogus. We should probably have a BO_REMOTE flag instead */ 435130640Sphk if (bp->b_dev == NULL) { 43653452Sphk TAILQ_REMOVE(&mountlist, 43748225Smckusick bp->b_vp->v_mount, mnt_list); 43853023Sphk continue; 43953023Sphk } 440137186Sphk#endif 44153023Sphk nbusy++; 442225448Sattilio if (show_busybufs > 0) { 443225448Sattilio printf( 444225448Sattilio "%d: buf:%p, vnode:%p, flags:%0x, blkno:%jd, lblkno:%jd, buflock:", 445225448Sattilio nbusy, bp, bp->b_vp, bp->b_flags, 446225448Sattilio (intmax_t)bp->b_blkno, 447225448Sattilio (intmax_t)bp->b_lblkno); 448225448Sattilio BUF_LOCKPRINTINFO(bp); 449225448Sattilio if (show_busybufs > 1) 450225448Sattilio vn_printf(bp->b_vp, 451225448Sattilio "vnode content: "); 452225448Sattilio } 45346568Speter } 45441137Smsmith } 45517658Sjulian if (nbusy) { 45617658Sjulian /* 45717658Sjulian * Failed to sync all blocks. Indicate this and don't 45817658Sjulian * unmount filesystems (thus forcing an fsck on reboot). 45917658Sjulian */ 460133763Struckman printf("Giving up on %d buffers\n", nbusy); 46117658Sjulian DELAY(5000000); /* 5 seconds */ 46217658Sjulian } else { 463133763Struckman if (!first_buf_printf) 464133763Struckman printf("Final sync complete\n"); 46517658Sjulian /* 46617658Sjulian * Unmount filesystems 46717658Sjulian */ 46817658Sjulian if (panicstr == 0) 46917658Sjulian vfs_unmountall(); 47017658Sjulian } 471157628Spjd swapoff_all(); 47239237Sgibbs DELAY(100000); /* wait for console output to finish */ 47317658Sjulian } 47427997Sjulian 47554233Sphk print_uptime(); 47654233Sphk 477228632Savg cngrab(); 478228632Savg 47927997Sjulian /* 48027997Sjulian * Ok, now do things that assume all filesystem activity has 48127997Sjulian * been completed. 48227997Sjulian */ 48350107Smsmith EVENTHANDLER_INVOKE(shutdown_post_sync, howto); 484137329Snjl 485132412Sjulian if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold && !dumping) 486222801Smarcel doadump(TRUE); 48739237Sgibbs 48839237Sgibbs /* Now that we're going to really halt the system... */ 48950107Smsmith EVENTHANDLER_INVOKE(shutdown_final, howto); 49039237Sgibbs 49150107Smsmith for(;;) ; /* safety against shutdown_reset not working */ 49250107Smsmith /* NOTREACHED */ 49350107Smsmith} 49450107Smsmith 49550107Smsmith/* 496293743Strasz * The system call that results in changing the rootfs. 497293743Strasz */ 498293743Straszstatic int 499293743Straszkern_reroot(void) 500293743Strasz{ 501293743Strasz struct vnode *oldrootvnode, *vp; 502293743Strasz struct mount *mp, *devmp; 503293743Strasz int error; 504293743Strasz 505293743Strasz if (curproc != initproc) 506293743Strasz return (EPERM); 507293743Strasz 508293743Strasz /* 509293743Strasz * Mark the filesystem containing currently-running executable 510293743Strasz * (the temporary copy of init(8)) busy. 511293743Strasz */ 512293743Strasz vp = curproc->p_textvp; 513293743Strasz error = vn_lock(vp, LK_SHARED); 514293743Strasz if (error != 0) 515293743Strasz return (error); 516293743Strasz mp = vp->v_mount; 517293743Strasz error = vfs_busy(mp, MBF_NOWAIT); 518293743Strasz if (error != 0) { 519293743Strasz vfs_ref(mp); 520293743Strasz VOP_UNLOCK(vp, 0); 521293743Strasz error = vfs_busy(mp, 0); 522293743Strasz vn_lock(vp, LK_SHARED | LK_RETRY); 523293743Strasz vfs_rel(mp); 524293743Strasz if (error != 0) { 525293743Strasz VOP_UNLOCK(vp, 0); 526293743Strasz return (ENOENT); 527293743Strasz } 528293743Strasz if (vp->v_iflag & VI_DOOMED) { 529293743Strasz VOP_UNLOCK(vp, 0); 530293743Strasz vfs_unbusy(mp); 531293743Strasz return (ENOENT); 532293743Strasz } 533293743Strasz } 534293743Strasz VOP_UNLOCK(vp, 0); 535293743Strasz 536293743Strasz /* 537293743Strasz * Remove the filesystem containing currently-running executable 538293743Strasz * from the mount list, to prevent it from being unmounted 539293743Strasz * by vfs_unmountall(), and to avoid confusing vfs_mountroot(). 540293743Strasz * 541293743Strasz * Also preserve /dev - forcibly unmounting it could cause driver 542293743Strasz * reinitialization. 543293743Strasz */ 544293743Strasz 545293743Strasz vfs_ref(rootdevmp); 546293743Strasz devmp = rootdevmp; 547293743Strasz rootdevmp = NULL; 548293743Strasz 549293743Strasz mtx_lock(&mountlist_mtx); 550293743Strasz TAILQ_REMOVE(&mountlist, mp, mnt_list); 551293743Strasz TAILQ_REMOVE(&mountlist, devmp, mnt_list); 552293743Strasz mtx_unlock(&mountlist_mtx); 553293743Strasz 554293743Strasz oldrootvnode = rootvnode; 555293743Strasz 556293743Strasz /* 557293743Strasz * Unmount everything except for the two filesystems preserved above. 558293743Strasz */ 559293743Strasz vfs_unmountall(); 560293743Strasz 561293743Strasz /* 562293743Strasz * Add /dev back; vfs_mountroot() will move it into its new place. 563293743Strasz */ 564293743Strasz mtx_lock(&mountlist_mtx); 565293743Strasz TAILQ_INSERT_HEAD(&mountlist, devmp, mnt_list); 566293743Strasz mtx_unlock(&mountlist_mtx); 567293743Strasz rootdevmp = devmp; 568293743Strasz vfs_rel(rootdevmp); 569293743Strasz 570293743Strasz /* 571293743Strasz * Mount the new rootfs. 572293743Strasz */ 573293743Strasz vfs_mountroot(); 574293743Strasz 575293743Strasz /* 576293743Strasz * Update all references to the old rootvnode. 577293743Strasz */ 578293743Strasz mountcheckdirs(oldrootvnode, rootvnode); 579293743Strasz 580293743Strasz /* 581293743Strasz * Add the temporary filesystem back and unbusy it. 582293743Strasz */ 583293743Strasz mtx_lock(&mountlist_mtx); 584293743Strasz TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 585293743Strasz mtx_unlock(&mountlist_mtx); 586293743Strasz vfs_unbusy(mp); 587293743Strasz 588293743Strasz return (0); 589293743Strasz} 590293743Strasz 591293743Strasz/* 59250107Smsmith * If the shutdown was a clean halt, behave accordingly. 59350107Smsmith */ 59450107Smsmithstatic void 59550107Smsmithshutdown_halt(void *junk, int howto) 59650107Smsmith{ 597110859Salfred 59817658Sjulian if (howto & RB_HALT) { 59917658Sjulian printf("\n"); 60017658Sjulian printf("The operating system has halted.\n"); 60117658Sjulian printf("Please press any key to reboot.\n\n"); 60219274Sjulian switch (cngetc()) { 60319274Sjulian case -1: /* No console, just die */ 60419274Sjulian cpu_halt(); 60519274Sjulian /* NOTREACHED */ 60619274Sjulian default: 60739237Sgibbs howto &= ~RB_HALT; 60819274Sjulian break; 60919274Sjulian } 61050107Smsmith } 61150107Smsmith} 61217658Sjulian 61350107Smsmith/* 61450107Smsmith * Check to see if the system paniced, pause and then reboot 61550107Smsmith * according to the specified delay. 61650107Smsmith */ 61750107Smsmithstatic void 61850107Smsmithshutdown_panic(void *junk, int howto) 61950107Smsmith{ 62050107Smsmith int loop; 62150107Smsmith 62250107Smsmith if (howto & RB_DUMP) { 623260431Scperciva if (panic_reboot_wait_time != 0) { 624260431Scperciva if (panic_reboot_wait_time != -1) { 62539237Sgibbs printf("Automatic reboot in %d seconds - " 62639237Sgibbs "press a key on the console to abort\n", 627260431Scperciva panic_reboot_wait_time); 628260431Scperciva for (loop = panic_reboot_wait_time * 10; 62939237Sgibbs loop > 0; --loop) { 63039237Sgibbs DELAY(1000 * 100); /* 1/10th second */ 63139237Sgibbs /* Did user type a key? */ 63239237Sgibbs if (cncheckc() != -1) 63339237Sgibbs break; 63417658Sjulian } 63539237Sgibbs if (!loop) 63650107Smsmith return; 63717658Sjulian } 63839237Sgibbs } else { /* zero time specified - reboot NOW */ 63950107Smsmith return; 64017658Sjulian } 64189522Snik printf("--> Press a key on the console to reboot,\n"); 64289522Snik printf("--> or switch off the system now.\n"); 64339237Sgibbs cngetc(); 64417658Sjulian } 64550107Smsmith} 64650107Smsmith 64750107Smsmith/* 64850107Smsmith * Everything done, now reset 64950107Smsmith */ 65050107Smsmithstatic void 65150107Smsmithshutdown_reset(void *junk, int howto) 65250107Smsmith{ 653110859Salfred 654206878Sattilio printf("Rebooting...\n"); 655206878Sattilio DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ 656206878Sattilio 657196196Sattilio /* 658206878Sattilio * Acquiring smp_ipi_mtx here has a double effect: 659206878Sattilio * - it disables interrupts avoiding CPU0 preemption 660206878Sattilio * by fast handlers (thus deadlocking against other CPUs) 661206878Sattilio * - it avoids deadlocks against smp_rendezvous() or, more 662206878Sattilio * generally, threads busy-waiting, with this spinlock held, 663206878Sattilio * and waiting for responses by threads on other CPUs 664206878Sattilio * (ie. smp_tlb_shootdown()). 665206897Sattilio * 666206897Sattilio * For the !SMP case it just needs to handle the former problem. 667196196Sattilio */ 668206897Sattilio#ifdef SMP 669206878Sattilio mtx_lock_spin(&smp_ipi_mtx); 670206897Sattilio#else 671206897Sattilio spinlock_enter(); 672206897Sattilio#endif 673196196Sattilio 67417677Sjulian /* cpu_boot(howto); */ /* doesn't do anything at the moment */ 67517658Sjulian cpu_reset(); 67650107Smsmith /* NOTREACHED */ /* assuming reset worked */ 67717658Sjulian} 67817658Sjulian 679244105Salfred#if defined(WITNESS) || defined(INVARIANTS) 680243980Salfredstatic int kassert_warn_only = 0; 681244099Salfred#ifdef KDB 682244099Salfredstatic int kassert_do_kdb = 0; 683244099Salfred#endif 684243980Salfred#ifdef KTR 685243980Salfredstatic int kassert_do_ktr = 0; 686243980Salfred#endif 687243980Salfredstatic int kassert_do_log = 1; 688243980Salfredstatic int kassert_log_pps_limit = 4; 689243980Salfredstatic int kassert_log_mute_at = 0; 690243980Salfredstatic int kassert_log_panic_at = 0; 691243980Salfredstatic int kassert_warnings = 0; 692243980Salfred 693243980SalfredSYSCTL_NODE(_debug, OID_AUTO, kassert, CTLFLAG_RW, NULL, "kassert options"); 694243980Salfred 695243980SalfredSYSCTL_INT(_debug_kassert, OID_AUTO, warn_only, CTLFLAG_RW | CTLFLAG_TUN, 696243980Salfred &kassert_warn_only, 0, 697243980Salfred "KASSERT triggers a panic (1) or just a warning (0)"); 698243980SalfredTUNABLE_INT("debug.kassert.warn_only", &kassert_warn_only); 699243980Salfred 700244099Salfred#ifdef KDB 701244099SalfredSYSCTL_INT(_debug_kassert, OID_AUTO, do_kdb, CTLFLAG_RW | CTLFLAG_TUN, 702244099Salfred &kassert_do_kdb, 0, "KASSERT will enter the debugger"); 703244099SalfredTUNABLE_INT("debug.kassert.do_kdb", &kassert_do_kdb); 704244099Salfred#endif 705244099Salfred 706243980Salfred#ifdef KTR 707243980SalfredSYSCTL_UINT(_debug_kassert, OID_AUTO, do_ktr, CTLFLAG_RW | CTLFLAG_TUN, 708243980Salfred &kassert_do_ktr, 0, 709243980Salfred "KASSERT does a KTR, set this to the KTRMASK you want"); 710243980SalfredTUNABLE_INT("debug.kassert.do_ktr", &kassert_do_ktr); 711243980Salfred#endif 712243980Salfred 713243980SalfredSYSCTL_INT(_debug_kassert, OID_AUTO, do_log, CTLFLAG_RW | CTLFLAG_TUN, 714243980Salfred &kassert_do_log, 0, "KASSERT triggers a panic (1) or just a warning (0)"); 715243980SalfredTUNABLE_INT("debug.kassert.do_log", &kassert_do_log); 716243980Salfred 717243980SalfredSYSCTL_INT(_debug_kassert, OID_AUTO, warnings, CTLFLAG_RW | CTLFLAG_TUN, 718243980Salfred &kassert_warnings, 0, "number of KASSERTs that have been triggered"); 719243980SalfredTUNABLE_INT("debug.kassert.warnings", &kassert_warnings); 720243980Salfred 721243980SalfredSYSCTL_INT(_debug_kassert, OID_AUTO, log_panic_at, CTLFLAG_RW | CTLFLAG_TUN, 722243980Salfred &kassert_log_panic_at, 0, "max number of KASSERTS before we will panic"); 723243980SalfredTUNABLE_INT("debug.kassert.log_panic_at", &kassert_log_panic_at); 724243980Salfred 725243980SalfredSYSCTL_INT(_debug_kassert, OID_AUTO, log_pps_limit, CTLFLAG_RW | CTLFLAG_TUN, 726243980Salfred &kassert_log_pps_limit, 0, "limit number of log messages per second"); 727243980SalfredTUNABLE_INT("debug.kassert.log_pps_limit", &kassert_log_pps_limit); 728243980Salfred 729243980SalfredSYSCTL_INT(_debug_kassert, OID_AUTO, log_mute_at, CTLFLAG_RW | CTLFLAG_TUN, 730243980Salfred &kassert_log_mute_at, 0, "max number of KASSERTS to log"); 731243980SalfredTUNABLE_INT("debug.kassert.log_mute_at", &kassert_log_mute_at); 732243980Salfred 733243980Salfredstatic int kassert_sysctl_kassert(SYSCTL_HANDLER_ARGS); 734243980Salfred 735243980SalfredSYSCTL_PROC(_debug_kassert, OID_AUTO, kassert, 736243980Salfred CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, NULL, 0, 737243980Salfred kassert_sysctl_kassert, "I", "set to trigger a test kassert"); 738243980Salfred 739243980Salfredstatic int 740243980Salfredkassert_sysctl_kassert(SYSCTL_HANDLER_ARGS) 741243980Salfred{ 742243980Salfred int error, i; 743243980Salfred 744243980Salfred error = sysctl_wire_old_buffer(req, sizeof(int)); 745243980Salfred if (error == 0) { 746243980Salfred i = 0; 747243980Salfred error = sysctl_handle_int(oidp, &i, 0, req); 748243980Salfred } 749243980Salfred if (error != 0 || req->newptr == NULL) 750243980Salfred return (error); 751243980Salfred KASSERT(0, ("kassert_sysctl_kassert triggered kassert %d", i)); 752243980Salfred return (0); 753243980Salfred} 754243980Salfred 75517658Sjulian/* 756243980Salfred * Called by KASSERT, this decides if we will panic 757243980Salfred * or if we will log via printf and/or ktr. 758243980Salfred */ 759243980Salfredvoid 760243980Salfredkassert_panic(const char *fmt, ...) 761243980Salfred{ 762243980Salfred static char buf[256]; 763243980Salfred va_list ap; 764243980Salfred 765243980Salfred va_start(ap, fmt); 766243980Salfred (void)vsnprintf(buf, sizeof(buf), fmt, ap); 767243980Salfred va_end(ap); 768243980Salfred 769243980Salfred /* 770243980Salfred * panic if we're not just warning, or if we've exceeded 771243980Salfred * kassert_log_panic_at warnings. 772243980Salfred */ 773243980Salfred if (!kassert_warn_only || 774243980Salfred (kassert_log_panic_at > 0 && 775243980Salfred kassert_warnings >= kassert_log_panic_at)) { 776243980Salfred va_start(ap, fmt); 777243980Salfred vpanic(fmt, ap); 778243980Salfred /* NORETURN */ 779243980Salfred } 780243980Salfred#ifdef KTR 781243980Salfred if (kassert_do_ktr) 782243980Salfred CTR0(ktr_mask, buf); 783243980Salfred#endif /* KTR */ 784243980Salfred /* 785243980Salfred * log if we've not yet met the mute limit. 786243980Salfred */ 787243980Salfred if (kassert_do_log && 788243980Salfred (kassert_log_mute_at == 0 || 789243980Salfred kassert_warnings < kassert_log_mute_at)) { 790243980Salfred static struct timeval lasterr; 791243980Salfred static int curerr; 792243980Salfred 793243980Salfred if (ppsratecheck(&lasterr, &curerr, kassert_log_pps_limit)) { 794243980Salfred printf("KASSERT failed: %s\n", buf); 795243980Salfred kdb_backtrace(); 796243980Salfred } 797243980Salfred } 798244099Salfred#ifdef KDB 799244099Salfred if (kassert_do_kdb) { 800244099Salfred kdb_enter(KDB_WHY_KASSERT, buf); 801244099Salfred } 802244099Salfred#endif 803243980Salfred atomic_add_int(&kassert_warnings, 1); 804243980Salfred} 805243980Salfred#endif 806243980Salfred 807243980Salfred/* 80817658Sjulian * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 80917658Sjulian * and then reboots. If we are called twice, then we avoid trying to sync 81017658Sjulian * the disks as this often leads to recursive panics. 81117658Sjulian */ 81217658Sjulianvoid 813130164Sphkpanic(const char *fmt, ...) 81417658Sjulian{ 815243980Salfred va_list ap; 816243980Salfred 817243980Salfred va_start(ap, fmt); 818243980Salfred vpanic(fmt, ap); 819243980Salfred} 820243980Salfred 821283676Smarkjvoid 822243980Salfredvpanic(const char *fmt, va_list ap) 823243980Salfred{ 824213648Savg#ifdef SMP 825228424Savg cpuset_t other_cpus; 826213648Savg#endif 827100209Sgallatin struct thread *td = curthread; 828103647Sjhb int bootopt, newpanic; 82938874Sache static char buf[256]; 83017658Sjulian 831243515Savg spinlock_enter(); 832228424Savg 83365557Sjasone#ifdef SMP 83482115Sjhb /* 835243515Savg * stop_cpus_hard(other_cpus) should prevent multiple CPUs from 836243515Savg * concurrently entering panic. Only the winner will proceed 837243515Savg * further. 83882115Sjhb */ 839243515Savg if (panicstr == NULL && !kdb_active) { 840243515Savg other_cpus = all_cpus; 841243515Savg CPU_CLR(PCPU_GET(cpuid), &other_cpus); 842243515Savg stop_cpus_hard(other_cpus); 843243515Savg } 844228424Savg 845243515Savg /* 846243515Savg * We set stop_scheduler here and not in the block above, 847243515Savg * because we want to ensure that if panic has been called and 848243515Savg * stop_scheduler_on_panic is true, then stop_scheduler will 849243515Savg * always be set. Even if panic has been entered from kdb. 850243515Savg */ 851243515Savg td->td_stopsched = 1; 85265557Sjasone#endif 85365557Sjasone 854222865Sattilio bootopt = RB_AUTOBOOT; 855103647Sjhb newpanic = 0; 85617658Sjulian if (panicstr) 85717658Sjulian bootopt |= RB_NOSYNC; 858103647Sjhb else { 859222865Sattilio bootopt |= RB_DUMP; 86017658Sjulian panicstr = fmt; 861103647Sjhb newpanic = 1; 862103647Sjhb } 86317658Sjulian 864116398Siedowse if (newpanic) { 865116398Siedowse (void)vsnprintf(buf, sizeof(buf), fmt, ap); 86638874Sache panicstr = buf; 867228632Savg cngrab(); 868130164Sphk printf("panic: %s\n", buf); 869116398Siedowse } else { 870116398Siedowse printf("panic: "); 871116398Siedowse vprintf(fmt, ap); 872130164Sphk printf("\n"); 873116398Siedowse } 87426100Sfsmp#ifdef SMP 875134089Sjhb printf("cpuid = %d\n", PCPU_GET(cpuid)); 87626100Sfsmp#endif 87717658Sjulian 878131927Smarcel#ifdef KDB 879103647Sjhb if (newpanic && trace_on_panic) 880131927Smarcel kdb_backtrace(); 88117658Sjulian if (debugger_on_panic) 882174898Srwatson kdb_enter(KDB_WHY_PANIC, "panic"); 88317658Sjulian#endif 884170307Sjeff /*thread_lock(td); */ 885100209Sgallatin td->td_flags |= TDF_INPANIC; 886170307Sjeff /* thread_unlock(td); */ 88785202Speter if (!sync_on_panic) 88885202Speter bootopt |= RB_NOSYNC; 889214004Smarcel kern_reboot(bootopt); 89017658Sjulian} 89117658Sjulian 89217768Sjulian/* 89343436Smsmith * Support for poweroff delay. 894197071Sn_hibma * 895197071Sn_hibma * Please note that setting this delay too short might power off your machine 896197071Sn_hibma * before the write cache on your hard disk has been flushed, leading to 897197071Sn_hibma * soft-updates inconsistencies. 89843436Smsmith */ 89954248Smsmith#ifndef POWEROFF_DELAY 90054248Smsmith# define POWEROFF_DELAY 5000 90154248Smsmith#endif 90254248Smsmithstatic int poweroff_delay = POWEROFF_DELAY; 90354248Smsmith 90443436SmsmithSYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW, 905228449Seadler &poweroff_delay, 0, "Delay before poweroff to write disk caches (msec)"); 90643436Smsmith 907110859Salfredstatic void 90850107Smsmithpoweroff_wait(void *junk, int howto) 90943436Smsmith{ 910110859Salfred 911110859Salfred if (!(howto & RB_POWEROFF) || poweroff_delay <= 0) 91243436Smsmith return; 91343436Smsmith DELAY(poweroff_delay * 1000); 91443436Smsmith} 91555539Sluoqi 91655539Sluoqi/* 91755539Sluoqi * Some system processes (e.g. syncer) need to be stopped at appropriate 91855539Sluoqi * points in their main loops prior to a system shutdown, so that they 91955539Sluoqi * won't interfere with the shutdown process (e.g. by holding a disk buf 92055539Sluoqi * to cause sync to fail). For each of these system processes, register 92155539Sluoqi * shutdown_kproc() as a handler for one of shutdown events. 92255539Sluoqi */ 92355539Sluoqistatic int kproc_shutdown_wait = 60; 92455539SluoqiSYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW, 925228449Seadler &kproc_shutdown_wait, 0, "Max wait time (sec) to stop for each process"); 92655539Sluoqi 92755539Sluoqivoid 92870063Sjhbkproc_shutdown(void *arg, int howto) 92955539Sluoqi{ 93055539Sluoqi struct proc *p; 93155539Sluoqi int error; 93255539Sluoqi 93355539Sluoqi if (panicstr) 93455539Sluoqi return; 93555539Sluoqi 93655539Sluoqi p = (struct proc *)arg; 937132866Snjl printf("Waiting (max %d seconds) for system process `%s' to stop...", 938198408Sjhb kproc_shutdown_wait, p->p_comm); 939172836Sjulian error = kproc_suspend(p, kproc_shutdown_wait * hz); 94055539Sluoqi 94155539Sluoqi if (error == EWOULDBLOCK) 942132866Snjl printf("timed out\n"); 94355539Sluoqi else 944132866Snjl printf("done\n"); 94555539Sluoqi} 94693496Sphk 947173004Sjulianvoid 948173004Sjuliankthread_shutdown(void *arg, int howto) 949173004Sjulian{ 950173004Sjulian struct thread *td; 951173004Sjulian int error; 952173004Sjulian 953173004Sjulian if (panicstr) 954173004Sjulian return; 955173004Sjulian 956173004Sjulian td = (struct thread *)arg; 957173004Sjulian printf("Waiting (max %d seconds) for system thread `%s' to stop...", 958198408Sjhb kproc_shutdown_wait, td->td_name); 959173004Sjulian error = kthread_suspend(td, kproc_shutdown_wait * hz); 960173004Sjulian 961173004Sjulian if (error == EWOULDBLOCK) 962173004Sjulian printf("timed out\n"); 963173004Sjulian else 964173004Sjulian printf("done\n"); 965173004Sjulian} 966173004Sjulian 967242439Salfredstatic char dumpdevname[sizeof(((struct cdev*)NULL)->si_name)]; 968242439SalfredSYSCTL_STRING(_kern_shutdown, OID_AUTO, dumpdevname, CTLFLAG_RD, 969242439Salfred dumpdevname, 0, "Device for kernel dumps"); 970242439Salfred 97193496Sphk/* Registration of dumpers */ 97293496Sphkint 973291215Ssmhset_dumper(struct dumperinfo *di, const char *devname, struct thread *td) 97493496Sphk{ 975242489Salfred size_t wantcopy; 976291215Ssmh int error; 977110859Salfred 978291215Ssmh error = priv_check(td, PRIV_SETDUMPER); 979291215Ssmh if (error != 0) 980291215Ssmh return (error); 981291215Ssmh 98293496Sphk if (di == NULL) { 98393496Sphk bzero(&dumper, sizeof dumper); 984242439Salfred dumpdevname[0] = '\0'; 98593496Sphk return (0); 98693496Sphk } 98793496Sphk if (dumper.dumper != NULL) 98893496Sphk return (EBUSY); 98993496Sphk dumper = *di; 990242489Salfred wantcopy = strlcpy(dumpdevname, devname, sizeof(dumpdevname)); 991242489Salfred if (wantcopy >= sizeof(dumpdevname)) { 992242439Salfred printf("set_dumper: device name truncated from '%s' -> '%s'\n", 993242439Salfred devname, dumpdevname); 994242439Salfred } 99593496Sphk return (0); 99693496Sphk} 99793496Sphk 998175768Sru/* Call dumper with bounds checking. */ 999175768Sruint 1000175768Srudump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical, 1001175768Sru off_t offset, size_t length) 1002175768Sru{ 1003175768Sru 1004175768Sru if (length != 0 && (offset < di->mediaoffset || 1005175768Sru offset - di->mediaoffset + length > di->mediasize)) { 1006225516Sattilio printf("Attempt to write outside dump device boundaries.\n" 1007225516Sattilio "offset(%jd), mediaoffset(%jd), length(%ju), mediasize(%jd).\n", 1008225516Sattilio (intmax_t)offset, (intmax_t)di->mediaoffset, 1009225516Sattilio (uintmax_t)length, (intmax_t)di->mediasize); 1010225516Sattilio return (ENOSPC); 1011175768Sru } 1012175768Sru return (di->dumper(di->priv, virtual, physical, offset, length)); 1013175768Sru} 1014175768Sru 101593496Sphkvoid 1016183527Spetermkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver, 1017183527Speter uint64_t dumplen, uint32_t blksz) 1018183527Speter{ 1019183527Speter 1020183527Speter bzero(kdh, sizeof(*kdh)); 1021284191Sasomers strlcpy(kdh->magic, magic, sizeof(kdh->magic)); 1022284191Sasomers strlcpy(kdh->architecture, MACHINE_ARCH, sizeof(kdh->architecture)); 1023183527Speter kdh->version = htod32(KERNELDUMPVERSION); 1024183527Speter kdh->architectureversion = htod32(archver); 1025183527Speter kdh->dumplength = htod64(dumplen); 1026183527Speter kdh->dumptime = htod64(time_second); 1027183527Speter kdh->blocksize = htod32(blksz); 1028284191Sasomers strlcpy(kdh->hostname, prison0.pr_hostname, sizeof(kdh->hostname)); 1029284191Sasomers strlcpy(kdh->versionstring, version, sizeof(kdh->versionstring)); 1030183527Speter if (panicstr != NULL) 1031284191Sasomers strlcpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring)); 1032183527Speter kdh->parity = kerneldump_parity(kdh); 1033183527Speter} 1034305853Shiren 1035305853Shiren#ifdef DDB 1036305853ShirenDB_SHOW_COMMAND(panic, db_show_panic) 1037305853Shiren{ 1038305853Shiren 1039305853Shiren if (panicstr == NULL) 1040305853Shiren db_printf("panicstr not set\n"); 1041305853Shiren else 1042305853Shiren db_printf("panic: %s\n", panicstr); 1043305853Shiren} 1044305853Shiren#endif 1045