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/servers/pm/misc.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 /* Miscellaneous system calls.                          Author: Kees J. Bot
    2  *                                                              31 Mar 2000
    3  * The entry points into this file are:
    4  *   do_reboot: kill all processes, then reboot system
    5  *   do_svrctl: process manager control
    6  *   do_getsysinfo: request copy of PM data structure  (Jorrit N. Herder)
    7  *   do_getprocnr: lookup process slot number  (Jorrit N. Herder)
    8  *   do_memalloc: allocate a chunk of memory  (Jorrit N. Herder)
    9  *   do_memfree: deallocate a chunk of memory  (Jorrit N. Herder)
   10  *   do_getsetpriority: get/set process priority
   11  */
   12 
   13 #include "pm.h"
   14 #include <minix/callnr.h>
   15 #include <signal.h>
   16 #include <sys/svrctl.h>
   17 #include <sys/resource.h>
   18 #include <minix/com.h>
   19 #include <minix/config.h>
   20 #include <minix/type.h>
   21 #include <string.h>
   22 #include "mproc.h"
   23 #include "param.h"
   24 
   25 /*===========================================================================*
   26  *                              do_allocmem                                  *
   27  *===========================================================================*/
   28 PUBLIC int do_allocmem()
   29 {
   30   vir_clicks mem_clicks;
   31   phys_clicks mem_base;
   32 
   33   mem_clicks = (m_in.memsize + CLICK_SIZE -1 ) >> CLICK_SHIFT;
   34   mem_base = alloc_mem(mem_clicks);
   35   if (mem_base == NO_MEM) return(ENOMEM);
   36   mp->mp_reply.membase =  (phys_bytes) (mem_base << CLICK_SHIFT);
   37   return(OK);
   38 }
   39 
   40 /*===========================================================================*
   41  *                              do_freemem                                   *
   42  *===========================================================================*/
   43 PUBLIC int do_freemem()
   44 {
   45   vir_clicks mem_clicks;
   46   phys_clicks mem_base;
   47 
   48   mem_clicks = (m_in.memsize + CLICK_SIZE -1 ) >> CLICK_SHIFT;
   49   mem_base = (m_in.membase + CLICK_SIZE -1 ) >> CLICK_SHIFT;
   50   free_mem(mem_base, mem_clicks);
   51   return(OK);
   52 }
   53 
   54 /*===========================================================================*
   55  *                              do_getsysinfo                                *
   56  *===========================================================================*/
   57 PUBLIC int do_getsysinfo()
   58 {
   59   struct mproc *proc_addr;
   60   vir_bytes src_addr, dst_addr;
   61   struct kinfo kinfo;
   62   size_t len;
   63   static struct pm_mem_info pmi;
   64   int s, r;
   65   size_t holesize;
   66 
   67   switch(m_in.info_what) {
   68   case SI_KINFO:                        /* kernel info is obtained via PM */
   69         sys_getkinfo(&kinfo);
   70         src_addr = (vir_bytes) &kinfo;
   71         len = sizeof(struct kinfo);
   72         break;
   73   case SI_PROC_ADDR:                    /* get address of PM process table */
   74         proc_addr = &mproc[0];
   75         src_addr = (vir_bytes) &proc_addr;
   76         len = sizeof(struct mproc *);
   77         break; 
   78   case SI_PROC_TAB:                     /* copy entire process table */
   79         src_addr = (vir_bytes) mproc;
   80         len = sizeof(struct mproc) * NR_PROCS;
   81         break;
   82   case SI_MEM_ALLOC:
   83         holesize = sizeof(pmi.pmi_holes);
   84         if((r=mem_holes_copy(pmi.pmi_holes, &holesize,
   85            &pmi.pmi_hi_watermark)) != OK)
   86                 return r;
   87         src_addr = (vir_bytes) &pmi;
   88         len = sizeof(pmi);
   89         break;
   90   default:
   91         return(EINVAL);
   92   }
   93 
   94   dst_addr = (vir_bytes) m_in.info_where;
   95   if (OK != (s=sys_datacopy(SELF, src_addr, who, dst_addr, len)))
   96         return(s);
   97   return(OK);
   98 }
   99 
  100 /*===========================================================================*
  101  *                              do_getprocnr                                 *
  102  *===========================================================================*/
  103 PUBLIC int do_getprocnr()
  104 {
  105   register struct mproc *rmp;
  106   static char search_key[PROC_NAME_LEN+1];
  107   int key_len;
  108   int s;
  109 
  110   if (m_in.pid >= 0) {                  /* lookup process by pid */
  111         for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
  112                 if ((rmp->mp_flags & IN_USE) && (rmp->mp_pid==m_in.pid)) {
  113                         mp->mp_reply.procnr = (int) (rmp - mproc);
  114                         return(OK);
  115                 } 
  116         }
  117         return(ESRCH);                  
  118   } else if (m_in.namelen > 0) {        /* lookup process by name */
  119         key_len = MIN(m_in.namelen, PROC_NAME_LEN);
  120         if (OK != (s=sys_datacopy(who, (vir_bytes) m_in.addr, 
  121                         SELF, (vir_bytes) search_key, key_len))) 
  122                 return(s);
  123         search_key[key_len] = '\0';     /* terminate for safety */
  124         for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
  125                 if (((rmp->mp_flags & (IN_USE | ZOMBIE)) == IN_USE) && 
  126                         strncmp(rmp->mp_name, search_key, key_len)==0) {
  127                         mp->mp_reply.procnr = (int) (rmp - mproc);
  128                         return(OK);
  129                 } 
  130         }
  131         return(ESRCH);                  
  132   } else {                              /* return own/parent process number */
  133         mp->mp_reply.procnr = who;
  134         mp->mp_reply.pprocnr = mp->mp_parent;  
  135   }
  136   return(OK);
  137 }
  138 
  139 /*===========================================================================*
  140  *                              do_reboot                                    *
  141  *===========================================================================*/
  142 #define REBOOT_CODE     "delay; boot"
  143 PUBLIC int do_reboot()
  144 {
  145   char monitor_code[32*sizeof(char *)];         
  146   int code_len;
  147   int abort_flag;
  148 
  149   if (mp->mp_effuid != SUPER_USER) return(EPERM);
  150 
  151   switch (m_in.reboot_flag) {
  152   case RBT_HALT:
  153   case RBT_PANIC:
  154   case RBT_RESET:
  155         abort_flag = m_in.reboot_flag;
  156         break;
  157   case RBT_REBOOT:
  158         code_len = strlen(REBOOT_CODE) + 1;
  159         strncpy(monitor_code, REBOOT_CODE, code_len);        
  160         abort_flag = RBT_MONITOR;
  161         break;
  162   case RBT_MONITOR:
  163         code_len = m_in.reboot_strlen + 1;
  164         if (code_len > sizeof(monitor_code)) return(EINVAL);
  165         if (sys_datacopy(who, (vir_bytes) m_in.reboot_code,
  166                 PM_PROC_NR, (vir_bytes) monitor_code,
  167                 (phys_bytes) (code_len)) != OK) return(EFAULT);
  168         if (monitor_code[code_len-1] != 0) return(EINVAL);
  169         abort_flag = RBT_MONITOR;
  170         break;
  171   default:
  172         return(EINVAL);
  173   }
  174 
  175   /* Order matters here. When FS is told to reboot, it exits all its
  176    * processes, and then would be confused if they're exited again by
  177    * SIGKILL. So first kill, then reboot.
  178    */
  179 
  180   check_sig(-1, SIGKILL);               /* kill all processes except init */
  181   tell_fs(REBOOT, 0, 0, 0);             /* tell FS to synchronize */
  182 
  183   /* Ask the kernel to abort. All system services, including the PM, will 
  184    * get a HARD_STOP notification. Await the notification in the main loop.
  185    */
  186   sys_abort(abort_flag, PM_PROC_NR, monitor_code, code_len);
  187   return(SUSPEND);                      /* don't reply to killed process */
  188 }
  189 
  190 /*===========================================================================*
  191  *                              do_getsetpriority                            *
  192  *===========================================================================*/
  193 PUBLIC int do_getsetpriority()
  194 {
  195         int arg_which, arg_who, arg_pri;
  196         int rmp_nr;
  197         struct mproc *rmp;
  198 
  199         arg_which = m_in.m1_i1;
  200         arg_who = m_in.m1_i2;
  201         arg_pri = m_in.m1_i3;   /* for SETPRIORITY */
  202 
  203         /* Code common to GETPRIORITY and SETPRIORITY. */
  204 
  205         /* Only support PRIO_PROCESS for now. */
  206         if (arg_which != PRIO_PROCESS)
  207                 return(EINVAL);
  208 
  209         if (arg_who == 0)
  210                 rmp_nr = who;
  211         else
  212                 if ((rmp_nr = proc_from_pid(arg_who)) < 0)
  213                         return(ESRCH);
  214 
  215         rmp = &mproc[rmp_nr];
  216 
  217         if (mp->mp_effuid != SUPER_USER &&
  218            mp->mp_effuid != rmp->mp_effuid && mp->mp_effuid != rmp->mp_realuid)
  219                 return EPERM;
  220 
  221         /* If GET, that's it. */
  222         if (call_nr == GETPRIORITY) {
  223                 return(rmp->mp_nice - PRIO_MIN);
  224         }
  225 
  226         /* Only root is allowed to reduce the nice level. */
  227         if (rmp->mp_nice > arg_pri && mp->mp_effuid != SUPER_USER)
  228                 return(EACCES);
  229         
  230         /* We're SET, and it's allowed. Do it and tell kernel. */
  231         rmp->mp_nice = arg_pri;
  232         return sys_nice(rmp_nr, arg_pri);
  233 }
  234 
  235 /*===========================================================================*
  236  *                              do_svrctl                                    *
  237  *===========================================================================*/
  238 PUBLIC int do_svrctl()
  239 {
  240   int s, req;
  241   vir_bytes ptr;
  242 #define MAX_LOCAL_PARAMS 2
  243   static struct {
  244         char name[30];
  245         char value[30];
  246   } local_param_overrides[MAX_LOCAL_PARAMS];
  247   static int local_params = 0;
  248 
  249   req = m_in.svrctl_req;
  250   ptr = (vir_bytes) m_in.svrctl_argp;
  251 
  252   /* Is the request indeed for the MM? */
  253   if (((req >> 8) & 0xFF) != 'M') return(EINVAL);
  254 
  255   /* Control operations local to the PM. */
  256   switch(req) {
  257   case MMSETPARAM:
  258   case MMGETPARAM: {
  259       struct sysgetenv sysgetenv;
  260       char search_key[64];
  261       char *val_start;
  262       size_t val_len;
  263       size_t copy_len;
  264 
  265       /* Copy sysgetenv structure to PM. */
  266       if (sys_datacopy(who, ptr, SELF, (vir_bytes) &sysgetenv, 
  267               sizeof(sysgetenv)) != OK) return(EFAULT);  
  268 
  269       /* Set a param override? */
  270       if (req == MMSETPARAM) {
  271         if (local_params >= MAX_LOCAL_PARAMS) return ENOSPC;
  272         if (sysgetenv.keylen <= 0
  273          || sysgetenv.keylen >=
  274                  sizeof(local_param_overrides[local_params].name)
  275          || sysgetenv.vallen <= 0
  276          || sysgetenv.vallen >=
  277                  sizeof(local_param_overrides[local_params].value))
  278                 return EINVAL;
  279                 
  280           if ((s = sys_datacopy(who, (vir_bytes) sysgetenv.key,
  281             SELF, (vir_bytes) local_param_overrides[local_params].name,
  282                sysgetenv.keylen)) != OK)
  283                 return s;
  284           if ((s = sys_datacopy(who, (vir_bytes) sysgetenv.val,
  285             SELF, (vir_bytes) local_param_overrides[local_params].value,
  286               sysgetenv.keylen)) != OK)
  287                 return s;
  288             local_param_overrides[local_params].name[sysgetenv.keylen] = '\0';
  289             local_param_overrides[local_params].value[sysgetenv.vallen] = '\0';
  290 
  291         local_params++;
  292 
  293         return OK;
  294       }
  295 
  296       if (sysgetenv.keylen == 0) {      /* copy all parameters */
  297           val_start = monitor_params;
  298           val_len = sizeof(monitor_params);
  299       } 
  300       else {                            /* lookup value for key */
  301           int p;
  302           /* Try to get a copy of the requested key. */
  303           if (sysgetenv.keylen > sizeof(search_key)) return(EINVAL);
  304           if ((s = sys_datacopy(who, (vir_bytes) sysgetenv.key,
  305                   SELF, (vir_bytes) search_key, sysgetenv.keylen)) != OK)
  306               return(s);
  307 
  308           /* Make sure key is null-terminated and lookup value.
  309            * First check local overrides.
  310            */
  311           search_key[sysgetenv.keylen-1]= '\0';
  312           for(p = 0; p < local_params; p++) {
  313                 if (!strcmp(search_key, local_param_overrides[p].name)) {
  314                         val_start = local_param_overrides[p].value;
  315                         break;
  316                 }
  317           }
  318           if (p >= local_params && (val_start = find_param(search_key)) == NULL)
  319                return(ESRCH);
  320           val_len = strlen(val_start) + 1;
  321       }
  322 
  323       /* See if it fits in the client's buffer. */
  324       if (val_len > sysgetenv.vallen)
  325         return E2BIG;
  326 
  327       /* Value found, make the actual copy (as far as possible). */
  328       copy_len = MIN(val_len, sysgetenv.vallen); 
  329       if ((s=sys_datacopy(SELF, (vir_bytes) val_start, 
  330               who, (vir_bytes) sysgetenv.val, copy_len)) != OK)
  331           return(s);
  332 
  333       return OK;
  334   }
  335 
  336 #if ENABLE_SWAP
  337   case MMSWAPON: {
  338         struct mmswapon swapon;
  339 
  340         if (mp->mp_effuid != SUPER_USER) return(EPERM);
  341 
  342         if (sys_datacopy(who, (phys_bytes) ptr,
  343                 PM_PROC_NR, (phys_bytes) &swapon,
  344                 (phys_bytes) sizeof(swapon)) != OK) return(EFAULT);
  345 
  346         return(swap_on(swapon.file, swapon.offset, swapon.size)); }
  347 
  348   case MMSWAPOFF: {
  349         if (mp->mp_effuid != SUPER_USER) return(EPERM);
  350 
  351         return(swap_off()); }
  352 #endif /* SWAP */
  353 
  354   default:
  355         return(EINVAL);
  356   }
  357 }
  358 

Cache object: ecd0021589efb38ddbbc8d37f5a25875


[ 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.