kern_shutdown.c (49679) | kern_shutdown.c (50107) |
---|---|
1/*- 2 * Copyright (c) 1986, 1988, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. --- 22 unchanged lines hidden (view full) --- 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94 | 1/*- 2 * Copyright (c) 1986, 1988, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. --- 22 unchanged lines hidden (view full) --- 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94 |
39 * $Id: kern_shutdown.c,v 1.59 1999/08/11 14:02:20 alfred Exp $ | 39 * $Id: kern_shutdown.c,v 1.60 1999/08/13 10:29:21 phk Exp $ |
40 */ 41 42#include "opt_ddb.h" 43#include "opt_hw_wdog.h" 44#include "opt_panic.h" 45#include "opt_show_busybufs.h" 46 47#include <sys/param.h> 48#include <sys/systm.h> | 40 */ 41 42#include "opt_ddb.h" 43#include "opt_hw_wdog.h" 44#include "opt_panic.h" 45#include "opt_show_busybufs.h" 46 47#include <sys/param.h> 48#include <sys/systm.h> |
49#include <sys/eventhandler.h> |
|
49#include <sys/buf.h> 50#include <sys/reboot.h> 51#include <sys/proc.h> 52#include <sys/vnode.h> 53#include <sys/malloc.h> 54#include <sys/kernel.h> 55#include <sys/mount.h> 56#include <sys/queue.h> --- 45 unchanged lines hidden (view full) --- 102#endif /* HW_WDOG */ 103 104/* 105 * Variable panicstr contains argument to first call to panic; used as flag 106 * to indicate that the kernel has already called panic. 107 */ 108const char *panicstr; 109 | 50#include <sys/buf.h> 51#include <sys/reboot.h> 52#include <sys/proc.h> 53#include <sys/vnode.h> 54#include <sys/malloc.h> 55#include <sys/kernel.h> 56#include <sys/mount.h> 57#include <sys/queue.h> --- 45 unchanged lines hidden (view full) --- 103#endif /* HW_WDOG */ 104 105/* 106 * Variable panicstr contains argument to first call to panic; used as flag 107 * to indicate that the kernel has already called panic. 108 */ 109const char *panicstr; 110 |
110/* 111 * callout list for things to do a shutdown 112 */ 113typedef struct shutdown_list_element { 114 LIST_ENTRY(shutdown_list_element) links; 115 bootlist_fn function; 116 void *arg; 117 int priority; 118} *sle_p; 119 120/* 121 * There are three shutdown lists. Some things need to be shut down 122 * earlier than others. 123 */ 124LIST_HEAD(shutdown_list, shutdown_list_element); 125 126static struct shutdown_list shutdown_lists[SHUTDOWN_FINAL + 1]; 127 | |
128static void boot __P((int)) __dead2; 129static void dumpsys __P((void)); 130static int setdumpdev __P((dev_t dev)); | 111static void boot __P((int)) __dead2; 112static void dumpsys __P((void)); 113static int setdumpdev __P((dev_t dev)); |
114static void poweroff_wait __P((void *, int)); 115static void shutdown_halt __P((void *junk, int howto)); 116static void shutdown_panic __P((void *junk, int howto)); 117static void shutdown_reset __P((void *junk, int howto)); |
|
131 | 118 |
119/* register various local shutdown events */ 120static void 121shutdown_conf(void *unused) 122{ 123 EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL, SHUTDOWN_PRI_FIRST); 124 EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL, SHUTDOWN_PRI_LAST + 100); 125 EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL, SHUTDOWN_PRI_LAST + 100); 126 EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL, SHUTDOWN_PRI_LAST + 200); 127} |
|
132 | 128 |
133#ifndef _SYS_SYSPROTO_H_ 134struct reboot_args { 135 int opt; 136}; 137#endif | 129SYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL) 130 |
138/* ARGSUSED */ 139 140/* 141 * The system call that results in a reboot 142 */ 143int 144reboot(p, uap) 145 struct proc *p; --- 30 unchanged lines hidden (view full) --- 176 * Go through the rigmarole of shutting down.. 177 * this used to be in machdep.c but I'll be dammned if I could see 178 * anything machine dependant in it. 179 */ 180static void 181boot(howto) 182 int howto; 183{ | 131/* ARGSUSED */ 132 133/* 134 * The system call that results in a reboot 135 */ 136int 137reboot(p, uap) 138 struct proc *p; --- 30 unchanged lines hidden (view full) --- 169 * Go through the rigmarole of shutting down.. 170 * this used to be in machdep.c but I'll be dammned if I could see 171 * anything machine dependant in it. 172 */ 173static void 174boot(howto) 175 int howto; 176{ |
184 sle_p ep; | |
185 186#ifdef SMP 187 if (smp_active) { 188 printf("boot() called on cpu#%d\n", cpuid); 189 } 190#endif 191 /* 192 * Do any callouts that should be done BEFORE syncing the filesystems. 193 */ | 177 178#ifdef SMP 179 if (smp_active) { 180 printf("boot() called on cpu#%d\n", cpuid); 181 } 182#endif 183 /* 184 * Do any callouts that should be done BEFORE syncing the filesystems. 185 */ |
194 LIST_FOREACH(ep, &shutdown_lists[SHUTDOWN_PRE_SYNC], links) 195 (*ep->function)(howto, ep->arg); | 186 EVENTHANDLER_INVOKE(shutdown_pre_sync, howto); |
196 197 /* 198 * Now sync filesystems 199 */ 200 if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { 201 register struct buf *bp; 202 int iter, nbusy; 203 --- 73 unchanged lines hidden (view full) --- 277 } 278 DELAY(100000); /* wait for console output to finish */ 279 } 280 281 /* 282 * Ok, now do things that assume all filesystem activity has 283 * been completed. 284 */ | 187 188 /* 189 * Now sync filesystems 190 */ 191 if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { 192 register struct buf *bp; 193 int iter, nbusy; 194 --- 73 unchanged lines hidden (view full) --- 268 } 269 DELAY(100000); /* wait for console output to finish */ 270 } 271 272 /* 273 * Ok, now do things that assume all filesystem activity has 274 * been completed. 275 */ |
285 LIST_FOREACH(ep, &shutdown_lists[SHUTDOWN_POST_SYNC], links) 286 (*ep->function)(howto, ep->arg); | 276 EVENTHANDLER_INVOKE(shutdown_post_sync, howto); |
287 splhigh(); 288 if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold) { 289 savectx(&dumppcb); 290#ifdef __i386__ 291 dumppcb.pcb_cr3 = rcr3(); 292#endif 293 dumpsys(); 294 } 295 296 /* Now that we're going to really halt the system... */ | 277 splhigh(); 278 if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold) { 279 savectx(&dumppcb); 280#ifdef __i386__ 281 dumppcb.pcb_cr3 = rcr3(); 282#endif 283 dumpsys(); 284 } 285 286 /* Now that we're going to really halt the system... */ |
297 LIST_FOREACH(ep, &shutdown_lists[SHUTDOWN_FINAL], links) 298 (*ep->function)(howto, ep->arg); | 287 EVENTHANDLER_INVOKE(shutdown_final, howto); |
299 | 288 |
289 for(;;) ; /* safety against shutdown_reset not working */ 290 /* NOTREACHED */ 291} 292 293/* 294 * If the shutdown was a clean halt, behave accordingly. 295 */ 296static void 297shutdown_halt(void *junk, int howto) 298{ |
|
300 if (howto & RB_HALT) { 301 printf("\n"); 302 printf("The operating system has halted.\n"); 303 printf("Please press any key to reboot.\n\n"); 304 switch (cngetc()) { 305 case -1: /* No console, just die */ 306 cpu_halt(); 307 /* NOTREACHED */ 308 default: 309 howto &= ~RB_HALT; 310 break; 311 } | 299 if (howto & RB_HALT) { 300 printf("\n"); 301 printf("The operating system has halted.\n"); 302 printf("Please press any key to reboot.\n\n"); 303 switch (cngetc()) { 304 case -1: /* No console, just die */ 305 cpu_halt(); 306 /* NOTREACHED */ 307 default: 308 howto &= ~RB_HALT; 309 break; 310 } |
312 } else if (howto & RB_DUMP) { 313 /* System Paniced */ | 311 } 312} |
314 | 313 |
314/* 315 * Check to see if the system paniced, pause and then reboot 316 * according to the specified delay. 317 */ 318static void 319shutdown_panic(void *junk, int howto) 320{ 321 int loop; 322 323 if (howto & RB_DUMP) { |
|
315 if (PANIC_REBOOT_WAIT_TIME != 0) { 316 if (PANIC_REBOOT_WAIT_TIME != -1) { | 324 if (PANIC_REBOOT_WAIT_TIME != 0) { 325 if (PANIC_REBOOT_WAIT_TIME != -1) { |
317 int loop; | |
318 printf("Automatic reboot in %d seconds - " 319 "press a key on the console to abort\n", 320 PANIC_REBOOT_WAIT_TIME); 321 for (loop = PANIC_REBOOT_WAIT_TIME * 10; 322 loop > 0; --loop) { 323 DELAY(1000 * 100); /* 1/10th second */ 324 /* Did user type a key? */ 325 if (cncheckc() != -1) 326 break; 327 } 328 if (!loop) | 326 printf("Automatic reboot in %d seconds - " 327 "press a key on the console to abort\n", 328 PANIC_REBOOT_WAIT_TIME); 329 for (loop = PANIC_REBOOT_WAIT_TIME * 10; 330 loop > 0; --loop) { 331 DELAY(1000 * 100); /* 1/10th second */ 332 /* Did user type a key? */ 333 if (cncheckc() != -1) 334 break; 335 } 336 if (!loop) |
329 goto die; | 337 return; |
330 } 331 } else { /* zero time specified - reboot NOW */ | 338 } 339 } else { /* zero time specified - reboot NOW */ |
332 goto die; | 340 return; |
333 } 334 printf("--> Press a key on the console to reboot <--\n"); 335 cngetc(); 336 } | 341 } 342 printf("--> Press a key on the console to reboot <--\n"); 343 cngetc(); 344 } |
337die: | 345} 346 347/* 348 * Everything done, now reset 349 */ 350static void 351shutdown_reset(void *junk, int howto) 352{ |
338 printf("Rebooting...\n"); 339 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ 340 /* cpu_boot(howto); */ /* doesn't do anything at the moment */ 341 cpu_reset(); | 353 printf("Rebooting...\n"); 354 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ 355 /* cpu_boot(howto); */ /* doesn't do anything at the moment */ 356 cpu_reset(); |
342 for(;;) ; 343 /* NOTREACHED */ | 357 /* NOTREACHED */ /* assuming reset worked */ |
344} 345 346/* 347 * Magic number for savecore 348 * 349 * exported (symorder) and used at least by savecore(8) 350 * 351 */ --- 159 unchanged lines hidden (view full) --- 511#if defined(DDB) 512 if (debugger_on_panic) 513 Debugger ("panic"); 514#endif 515 boot(bootopt); 516} 517 518/* | 358} 359 360/* 361 * Magic number for savecore 362 * 363 * exported (symorder) and used at least by savecore(8) 364 * 365 */ --- 159 unchanged lines hidden (view full) --- 525#if defined(DDB) 526 if (debugger_on_panic) 527 Debugger ("panic"); 528#endif 529 boot(bootopt); 530} 531 532/* |
519 * Three routines to handle adding/deleting items on the 520 * shutdown callout lists 521 * 522 * at_shutdown(): 523 * Take the arguments given and put them onto the shutdown callout list. 524 * However first make sure that it's not already there. 525 * returns 0 on success. 526 */ 527int 528at_shutdown(bootlist_fn function, void *arg, int queue) 529{ 530 return(at_shutdown_pri(function, arg, queue, SHUTDOWN_PRI_DEFAULT)); 531} 532 533/* 534 * at_shutdown_pri(): 535 * Take the arguments given and put them onto the shutdown callout list 536 * with the given execution priority. 537 * returns 0 on success. 538 */ 539int 540at_shutdown_pri(bootlist_fn function, void *arg, int queue, int pri) 541{ 542 sle_p op, ep, ip; 543 544 op = NULL; /* shut up gcc */ 545 if (queue < SHUTDOWN_PRE_SYNC 546 || queue > SHUTDOWN_FINAL) { 547 printf("at_shutdown: bad exit callout queue %d specified\n", 548 queue); 549 return (EINVAL); 550 } 551 if (rm_at_shutdown(function, arg)) 552 printf("at_shutdown: exit callout entry was already present\n"); 553 ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT); 554 if (ep == NULL) 555 return (ENOMEM); 556 ep->function = function; 557 ep->arg = arg; 558 ep->priority = pri; 559 560 /* Sort into list of items on this queue */ 561 ip = LIST_FIRST(&shutdown_lists[queue]); 562 if (ip == NULL) { 563 LIST_INSERT_HEAD(&shutdown_lists[queue], ep, links); 564 } else { 565 for (; ip != NULL; op = ip, ip = LIST_NEXT(ip, links)) { 566 if (ep->priority < ip->priority) { 567 LIST_INSERT_BEFORE(ip, ep, links); 568 ep = NULL; 569 break; 570 } 571 } 572 if (ep != NULL) 573 LIST_INSERT_AFTER(op, ep, links); 574 } 575 return (0); 576} 577 578/* 579 * Scan the exit callout lists for the given items and remove them. 580 * Returns the number of items removed. 581 */ 582int 583rm_at_shutdown(bootlist_fn function, void *arg) 584{ 585 sle_p ep; 586 int count; 587 int queue; 588 589 count = 0; 590 for (queue = SHUTDOWN_PRE_SYNC; queue < SHUTDOWN_FINAL; queue++) { 591 LIST_FOREACH(ep, &shutdown_lists[queue], links) { 592 if ((ep->function == function) && (ep->arg == arg)) { 593 LIST_REMOVE(ep, links); 594 free(ep, M_TEMP); 595 count++; 596 } 597 } 598 } 599 return (count); 600} 601 602/* | |
603 * Support for poweroff delay. 604 */ 605static int poweroff_delay = 0; 606SYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW, 607 &poweroff_delay, 0, ""); 608 | 533 * Support for poweroff delay. 534 */ 535static int poweroff_delay = 0; 536SYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW, 537 &poweroff_delay, 0, ""); 538 |
609static void poweroff_wait(int howto, void *unused) | 539static void 540poweroff_wait(void *junk, int howto) |
610{ 611 if(!(howto & RB_POWEROFF) || poweroff_delay <= 0) 612 return; 613 DELAY(poweroff_delay * 1000); 614} | 541{ 542 if(!(howto & RB_POWEROFF) || poweroff_delay <= 0) 543 return; 544 DELAY(poweroff_delay * 1000); 545} |
615 616/* 617 * XXX OK? This implies I know SHUTDOWN_PRI_LAST > SHUTDOWN_PRI_FIRST 618 */ 619static void poweroff_conf(void *unused) 620{ 621 at_shutdown_pri(poweroff_wait, NULL, SHUTDOWN_FINAL, SHUTDOWN_PRI_FIRST); 622} 623 624SYSINIT(poweroff_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, poweroff_conf, NULL) | |