Deleted Added
full compact
kern_shutdown.c (38874) kern_shutdown.c (39237)
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.37 1998/08/23 14:18:08 des Exp $
39 * $Id: kern_shutdown.c,v 1.38 1998/09/06 06:25:04 ache 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>
49#include <sys/buf.h>
50#include <sys/reboot.h>
51#include <sys/proc.h>
52#include <sys/malloc.h>
53#include <sys/kernel.h>
54#include <sys/mount.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/buf.h>
50#include <sys/reboot.h>
51#include <sys/proc.h>
52#include <sys/malloc.h>
53#include <sys/kernel.h>
54#include <sys/mount.h>
55#include <sys/queue.h>
55#include <sys/sysctl.h>
56#include <sys/conf.h>
57#include <sys/sysproto.h>
58
59#include <machine/pcb.h>
60#include <machine/clock.h>
61#include <machine/cons.h>
62#include <machine/md_var.h>

--- 39 unchanged lines hidden (view full) ---

102 * to indicate that the kernel has already called panic.
103 */
104const char *panicstr;
105
106/*
107 * callout list for things to do a shutdown
108 */
109typedef struct shutdown_list_element {
56#include <sys/sysctl.h>
57#include <sys/conf.h>
58#include <sys/sysproto.h>
59
60#include <machine/pcb.h>
61#include <machine/clock.h>
62#include <machine/cons.h>
63#include <machine/md_var.h>

--- 39 unchanged lines hidden (view full) ---

103 * to indicate that the kernel has already called panic.
104 */
105const char *panicstr;
106
107/*
108 * callout list for things to do a shutdown
109 */
110typedef struct shutdown_list_element {
110 struct shutdown_list_element *next;
111 LIST_ENTRY(shutdown_list_element) links;
111 bootlist_fn function;
112 void *arg;
113} *sle_p;
114
115/*
112 bootlist_fn function;
113 void *arg;
114} *sle_p;
115
116/*
116 * there are two shutdown lists. Some things need to be shut down
117 * Earlier than others.
117 * There are three shutdown lists. Some things need to be shut down
118 * earlier than others.
118 */
119 */
119static sle_p shutdown_list1;
120static sle_p shutdown_list2;
120LIST_HEAD(shutdown_list, shutdown_list_element);
121
121
122static struct shutdown_list shutdown_lists[SHUTDOWN_FINAL + 1];
123
122static void boot __P((int)) __dead2;
123static void dumpsys __P((void));
124
125#ifndef _SYS_SYSPROTO_H_
126struct reboot_args {
127 int opt;
128};
129#endif

--- 48 unchanged lines hidden (view full) ---

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 */
124static void boot __P((int)) __dead2;
125static void dumpsys __P((void));
126
127#ifndef _SYS_SYSPROTO_H_
128struct reboot_args {
129 int opt;
130};
131#endif

--- 48 unchanged lines hidden (view full) ---

180#ifdef SMP
181 if (smp_active) {
182 printf("boot() called on cpu#%d\n", cpuid);
183 }
184#endif
185 /*
186 * Do any callouts that should be done BEFORE syncing the filesystems.
187 */
186 ep = shutdown_list1;
187 while (ep) {
188 shutdown_list1 = ep->next;
188 LIST_FOREACH(ep, &shutdown_lists[SHUTDOWN_PRE_SYNC], links)
189 (*ep->function)(howto, ep->arg);
189 (*ep->function)(howto, ep->arg);
190 ep = ep->next;
191 }
192
193 /*
194 * Now sync filesystems
195 */
196 if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
197 register struct buf *bp;
198 int iter, nbusy;
199

--- 5 unchanged lines hidden (view full) ---

205 /*
206 * With soft updates, some buffers that are
207 * written will be remarked as dirty until other
208 * buffers are written.
209 */
210 for (iter = 0; iter < 20; iter++) {
211 nbusy = 0;
212 for (bp = &buf[nbuf]; --bp >= buf; ) {
190
191 /*
192 * Now sync filesystems
193 */
194 if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
195 register struct buf *bp;
196 int iter, nbusy;
197

--- 5 unchanged lines hidden (view full) ---

203 /*
204 * With soft updates, some buffers that are
205 * written will be remarked as dirty until other
206 * buffers are written.
207 */
208 for (iter = 0; iter < 20; iter++) {
209 nbusy = 0;
210 for (bp = &buf[nbuf]; --bp >= buf; ) {
213 if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) {
211 if ((bp->b_flags & (B_BUSY | B_INVAL))
212 == B_BUSY) {
214 nbusy++;
215 } else if ((bp->b_flags & (B_DELWRI | B_INVAL))
216 == B_DELWRI) {
217 /* bawrite(bp);*/
218 nbusy++;
219 }
220 }
221 if (nbusy == 0)

--- 6 unchanged lines hidden (view full) ---

228 /*
229 * Failed to sync all blocks. Indicate this and don't
230 * unmount filesystems (thus forcing an fsck on reboot).
231 */
232 printf("giving up\n");
233#ifdef SHOW_BUSYBUFS
234 nbusy = 0;
235 for (bp = &buf[nbuf]; --bp >= buf; ) {
213 nbusy++;
214 } else if ((bp->b_flags & (B_DELWRI | B_INVAL))
215 == B_DELWRI) {
216 /* bawrite(bp);*/
217 nbusy++;
218 }
219 }
220 if (nbusy == 0)

--- 6 unchanged lines hidden (view full) ---

227 /*
228 * Failed to sync all blocks. Indicate this and don't
229 * unmount filesystems (thus forcing an fsck on reboot).
230 */
231 printf("giving up\n");
232#ifdef SHOW_BUSYBUFS
233 nbusy = 0;
234 for (bp = &buf[nbuf]; --bp >= buf; ) {
236 if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) {
235 if ((bp->b_flags & (B_BUSY | B_INVAL))
236 == B_BUSY) {
237 nbusy++;
238 printf(
239 "%d: dev:%08lx, flags:%08lx, blkno:%ld, lblkno:%ld\n",
240 nbusy, (u_long)bp->b_dev,
241 bp->b_flags, (long)bp->b_blkno,
242 (long)bp->b_lblkno);
243 }
244 }
245 DELAY(5000000); /* 5 seconds */
246#endif
247 } else {
248 printf("done\n");
249 /*
250 * Unmount filesystems
251 */
252 if (panicstr == 0)
253 vfs_unmountall();
254 }
237 nbusy++;
238 printf(
239 "%d: dev:%08lx, flags:%08lx, blkno:%ld, lblkno:%ld\n",
240 nbusy, (u_long)bp->b_dev,
241 bp->b_flags, (long)bp->b_blkno,
242 (long)bp->b_lblkno);
243 }
244 }
245 DELAY(5000000); /* 5 seconds */
246#endif
247 } else {
248 printf("done\n");
249 /*
250 * Unmount filesystems
251 */
252 if (panicstr == 0)
253 vfs_unmountall();
254 }
255 DELAY(100000); /* wait for console output to finish */
255 DELAY(100000); /* wait for console output to finish */
256 }
257
258 /*
259 * Ok, now do things that assume all filesystem activity has
260 * been completed.
261 */
256 }
257
258 /*
259 * Ok, now do things that assume all filesystem activity has
260 * been completed.
261 */
262 ep = shutdown_list2;
263 while (ep) {
264 shutdown_list2 = ep->next;
262 LIST_FOREACH(ep, &shutdown_lists[SHUTDOWN_POST_SYNC], links)
265 (*ep->function)(howto, ep->arg);
263 (*ep->function)(howto, ep->arg);
266 ep = ep->next;
267 }
268 splhigh();
264 splhigh();
265 if ((howto & (RB_HALT|RB_DUMP) == RB_DUMP) && !cold) {
266 savectx(&dumppcb);
267#ifdef __i386__
268 dumppcb.pcb_cr3 = rcr3();
269#endif
270 dumpsys();
271 }
272
273 /* Now that we're going to really halt the system... */
274 LIST_FOREACH(ep, &shutdown_lists[SHUTDOWN_FINAL], links)
275 (*ep->function)(howto, ep->arg);
276
269 if (howto & RB_HALT) {
270 cpu_power_down();
271 printf("\n");
272 printf("The operating system has halted.\n");
273 printf("Please press any key to reboot.\n\n");
274 switch (cngetc()) {
275 case -1: /* No console, just die */
276 cpu_halt();
277 /* NOTREACHED */
278 default:
277 if (howto & RB_HALT) {
278 cpu_power_down();
279 printf("\n");
280 printf("The operating system has halted.\n");
281 printf("Please press any key to reboot.\n\n");
282 switch (cngetc()) {
283 case -1: /* No console, just die */
284 cpu_halt();
285 /* NOTREACHED */
286 default:
287 howto &= ~RB_HALT;
279 break;
280 }
288 break;
289 }
281 } else {
282 if (howto & RB_DUMP) {
283 if (!cold) {
284 savectx(&dumppcb);
285#ifdef __i386__
286 dumppcb.pcb_cr3 = rcr3();
287#endif
288 dumpsys();
289 }
290 } else if (howto & RB_DUMP) {
291 /* System Paniced */
290
292
291 if (PANIC_REBOOT_WAIT_TIME != 0) {
292 if (PANIC_REBOOT_WAIT_TIME != -1) {
293 int loop;
294 printf("Automatic reboot in %d seconds - press a key on the console to abort\n",
295 PANIC_REBOOT_WAIT_TIME);
296 for (loop = PANIC_REBOOT_WAIT_TIME * 10; loop > 0; --loop) {
297 DELAY(1000 * 100); /* 1/10th second */
298 /* Did user type a key? */
299 if (cncheckc() != -1)
300 break;
301 }
302 if (!loop)
303 goto die;
293 if (PANIC_REBOOT_WAIT_TIME != 0) {
294 if (PANIC_REBOOT_WAIT_TIME != -1) {
295 int loop;
296 printf("Automatic reboot in %d seconds - "
297 "press a key on the console to abort\n",
298 PANIC_REBOOT_WAIT_TIME);
299 for (loop = PANIC_REBOOT_WAIT_TIME * 10;
300 loop > 0; --loop) {
301 DELAY(1000 * 100); /* 1/10th second */
302 /* Did user type a key? */
303 if (cncheckc() != -1)
304 break;
304 }
305 }
305 } else { /* zero time specified - reboot NOW */
306 goto die;
306 if (!loop)
307 goto die;
307 }
308 }
308 printf("--> Press a key on the console to reboot <--\n");
309 cngetc();
309 } else { /* zero time specified - reboot NOW */
310 goto die;
310 }
311 }
312 printf("--> Press a key on the console to reboot <--\n");
313 cngetc();
311 }
312die:
313 printf("Rebooting...\n");
314 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */
315 /* cpu_boot(howto); */ /* doesn't do anything at the moment */
316 cpu_reset();
317 for(;;) ;
318 /* NOTREACHED */

--- 113 unchanged lines hidden (view full) ---

432 * shutdown callout lists
433 *
434 * at_shutdown():
435 * Take the arguments given and put them onto the shutdown callout list.
436 * However first make sure that it's not already there.
437 * returns 0 on success.
438 */
439int
314 }
315die:
316 printf("Rebooting...\n");
317 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */
318 /* cpu_boot(howto); */ /* doesn't do anything at the moment */
319 cpu_reset();
320 for(;;) ;
321 /* NOTREACHED */

--- 113 unchanged lines hidden (view full) ---

435 * shutdown callout lists
436 *
437 * at_shutdown():
438 * Take the arguments given and put them onto the shutdown callout list.
439 * However first make sure that it's not already there.
440 * returns 0 on success.
441 */
442int
440at_shutdown(bootlist_fn function, void *arg, int position)
443at_shutdown(bootlist_fn function, void *arg, int queue)
441{
444{
442 sle_p ep, *epp;
445 sle_p ep;
443
446
444 switch(position) {
445 case SHUTDOWN_PRE_SYNC:
446 epp = &shutdown_list1;
447 break;
448 case SHUTDOWN_POST_SYNC:
449 epp = &shutdown_list2;
450 break;
451 default:
452 printf("bad exit callout list specified\n");
447 if (queue < SHUTDOWN_PRE_SYNC
448 || queue > SHUTDOWN_FINAL) {
449 printf("at_shutdown: bad exit callout queue %d specified\n",
450 queue);
453 return (EINVAL);
454 }
455 if (rm_at_shutdown(function, arg))
451 return (EINVAL);
452 }
453 if (rm_at_shutdown(function, arg))
456 printf("exit callout entry already present\n");
454 printf("at_shutdown: exit callout entry was already present\n");
457 ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT);
458 if (ep == NULL)
459 return (ENOMEM);
455 ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT);
456 if (ep == NULL)
457 return (ENOMEM);
460 ep->next = *epp;
461 ep->function = function;
462 ep->arg = arg;
458 ep->function = function;
459 ep->arg = arg;
463 *epp = ep;
460 LIST_INSERT_HEAD(&shutdown_lists[queue], ep, links);
464 return (0);
465}
466
467/*
468 * Scan the exit callout lists for the given items and remove them.
469 * Returns the number of items removed.
470 */
471int
472rm_at_shutdown(bootlist_fn function, void *arg)
473{
461 return (0);
462}
463
464/*
465 * Scan the exit callout lists for the given items and remove them.
466 * Returns the number of items removed.
467 */
468int
469rm_at_shutdown(bootlist_fn function, void *arg)
470{
474 sle_p *epp, ep;
475 int count;
471 sle_p ep;
472 int count;
473 int queue;
476
477 count = 0;
474
475 count = 0;
478 epp = &shutdown_list1;
479 ep = *epp;
480 while (ep) {
481 if ((ep->function == function) && (ep->arg == arg)) {
482 *epp = ep->next;
483 free(ep, M_TEMP);
484 count++;
485 } else {
486 epp = &ep->next;
476 for (queue = SHUTDOWN_PRE_SYNC; queue < SHUTDOWN_FINAL; queue++) {
477 LIST_FOREACH(ep, &shutdown_lists[queue], links) {
478 if ((ep->function == function) && (ep->arg == arg)) {
479 LIST_REMOVE(ep, links);
480 free(ep, M_TEMP);
481 count++;
482 }
487 }
483 }
488 ep = *epp;
489 }
484 }
490 epp = &shutdown_list2;
491 ep = *epp;
492 while (ep) {
493 if ((ep->function == function) && (ep->arg == arg)) {
494 *epp = ep->next;
495 free(ep, M_TEMP);
496 count++;
497 } else {
498 epp = &ep->next;
499 }
500 ep = *epp;
501 }
502 return (count);
503}
485 return (count);
486}