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} |