Deleted Added
full compact
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)