The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/kern_shutdown.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  *      File:   bsd/kern/kern_shutdown.c
   27  *
   28  *      Copyright (C) 1989, NeXT, Inc.
   29  *
   30  */
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/kernel.h>
   35 #include <sys/vm.h>
   36 #include <sys/proc.h>
   37 #include <sys/user.h>
   38 #include <sys/buf.h>
   39 #include <sys/reboot.h>
   40 #include <sys/conf.h>
   41 #include <sys/vnode.h>
   42 #include <sys/file.h>
   43 #include <sys/clist.h>
   44 #include <sys/callout.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/msgbuf.h>
   47 #include <sys/ioctl.h>
   48 #include <sys/signal.h>
   49 #include <sys/tty.h>
   50 #include <kern/task.h>
   51 #include <sys/quota.h>
   52 #include <ufs/ufs/inode.h>
   53 #if     NCPUS > 1
   54 #include <kern/processor.h>
   55 #include <kern/thread.h>
   56 #include <sys/lock.h>
   57 #endif  /* NCPUS > 1 */
   58 #include <vm/vm_kern.h>
   59 #include <mach/vm_param.h>
   60 #include <sys/filedesc.h>
   61 #include <mach/host_reboot.h>
   62 #include <sys/kern_audit.h>
   63 
   64 int     waittime = -1;
   65 
   66 void
   67 boot(paniced, howto, command)
   68         int paniced, howto;
   69         char *command;
   70 {
   71         register int i;
   72         int s;
   73         struct proc *p = current_proc();        /* XXX */
   74         int hostboot_option=0;
   75         int funnel_state;
   76 
   77         static void proc_shutdown();
   78     extern void md_prepare_for_shutdown(int paniced, int howto, char * command);
   79 
   80         funnel_state = thread_funnel_set(kernel_flock, TRUE);
   81 
   82         md_prepare_for_shutdown(paniced, howto, command);
   83 
   84         if ((howto&RB_NOSYNC)==0 && waittime < 0) {
   85                 int iter, nbusy;
   86 
   87                 waittime = 0;
   88                 
   89                 printf("syncing disks... ");
   90 
   91                 /*
   92                  * Release vnodes held by texts before sync.
   93                  */
   94 
   95                 /* handle live procs (deallocate their root and current directories). */                
   96                 proc_shutdown();
   97 
   98                 audit_shutdown();
   99 
  100                 sync(p, (void *)NULL, (int *)NULL);
  101 
  102                 /* Release vnodes from the VM object cache */    
  103                 ubc_unmountall();
  104 
  105                 IOSleep( 1 * 1000 );
  106 
  107                 /*
  108                  * Unmount filesystems
  109                  */
  110                 if (panicstr == 0)
  111                         vfs_unmountall();
  112 
  113                 /* Wait for the buffer cache to clean remaining dirty buffers */
  114                 for (iter = 0; iter < 20; iter++) {
  115                         nbusy = count_busy_buffers();
  116                         if (nbusy == 0)
  117                                 break;
  118                         printf("%d ", nbusy);
  119                         IOSleep( 4 * nbusy );
  120                 }
  121                 if (nbusy)
  122                         printf("giving up\n");
  123                 else
  124                         printf("done\n");
  125         }
  126 
  127         /*
  128          * Can't just use an splnet() here to disable the network
  129          * because that will lock out softints which the disk
  130          * drivers depend on to finish DMAs.
  131          */
  132         if_down_all();
  133 
  134         if (howto & RB_POWERDOWN)
  135                 hostboot_option = HOST_REBOOT_HALT;
  136         if (howto & RB_HALT)
  137                 hostboot_option = HOST_REBOOT_HALT;
  138         if (paniced == RB_PANIC)
  139                 hostboot_option = HOST_REBOOT_HALT;
  140 
  141         if (hostboot_option == HOST_REBOOT_HALT)
  142                 IOSleep( 1 * 1000 );
  143 
  144         host_reboot(host_priv_self(), hostboot_option);
  145 
  146         thread_funnel_set(kernel_flock, FALSE);
  147 }
  148 
  149 /*
  150  * proc_shutdown()
  151  *
  152  *      Shutdown down proc system (release references to current and root
  153  *      dirs for each process).
  154  *
  155  * POSIX modifications:
  156  *
  157  *      For POSIX fcntl() file locking call vno_lockrelease() on 
  158  *      the file to release all of its record locks, if any.
  159  */
  160 
  161 static void
  162 proc_shutdown()
  163 {
  164         struct proc     *p, *self;
  165         struct vnode    **cdirp, **rdirp, *vp;
  166         int             restart, i, TERM_catch;
  167 
  168         /*
  169          *      Kill as many procs as we can.  (Except ourself...)
  170          */
  171         self = (struct proc *)current_proc();
  172         
  173         /*
  174          * Suspend /etc/init
  175          */
  176         p = pfind(1);
  177         if (p && p != self)
  178                 task_suspend(p->task);          /* stop init */
  179 
  180         printf("Killing all processes ");
  181 
  182         /*
  183          * send SIGTERM to those procs interested in catching one
  184          */
  185         for (p = allproc.lh_first; p; p = p->p_list.le_next) {
  186                 if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self)) {
  187                         if (p->p_sigcatch & sigmask(SIGTERM))
  188                                 psignal(p, SIGTERM);
  189                 }
  190         }
  191         /*
  192          * now wait for up to 30 seconds to allow those procs catching SIGTERM
  193          * to digest it
  194          * as soon as these procs have exited, we'll continue on to the next step
  195          */
  196         for (i = 0; i < 300; i++) {
  197                 /*
  198                  * sleep for a tenth of a second
  199                  * and then check to see if the tasks that were sent a
  200                  * SIGTERM have exited
  201                  */
  202                 IOSleep(100);   
  203                 TERM_catch = 0;
  204 
  205                 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
  206                         if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self)) {
  207                                 if (p->p_sigcatch & sigmask(SIGTERM))
  208                                         TERM_catch++;
  209                         }
  210                 }
  211                 if (TERM_catch == 0)
  212                         break;
  213         }
  214         if (TERM_catch) {
  215                 /*
  216                  * log the names of the unresponsive tasks
  217                  */
  218 
  219                 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
  220                         if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self)) {
  221                                 if (p->p_sigcatch & sigmask(SIGTERM))
  222                                   printf("%s[%d]: didn't act on SIGTERM\n", p->p_comm, p->p_pid);
  223                         }
  224                 }
  225                 IOSleep(1000 * 5);
  226         }
  227 
  228         /*
  229          * send a SIGKILL to all the procs still hanging around
  230          */
  231         for (p = allproc.lh_first; p; p = p->p_list.le_next) {
  232                 if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self))
  233                         psignal(p, SIGKILL);
  234         }
  235         /*
  236          * wait for up to 60 seconds to allow these procs to exit normally
  237          */
  238         for (i = 0; i < 300; i++) {
  239                 IOSleep(200);  /* double the time from 100 to 200 for NFS requests in particular */
  240 
  241                 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
  242                         if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self))
  243                                 break;
  244                 }
  245                 if (!p)
  246                         break;
  247         }
  248 
  249         /*
  250          * if we still have procs that haven't exited, then brute force 'em
  251          */
  252         p = allproc.lh_first;
  253         while (p) {
  254                 if ((p->p_flag&P_SYSTEM) || (p->p_pptr->p_pid == 0) || (p == self)) {
  255                         p = p->p_list.le_next;
  256                 }
  257                 else {
  258                         /*
  259                          * NOTE: following code ignores sig_lock and plays
  260                          * with exit_thread correctly.  This is OK unless we
  261                          * are a multiprocessor, in which case I do not
  262                          * understand the sig_lock.  This needs to be fixed.
  263                          * XXX
  264                          */
  265                         if (p->exit_thread) {   /* someone already doing it */
  266                                                 /* give him a chance */
  267                                 thread_block(THREAD_CONTINUE_NULL);
  268                         }
  269                         else {
  270                                 p->exit_thread = current_act();
  271                                 printf(".");
  272                                 exit1(p, 1, (int *)NULL);
  273                         }
  274                         p = allproc.lh_first;
  275                 }
  276         }
  277         printf("\n");
  278         /*
  279          *      Forcibly free resources of what's left.
  280          */
  281         p = allproc.lh_first;
  282         while (p) {
  283         /*
  284          * Close open files and release open-file table.
  285          * This may block!
  286          */
  287 #ifdef notyet
  288         /* panics on reboot due to "zfree: non-allocated memory in collectable zone" message */
  289         fdfree(p);
  290 #endif /* notyet */
  291         p = p->p_list.le_next;
  292         }
  293         /* Wait for the reaper thread to run, and clean up what we have done 
  294          * before we proceed with the hardcore shutdown. This reduces the race
  295          * between kill_tasks and the reaper thread.
  296          */
  297         /* thread_wakeup(&reaper_queue); */
  298         /*      IOSleep( 1 * 1000);      */
  299         printf("continuing\n");
  300 }
  301 

Cache object: a20f4fea9964df19b1f383047eaf31ae


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.