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/kern/kern_racct.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) 2010 The FreeBSD Foundation
    3  * All rights reserved.
    4  *
    5  * This software was developed by Edward Tomasz Napierala under sponsorship
    6  * from the FreeBSD Foundation.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * $FreeBSD: releng/9.0/sys/kern/kern_racct.c 226092 2011-10-07 06:46:46Z trasz $
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/9.0/sys/kern/kern_racct.c 226092 2011-10-07 06:46:46Z trasz $");
   34 
   35 #include "opt_kdtrace.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/eventhandler.h>
   39 #include <sys/param.h>
   40 #include <sys/jail.h>
   41 #include <sys/kernel.h>
   42 #include <sys/kthread.h>
   43 #include <sys/lock.h>
   44 #include <sys/loginclass.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mutex.h>
   47 #include <sys/proc.h>
   48 #include <sys/racct.h>
   49 #include <sys/resourcevar.h>
   50 #include <sys/sbuf.h>
   51 #include <sys/sched.h>
   52 #include <sys/sdt.h>
   53 #include <sys/sx.h>
   54 #include <sys/sysent.h>
   55 #include <sys/sysproto.h>
   56 #include <sys/systm.h>
   57 #include <sys/umtx.h>
   58 
   59 #ifdef RCTL
   60 #include <sys/rctl.h>
   61 #endif
   62 
   63 #ifdef RACCT
   64 
   65 FEATURE(racct, "Resource Accounting");
   66 
   67 static struct mtx racct_lock;
   68 MTX_SYSINIT(racct_lock, &racct_lock, "racct lock", MTX_DEF);
   69 
   70 static uma_zone_t racct_zone;
   71 
   72 static void racct_sub_racct(struct racct *dest, const struct racct *src);
   73 static void racct_sub_cred_locked(struct ucred *cred, int resource,
   74                 uint64_t amount);
   75 static void racct_add_cred_locked(struct ucred *cred, int resource,
   76                 uint64_t amount);
   77 
   78 SDT_PROVIDER_DEFINE(racct);
   79 SDT_PROBE_DEFINE3(racct, kernel, rusage, add, add, "struct proc *", "int",
   80     "uint64_t");
   81 SDT_PROBE_DEFINE3(racct, kernel, rusage, add_failure, add-failure,
   82     "struct proc *", "int", "uint64_t");
   83 SDT_PROBE_DEFINE3(racct, kernel, rusage, add_cred, add-cred, "struct ucred *",
   84     "int", "uint64_t");
   85 SDT_PROBE_DEFINE3(racct, kernel, rusage, add_force, add-force, "struct proc *",
   86     "int", "uint64_t");
   87 SDT_PROBE_DEFINE3(racct, kernel, rusage, set, set, "struct proc *", "int",
   88     "uint64_t");
   89 SDT_PROBE_DEFINE3(racct, kernel, rusage, set_failure, set-failure,
   90     "struct proc *", "int", "uint64_t");
   91 SDT_PROBE_DEFINE3(racct, kernel, rusage, sub, sub, "struct proc *", "int",
   92     "uint64_t");
   93 SDT_PROBE_DEFINE3(racct, kernel, rusage, sub_cred, sub-cred, "struct ucred *",
   94     "int", "uint64_t");
   95 SDT_PROBE_DEFINE1(racct, kernel, racct, create, create, "struct racct *");
   96 SDT_PROBE_DEFINE1(racct, kernel, racct, destroy, destroy, "struct racct *");
   97 SDT_PROBE_DEFINE2(racct, kernel, racct, join, join, "struct racct *",
   98     "struct racct *");
   99 SDT_PROBE_DEFINE2(racct, kernel, racct, join_failure, join-failure,
  100     "struct racct *", "struct racct *");
  101 SDT_PROBE_DEFINE2(racct, kernel, racct, leave, leave, "struct racct *",
  102     "struct racct *");
  103 
  104 int racct_types[] = {
  105         [RACCT_CPU] =
  106                 RACCT_IN_MILLIONS,
  107         [RACCT_DATA] =
  108                 RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
  109         [RACCT_STACK] =
  110                 RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
  111         [RACCT_CORE] =
  112                 RACCT_DENIABLE,
  113         [RACCT_RSS] =
  114                 RACCT_RECLAIMABLE,
  115         [RACCT_MEMLOCK] =
  116                 RACCT_RECLAIMABLE | RACCT_DENIABLE,
  117         [RACCT_NPROC] =
  118                 RACCT_RECLAIMABLE | RACCT_DENIABLE,
  119         [RACCT_NOFILE] =
  120                 RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
  121         [RACCT_VMEM] =
  122                 RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
  123         [RACCT_NPTS] =
  124                 RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
  125         [RACCT_SWAP] =
  126                 RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
  127         [RACCT_NTHR] =
  128                 RACCT_RECLAIMABLE | RACCT_DENIABLE,
  129         [RACCT_MSGQQUEUED] =
  130                 RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
  131         [RACCT_MSGQSIZE] =
  132                 RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
  133         [RACCT_NMSGQ] =
  134                 RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
  135         [RACCT_NSEM] =
  136                 RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
  137         [RACCT_NSEMOP] =
  138                 RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
  139         [RACCT_NSHM] =
  140                 RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
  141         [RACCT_SHMSIZE] =
  142                 RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
  143         [RACCT_WALLCLOCK] =
  144                 RACCT_IN_MILLIONS };
  145 
  146 static void
  147 racct_add_racct(struct racct *dest, const struct racct *src)
  148 {
  149         int i;
  150 
  151         mtx_assert(&racct_lock, MA_OWNED);
  152 
  153         /*
  154          * Update resource usage in dest.
  155          */
  156         for (i = 0; i <= RACCT_MAX; i++) {
  157                 KASSERT(dest->r_resources[i] >= 0,
  158                     ("racct propagation meltdown: dest < 0"));
  159                 KASSERT(src->r_resources[i] >= 0,
  160                     ("racct propagation meltdown: src < 0"));
  161                 dest->r_resources[i] += src->r_resources[i];
  162         }
  163 }
  164 
  165 static void
  166 racct_sub_racct(struct racct *dest, const struct racct *src)
  167 {
  168         int i;
  169 
  170         mtx_assert(&racct_lock, MA_OWNED);
  171 
  172         /*
  173          * Update resource usage in dest.
  174          */
  175         for (i = 0; i <= RACCT_MAX; i++) {
  176                 if (!RACCT_IS_SLOPPY(i)) {
  177                         KASSERT(dest->r_resources[i] >= 0,
  178                             ("racct propagation meltdown: dest < 0"));
  179                         KASSERT(src->r_resources[i] >= 0,
  180                             ("racct propagation meltdown: src < 0"));
  181                         KASSERT(src->r_resources[i] <= dest->r_resources[i],
  182                             ("racct propagation meltdown: src > dest"));
  183                 }
  184                 if (RACCT_IS_RECLAIMABLE(i)) {
  185                         dest->r_resources[i] -= src->r_resources[i];
  186                         if (dest->r_resources[i] < 0) {
  187                                 KASSERT(RACCT_IS_SLOPPY(i),
  188                                     ("racct_sub_racct: usage < 0"));
  189                                 dest->r_resources[i] = 0;
  190                         }
  191                 }
  192         }
  193 }
  194 
  195 void
  196 racct_create(struct racct **racctp)
  197 {
  198 
  199         SDT_PROBE(racct, kernel, racct, create, racctp, 0, 0, 0, 0);
  200 
  201         KASSERT(*racctp == NULL, ("racct already allocated"));
  202 
  203         *racctp = uma_zalloc(racct_zone, M_WAITOK | M_ZERO);
  204 }
  205 
  206 static void
  207 racct_destroy_locked(struct racct **racctp)
  208 {
  209         int i;
  210         struct racct *racct;
  211 
  212         SDT_PROBE(racct, kernel, racct, destroy, racctp, 0, 0, 0, 0);
  213 
  214         mtx_assert(&racct_lock, MA_OWNED);
  215         KASSERT(racctp != NULL, ("NULL racctp"));
  216         KASSERT(*racctp != NULL, ("NULL racct"));
  217 
  218         racct = *racctp;
  219 
  220         for (i = 0; i <= RACCT_MAX; i++) {
  221                 if (RACCT_IS_SLOPPY(i))
  222                         continue;
  223                 if (!RACCT_IS_RECLAIMABLE(i))
  224                         continue;
  225                 KASSERT(racct->r_resources[i] == 0,
  226                     ("destroying non-empty racct: "
  227                     "%ju allocated for resource %d\n",
  228                     racct->r_resources[i], i));
  229         }
  230         uma_zfree(racct_zone, racct);
  231         *racctp = NULL;
  232 }
  233 
  234 void
  235 racct_destroy(struct racct **racct)
  236 {
  237 
  238         mtx_lock(&racct_lock);
  239         racct_destroy_locked(racct);
  240         mtx_unlock(&racct_lock);
  241 }
  242 
  243 /*
  244  * Increase consumption of 'resource' by 'amount' for 'racct'
  245  * and all its parents.  Differently from other cases, 'amount' here
  246  * may be less than zero.
  247  */
  248 static void
  249 racct_alloc_resource(struct racct *racct, int resource,
  250     uint64_t amount)
  251 {
  252 
  253         mtx_assert(&racct_lock, MA_OWNED);
  254         KASSERT(racct != NULL, ("NULL racct"));
  255 
  256         racct->r_resources[resource] += amount;
  257         if (racct->r_resources[resource] < 0) {
  258                 KASSERT(RACCT_IS_SLOPPY(resource),
  259                     ("racct_alloc_resource: usage < 0"));
  260                 racct->r_resources[resource] = 0;
  261         }
  262 }
  263 
  264 static int
  265 racct_add_locked(struct proc *p, int resource, uint64_t amount)
  266 {
  267 #ifdef RCTL
  268         int error;
  269 #endif
  270 
  271         if (p->p_flag & P_SYSTEM)
  272                 return (0);
  273 
  274         SDT_PROBE(racct, kernel, rusage, add, p, resource, amount, 0, 0);
  275 
  276         /*
  277          * We need proc lock to dereference p->p_ucred.
  278          */
  279         PROC_LOCK_ASSERT(p, MA_OWNED);
  280 
  281 #ifdef RCTL
  282         error = rctl_enforce(p, resource, amount);
  283         if (error && RACCT_IS_DENIABLE(resource)) {
  284                 SDT_PROBE(racct, kernel, rusage, add_failure, p, resource,
  285                     amount, 0, 0);
  286                 return (error);
  287         }
  288 #endif
  289         racct_alloc_resource(p->p_racct, resource, amount);
  290         racct_add_cred_locked(p->p_ucred, resource, amount);
  291 
  292         return (0);
  293 }
  294 
  295 /*
  296  * Increase allocation of 'resource' by 'amount' for process 'p'.
  297  * Return 0 if it's below limits, or errno, if it's not.
  298  */
  299 int
  300 racct_add(struct proc *p, int resource, uint64_t amount)
  301 {
  302         int error;
  303 
  304         mtx_lock(&racct_lock);
  305         error = racct_add_locked(p, resource, amount);
  306         mtx_unlock(&racct_lock);
  307         return (error);
  308 }
  309 
  310 static void
  311 racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount)
  312 {
  313         struct prison *pr;
  314 
  315         SDT_PROBE(racct, kernel, rusage, add_cred, cred, resource, amount,
  316             0, 0);
  317 
  318         racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, amount);
  319         for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
  320                 racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource,
  321                     amount);
  322         racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, amount);
  323 }
  324 
  325 /*
  326  * Increase allocation of 'resource' by 'amount' for credential 'cred'.
  327  * Doesn't check for limits and never fails.
  328  *
  329  * XXX: Shouldn't this ever return an error?
  330  */
  331 void
  332 racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
  333 {
  334 
  335         mtx_lock(&racct_lock);
  336         racct_add_cred_locked(cred, resource, amount);
  337         mtx_unlock(&racct_lock);
  338 }
  339 
  340 /*
  341  * Increase allocation of 'resource' by 'amount' for process 'p'.
  342  * Doesn't check for limits and never fails.
  343  */
  344 void
  345 racct_add_force(struct proc *p, int resource, uint64_t amount)
  346 {
  347 
  348         if (p->p_flag & P_SYSTEM)
  349                 return;
  350 
  351         SDT_PROBE(racct, kernel, rusage, add_force, p, resource, amount, 0, 0);
  352 
  353         /*
  354          * We need proc lock to dereference p->p_ucred.
  355          */
  356         PROC_LOCK_ASSERT(p, MA_OWNED);
  357 
  358         mtx_lock(&racct_lock);
  359         racct_alloc_resource(p->p_racct, resource, amount);
  360         mtx_unlock(&racct_lock);
  361         racct_add_cred(p->p_ucred, resource, amount);
  362 }
  363 
  364 static int
  365 racct_set_locked(struct proc *p, int resource, uint64_t amount)
  366 {
  367         int64_t diff;
  368 #ifdef RCTL
  369         int error;
  370 #endif
  371 
  372         if (p->p_flag & P_SYSTEM)
  373                 return (0);
  374 
  375         SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
  376 
  377         /*
  378          * We need proc lock to dereference p->p_ucred.
  379          */
  380         PROC_LOCK_ASSERT(p, MA_OWNED);
  381 
  382         diff = amount - p->p_racct->r_resources[resource];
  383 #ifdef notyet
  384         KASSERT(diff >= 0 || RACCT_IS_RECLAIMABLE(resource),
  385             ("racct_set: usage of non-reclaimable resource %d dropping",
  386              resource));
  387 #endif
  388 #ifdef RCTL
  389         if (diff > 0) {
  390                 error = rctl_enforce(p, resource, diff);
  391                 if (error && RACCT_IS_DENIABLE(resource)) {
  392                         SDT_PROBE(racct, kernel, rusage, set_failure, p,
  393                             resource, amount, 0, 0);
  394                         return (error);
  395                 }
  396         }
  397 #endif
  398         racct_alloc_resource(p->p_racct, resource, diff);
  399         if (diff > 0)
  400                 racct_add_cred_locked(p->p_ucred, resource, diff);
  401         else if (diff < 0)
  402                 racct_sub_cred_locked(p->p_ucred, resource, -diff);
  403 
  404         return (0);
  405 }
  406 
  407 /*
  408  * Set allocation of 'resource' to 'amount' for process 'p'.
  409  * Return 0 if it's below limits, or errno, if it's not.
  410  *
  411  * Note that decreasing the allocation always returns 0,
  412  * even if it's above the limit.
  413  */
  414 int
  415 racct_set(struct proc *p, int resource, uint64_t amount)
  416 {
  417         int error;
  418 
  419         mtx_lock(&racct_lock);
  420         error = racct_set_locked(p, resource, amount);
  421         mtx_unlock(&racct_lock);
  422         return (error);
  423 }
  424 
  425 void
  426 racct_set_force(struct proc *p, int resource, uint64_t amount)
  427 {
  428         int64_t diff;
  429 
  430         if (p->p_flag & P_SYSTEM)
  431                 return;
  432 
  433         SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
  434 
  435         /*
  436          * We need proc lock to dereference p->p_ucred.
  437          */
  438         PROC_LOCK_ASSERT(p, MA_OWNED);
  439 
  440         mtx_lock(&racct_lock);
  441         diff = amount - p->p_racct->r_resources[resource];
  442         racct_alloc_resource(p->p_racct, resource, diff);
  443         if (diff > 0)
  444                 racct_add_cred_locked(p->p_ucred, resource, diff);
  445         else if (diff < 0)
  446                 racct_sub_cred_locked(p->p_ucred, resource, -diff);
  447         mtx_unlock(&racct_lock);
  448 }
  449 
  450 /*
  451  * Returns amount of 'resource' the process 'p' can keep allocated.
  452  * Allocating more than that would be denied, unless the resource
  453  * is marked undeniable.  Amount of already allocated resource does
  454  * not matter.
  455  */
  456 uint64_t
  457 racct_get_limit(struct proc *p, int resource)
  458 {
  459 
  460 #ifdef RCTL
  461         return (rctl_get_limit(p, resource));
  462 #else
  463         return (UINT64_MAX);
  464 #endif
  465 }
  466 
  467 /*
  468  * Returns amount of 'resource' the process 'p' can keep allocated.
  469  * Allocating more than that would be denied, unless the resource
  470  * is marked undeniable.  Amount of already allocated resource does
  471  * matter.
  472  */
  473 uint64_t
  474 racct_get_available(struct proc *p, int resource)
  475 {
  476 
  477 #ifdef RCTL
  478         return (rctl_get_available(p, resource));
  479 #else
  480         return (UINT64_MAX);
  481 #endif
  482 }
  483 
  484 /*
  485  * Decrease allocation of 'resource' by 'amount' for process 'p'.
  486  */
  487 void
  488 racct_sub(struct proc *p, int resource, uint64_t amount)
  489 {
  490 
  491         if (p->p_flag & P_SYSTEM)
  492                 return;
  493 
  494         SDT_PROBE(racct, kernel, rusage, sub, p, resource, amount, 0, 0);
  495 
  496         /*
  497          * We need proc lock to dereference p->p_ucred.
  498          */
  499         PROC_LOCK_ASSERT(p, MA_OWNED);
  500         KASSERT(RACCT_IS_RECLAIMABLE(resource),
  501             ("racct_sub: called for non-reclaimable resource %d", resource));
  502 
  503         mtx_lock(&racct_lock);
  504         KASSERT(amount <= p->p_racct->r_resources[resource],
  505             ("racct_sub: freeing %ju of resource %d, which is more "
  506              "than allocated %jd for %s (pid %d)", amount, resource,
  507             (intmax_t)p->p_racct->r_resources[resource], p->p_comm, p->p_pid));
  508 
  509         racct_alloc_resource(p->p_racct, resource, -amount);
  510         racct_sub_cred_locked(p->p_ucred, resource, amount);
  511         mtx_unlock(&racct_lock);
  512 }
  513 
  514 static void
  515 racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount)
  516 {
  517         struct prison *pr;
  518 
  519         SDT_PROBE(racct, kernel, rusage, sub_cred, cred, resource, amount,
  520             0, 0);
  521 
  522 #ifdef notyet
  523         KASSERT(RACCT_IS_RECLAIMABLE(resource),
  524             ("racct_sub_cred: called for non-reclaimable resource %d",
  525              resource));
  526 #endif
  527 
  528         racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, -amount);
  529         for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
  530                 racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource,
  531                     -amount);
  532         racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, -amount);
  533 }
  534 
  535 /*
  536  * Decrease allocation of 'resource' by 'amount' for credential 'cred'.
  537  */
  538 void
  539 racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
  540 {
  541 
  542         mtx_lock(&racct_lock);
  543         racct_sub_cred_locked(cred, resource, amount);
  544         mtx_unlock(&racct_lock);
  545 }
  546 
  547 /*
  548  * Inherit resource usage information from the parent process.
  549  */
  550 int
  551 racct_proc_fork(struct proc *parent, struct proc *child)
  552 {
  553         int i, error = 0;
  554 
  555         /*
  556          * Create racct for the child process.
  557          */
  558         racct_create(&child->p_racct);
  559 
  560         /*
  561          * No resource accounting for kernel processes.
  562          */
  563         if (child->p_flag & P_SYSTEM)
  564                 return (0);
  565 
  566         PROC_LOCK(parent);
  567         PROC_LOCK(child);
  568         mtx_lock(&racct_lock);
  569 
  570 #ifdef RCTL
  571         error = rctl_proc_fork(parent, child);
  572         if (error != 0)
  573                 goto out;
  574 #endif
  575 
  576         /*
  577          * Inherit resource usage.
  578          */
  579         for (i = 0; i <= RACCT_MAX; i++) {
  580                 if (parent->p_racct->r_resources[i] == 0 ||
  581                     !RACCT_IS_INHERITABLE(i))
  582                         continue;
  583 
  584                 error = racct_set_locked(child, i,
  585                     parent->p_racct->r_resources[i]);
  586                 if (error != 0)
  587                         goto out;
  588         }
  589 
  590         error = racct_add_locked(child, RACCT_NPROC, 1);
  591         error += racct_add_locked(child, RACCT_NTHR, 1);
  592 
  593 out:
  594         mtx_unlock(&racct_lock);
  595         PROC_UNLOCK(child);
  596         PROC_UNLOCK(parent);
  597 
  598         return (error);
  599 }
  600 
  601 /*
  602  * Called at the end of fork1(), to handle rules that require the process
  603  * to be fully initialized.
  604  */
  605 void
  606 racct_proc_fork_done(struct proc *child)
  607 {
  608 
  609 #ifdef RCTL
  610         PROC_LOCK(child);
  611         mtx_lock(&racct_lock);
  612         rctl_enforce(child, RACCT_NPROC, 0);
  613         rctl_enforce(child, RACCT_NTHR, 0);
  614         mtx_unlock(&racct_lock);
  615         PROC_UNLOCK(child);
  616 #endif
  617 }
  618 
  619 void
  620 racct_proc_exit(struct proc *p)
  621 {
  622         int i;
  623         uint64_t runtime;
  624 
  625         PROC_LOCK(p);
  626         /*
  627          * We don't need to calculate rux, proc_reap() has already done this.
  628          */
  629         runtime = cputick2usec(p->p_rux.rux_runtime);
  630 #ifdef notyet
  631         KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime"));
  632 #else
  633         if (runtime < p->p_prev_runtime)
  634                 runtime = p->p_prev_runtime;
  635 #endif
  636         mtx_lock(&racct_lock);
  637         racct_set_locked(p, RACCT_CPU, runtime);
  638 
  639         for (i = 0; i <= RACCT_MAX; i++) {
  640                 if (p->p_racct->r_resources[i] == 0)
  641                         continue;
  642                 if (!RACCT_IS_RECLAIMABLE(i))
  643                         continue;
  644                 racct_set_locked(p, i, 0);
  645         }
  646 
  647         mtx_unlock(&racct_lock);
  648         PROC_UNLOCK(p);
  649 
  650 #ifdef RCTL
  651         rctl_racct_release(p->p_racct);
  652 #endif
  653         racct_destroy(&p->p_racct);
  654 }
  655 
  656 /*
  657  * Called after credentials change, to move resource utilisation
  658  * between raccts.
  659  */
  660 void
  661 racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
  662     struct ucred *newcred)
  663 {
  664         struct uidinfo *olduip, *newuip;
  665         struct loginclass *oldlc, *newlc;
  666         struct prison *oldpr, *newpr, *pr;
  667 
  668         PROC_LOCK_ASSERT(p, MA_NOTOWNED);
  669 
  670         newuip = newcred->cr_ruidinfo;
  671         olduip = oldcred->cr_ruidinfo;
  672         newlc = newcred->cr_loginclass;
  673         oldlc = oldcred->cr_loginclass;
  674         newpr = newcred->cr_prison;
  675         oldpr = oldcred->cr_prison;
  676 
  677         mtx_lock(&racct_lock);
  678         if (newuip != olduip) {
  679                 racct_sub_racct(olduip->ui_racct, p->p_racct);
  680                 racct_add_racct(newuip->ui_racct, p->p_racct);
  681         }
  682         if (newlc != oldlc) {
  683                 racct_sub_racct(oldlc->lc_racct, p->p_racct);
  684                 racct_add_racct(newlc->lc_racct, p->p_racct);
  685         }
  686         if (newpr != oldpr) {
  687                 for (pr = oldpr; pr != NULL; pr = pr->pr_parent)
  688                         racct_sub_racct(pr->pr_prison_racct->prr_racct,
  689                             p->p_racct);
  690                 for (pr = newpr; pr != NULL; pr = pr->pr_parent)
  691                         racct_add_racct(pr->pr_prison_racct->prr_racct,
  692                             p->p_racct);
  693         }
  694         mtx_unlock(&racct_lock);
  695 
  696 #ifdef RCTL
  697         rctl_proc_ucred_changed(p, newcred);
  698 #endif
  699 }
  700 
  701 static void
  702 racctd(void)
  703 {
  704         struct thread *td;
  705         struct proc *p;
  706         struct timeval wallclock;
  707         uint64_t runtime;
  708 
  709         for (;;) {
  710                 sx_slock(&allproc_lock);
  711 
  712                 FOREACH_PROC_IN_SYSTEM(p) {
  713                         if (p->p_state != PRS_NORMAL)
  714                                 continue;
  715                         if (p->p_flag & P_SYSTEM)
  716                                 continue;
  717 
  718                         microuptime(&wallclock);
  719                         timevalsub(&wallclock, &p->p_stats->p_start);
  720                         PROC_LOCK(p);
  721                         PROC_SLOCK(p);
  722                         FOREACH_THREAD_IN_PROC(p, td) {
  723                                 ruxagg(p, td);
  724                                 thread_lock(td);
  725                                 thread_unlock(td);
  726                         }
  727                         runtime = cputick2usec(p->p_rux.rux_runtime);
  728                         PROC_SUNLOCK(p);
  729 #ifdef notyet
  730                         KASSERT(runtime >= p->p_prev_runtime,
  731                             ("runtime < p_prev_runtime"));
  732 #else
  733                         if (runtime < p->p_prev_runtime)
  734                                 runtime = p->p_prev_runtime;
  735 #endif
  736                         p->p_prev_runtime = runtime;
  737                         mtx_lock(&racct_lock);
  738                         racct_set_locked(p, RACCT_CPU, runtime);
  739                         racct_set_locked(p, RACCT_WALLCLOCK,
  740                             wallclock.tv_sec * 1000000 + wallclock.tv_usec);
  741                         mtx_unlock(&racct_lock);
  742                         PROC_UNLOCK(p);
  743                 }
  744                 sx_sunlock(&allproc_lock);
  745                 pause("-", hz);
  746         }
  747 }
  748 
  749 static struct kproc_desc racctd_kp = {
  750         "racctd",
  751         racctd,
  752         NULL
  753 };
  754 SYSINIT(racctd, SI_SUB_RACCTD, SI_ORDER_FIRST, kproc_start, &racctd_kp);
  755 
  756 static void
  757 racct_init(void)
  758 {
  759 
  760         racct_zone = uma_zcreate("racct", sizeof(struct racct),
  761             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
  762         /*
  763          * XXX: Move this somewhere.
  764          */
  765         prison0.pr_prison_racct = prison_racct_find("");
  766 }
  767 SYSINIT(racct, SI_SUB_RACCT, SI_ORDER_FIRST, racct_init, NULL);
  768 
  769 #else /* !RACCT */
  770 
  771 int
  772 racct_add(struct proc *p, int resource, uint64_t amount)
  773 {
  774 
  775         return (0);
  776 }
  777 
  778 void
  779 racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
  780 {
  781 }
  782 
  783 void
  784 racct_add_force(struct proc *p, int resource, uint64_t amount)
  785 {
  786 
  787         return;
  788 }
  789 
  790 int
  791 racct_set(struct proc *p, int resource, uint64_t amount)
  792 {
  793 
  794         return (0);
  795 }
  796 
  797 void
  798 racct_set_force(struct proc *p, int resource, uint64_t amount)
  799 {
  800 }
  801 
  802 void
  803 racct_sub(struct proc *p, int resource, uint64_t amount)
  804 {
  805 }
  806 
  807 void
  808 racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
  809 {
  810 }
  811 
  812 uint64_t
  813 racct_get_limit(struct proc *p, int resource)
  814 {
  815 
  816         return (UINT64_MAX);
  817 }
  818 
  819 uint64_t
  820 racct_get_available(struct proc *p, int resource)
  821 {
  822 
  823         return (UINT64_MAX);
  824 }
  825 
  826 void
  827 racct_create(struct racct **racctp)
  828 {
  829 }
  830 
  831 void
  832 racct_destroy(struct racct **racctp)
  833 {
  834 }
  835 
  836 int
  837 racct_proc_fork(struct proc *parent, struct proc *child)
  838 {
  839 
  840         return (0);
  841 }
  842 
  843 void
  844 racct_proc_fork_done(struct proc *child)
  845 {
  846 }
  847 
  848 void
  849 racct_proc_exit(struct proc *p)
  850 {
  851 }
  852 
  853 #endif /* !RACCT */

Cache object: 9f73d87551723a6daf240aee0bd58d11


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