1097055e2SEdward Tomasz Napierala /*- 2097055e2SEdward Tomasz Napierala * Copyright (c) 2010 The FreeBSD Foundation 3097055e2SEdward Tomasz Napierala * All rights reserved. 4097055e2SEdward Tomasz Napierala * 5097055e2SEdward Tomasz Napierala * This software was developed by Edward Tomasz Napierala under sponsorship 6097055e2SEdward Tomasz Napierala * from the FreeBSD Foundation. 7097055e2SEdward Tomasz Napierala * 8097055e2SEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without 9097055e2SEdward Tomasz Napierala * modification, are permitted provided that the following conditions 10097055e2SEdward Tomasz Napierala * are met: 11097055e2SEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright 12097055e2SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer. 13097055e2SEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright 14097055e2SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the 15097055e2SEdward Tomasz Napierala * documentation and/or other materials provided with the distribution. 16097055e2SEdward Tomasz Napierala * 17097055e2SEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18097055e2SEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19097055e2SEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20097055e2SEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21097055e2SEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22097055e2SEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23097055e2SEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24097055e2SEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25097055e2SEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26097055e2SEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27097055e2SEdward Tomasz Napierala * SUCH DAMAGE. 28097055e2SEdward Tomasz Napierala * 29097055e2SEdward Tomasz Napierala * $FreeBSD$ 30097055e2SEdward Tomasz Napierala */ 31097055e2SEdward Tomasz Napierala 32097055e2SEdward Tomasz Napierala #include <sys/cdefs.h> 33097055e2SEdward Tomasz Napierala __FBSDID("$FreeBSD$"); 34097055e2SEdward Tomasz Napierala 35097055e2SEdward Tomasz Napierala #include "opt_kdtrace.h" 36097055e2SEdward Tomasz Napierala 37097055e2SEdward Tomasz Napierala #include <sys/param.h> 38*0e225211SAndriy Gapon #include <sys/systm.h> 39097055e2SEdward Tomasz Napierala #include <sys/eventhandler.h> 40097055e2SEdward Tomasz Napierala #include <sys/jail.h> 41097055e2SEdward Tomasz Napierala #include <sys/kernel.h> 42097055e2SEdward Tomasz Napierala #include <sys/kthread.h> 43097055e2SEdward Tomasz Napierala #include <sys/lock.h> 44097055e2SEdward Tomasz Napierala #include <sys/loginclass.h> 45097055e2SEdward Tomasz Napierala #include <sys/malloc.h> 46097055e2SEdward Tomasz Napierala #include <sys/mutex.h> 47097055e2SEdward Tomasz Napierala #include <sys/proc.h> 48097055e2SEdward Tomasz Napierala #include <sys/racct.h> 49097055e2SEdward Tomasz Napierala #include <sys/resourcevar.h> 50097055e2SEdward Tomasz Napierala #include <sys/sbuf.h> 51097055e2SEdward Tomasz Napierala #include <sys/sched.h> 52097055e2SEdward Tomasz Napierala #include <sys/sdt.h> 53097055e2SEdward Tomasz Napierala #include <sys/sx.h> 54097055e2SEdward Tomasz Napierala #include <sys/sysent.h> 55097055e2SEdward Tomasz Napierala #include <sys/sysproto.h> 56097055e2SEdward Tomasz Napierala #include <sys/umtx.h> 57097055e2SEdward Tomasz Napierala 58097055e2SEdward Tomasz Napierala #ifdef RCTL 59097055e2SEdward Tomasz Napierala #include <sys/rctl.h> 60097055e2SEdward Tomasz Napierala #endif 61097055e2SEdward Tomasz Napierala 62097055e2SEdward Tomasz Napierala #ifdef RACCT 63097055e2SEdward Tomasz Napierala 64097055e2SEdward Tomasz Napierala FEATURE(racct, "Resource Accounting"); 65097055e2SEdward Tomasz Napierala 66097055e2SEdward Tomasz Napierala static struct mtx racct_lock; 67097055e2SEdward Tomasz Napierala MTX_SYSINIT(racct_lock, &racct_lock, "racct lock", MTX_DEF); 68097055e2SEdward Tomasz Napierala 69097055e2SEdward Tomasz Napierala static uma_zone_t racct_zone; 70097055e2SEdward Tomasz Napierala 71097055e2SEdward Tomasz Napierala static void racct_sub_racct(struct racct *dest, const struct racct *src); 72097055e2SEdward Tomasz Napierala static void racct_sub_cred_locked(struct ucred *cred, int resource, 73097055e2SEdward Tomasz Napierala uint64_t amount); 74097055e2SEdward Tomasz Napierala static void racct_add_cred_locked(struct ucred *cred, int resource, 75097055e2SEdward Tomasz Napierala uint64_t amount); 76097055e2SEdward Tomasz Napierala 77097055e2SEdward Tomasz Napierala SDT_PROVIDER_DEFINE(racct); 78097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, add, add, "struct proc *", "int", 79097055e2SEdward Tomasz Napierala "uint64_t"); 80097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, add_failure, add-failure, 81097055e2SEdward Tomasz Napierala "struct proc *", "int", "uint64_t"); 82097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, add_cred, add-cred, "struct ucred *", 83097055e2SEdward Tomasz Napierala "int", "uint64_t"); 84097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, add_force, add-force, "struct proc *", 85097055e2SEdward Tomasz Napierala "int", "uint64_t"); 86097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, set, set, "struct proc *", "int", 87097055e2SEdward Tomasz Napierala "uint64_t"); 88097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, set_failure, set-failure, 89097055e2SEdward Tomasz Napierala "struct proc *", "int", "uint64_t"); 90097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, sub, sub, "struct proc *", "int", 91097055e2SEdward Tomasz Napierala "uint64_t"); 92097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, sub_cred, sub-cred, "struct ucred *", 93097055e2SEdward Tomasz Napierala "int", "uint64_t"); 94097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE1(racct, kernel, racct, create, create, "struct racct *"); 95097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE1(racct, kernel, racct, destroy, destroy, "struct racct *"); 96097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE2(racct, kernel, racct, join, join, "struct racct *", 97097055e2SEdward Tomasz Napierala "struct racct *"); 98097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE2(racct, kernel, racct, join_failure, join-failure, 99097055e2SEdward Tomasz Napierala "struct racct *", "struct racct *"); 100097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE2(racct, kernel, racct, leave, leave, "struct racct *", 101097055e2SEdward Tomasz Napierala "struct racct *"); 102097055e2SEdward Tomasz Napierala 103097055e2SEdward Tomasz Napierala int racct_types[] = { 104097055e2SEdward Tomasz Napierala [RACCT_CPU] = 10585a2f1b4SEdward Tomasz Napierala RACCT_IN_MILLIONS, 106097055e2SEdward Tomasz Napierala [RACCT_DATA] = 107097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 108097055e2SEdward Tomasz Napierala [RACCT_STACK] = 109097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 110097055e2SEdward Tomasz Napierala [RACCT_CORE] = 111097055e2SEdward Tomasz Napierala RACCT_DENIABLE, 112097055e2SEdward Tomasz Napierala [RACCT_RSS] = 113097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE, 114097055e2SEdward Tomasz Napierala [RACCT_MEMLOCK] = 115097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE, 116097055e2SEdward Tomasz Napierala [RACCT_NPROC] = 117097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE, 118097055e2SEdward Tomasz Napierala [RACCT_NOFILE] = 119097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 120097055e2SEdward Tomasz Napierala [RACCT_VMEM] = 121097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 122097055e2SEdward Tomasz Napierala [RACCT_NPTS] = 123097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 124097055e2SEdward Tomasz Napierala [RACCT_SWAP] = 125097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 126097055e2SEdward Tomasz Napierala [RACCT_NTHR] = 127097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE, 128097055e2SEdward Tomasz Napierala [RACCT_MSGQQUEUED] = 129097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 130097055e2SEdward Tomasz Napierala [RACCT_MSGQSIZE] = 131097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 132097055e2SEdward Tomasz Napierala [RACCT_NMSGQ] = 133097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 134097055e2SEdward Tomasz Napierala [RACCT_NSEM] = 135097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 136097055e2SEdward Tomasz Napierala [RACCT_NSEMOP] = 137097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 138097055e2SEdward Tomasz Napierala [RACCT_NSHM] = 139097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 140097055e2SEdward Tomasz Napierala [RACCT_SHMSIZE] = 141097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 142097055e2SEdward Tomasz Napierala [RACCT_WALLCLOCK] = 14385a2f1b4SEdward Tomasz Napierala RACCT_IN_MILLIONS }; 144097055e2SEdward Tomasz Napierala 145097055e2SEdward Tomasz Napierala static void 146097055e2SEdward Tomasz Napierala racct_add_racct(struct racct *dest, const struct racct *src) 147097055e2SEdward Tomasz Napierala { 148097055e2SEdward Tomasz Napierala int i; 149097055e2SEdward Tomasz Napierala 150097055e2SEdward Tomasz Napierala mtx_assert(&racct_lock, MA_OWNED); 151097055e2SEdward Tomasz Napierala 152097055e2SEdward Tomasz Napierala /* 153097055e2SEdward Tomasz Napierala * Update resource usage in dest. 154097055e2SEdward Tomasz Napierala */ 155097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 156097055e2SEdward Tomasz Napierala KASSERT(dest->r_resources[i] >= 0, 157097055e2SEdward Tomasz Napierala ("racct propagation meltdown: dest < 0")); 158097055e2SEdward Tomasz Napierala KASSERT(src->r_resources[i] >= 0, 159097055e2SEdward Tomasz Napierala ("racct propagation meltdown: src < 0")); 160097055e2SEdward Tomasz Napierala dest->r_resources[i] += src->r_resources[i]; 161097055e2SEdward Tomasz Napierala } 162097055e2SEdward Tomasz Napierala } 163097055e2SEdward Tomasz Napierala 164097055e2SEdward Tomasz Napierala static void 165097055e2SEdward Tomasz Napierala racct_sub_racct(struct racct *dest, const struct racct *src) 166097055e2SEdward Tomasz Napierala { 167097055e2SEdward Tomasz Napierala int i; 168097055e2SEdward Tomasz Napierala 169097055e2SEdward Tomasz Napierala mtx_assert(&racct_lock, MA_OWNED); 170097055e2SEdward Tomasz Napierala 171097055e2SEdward Tomasz Napierala /* 172097055e2SEdward Tomasz Napierala * Update resource usage in dest. 173097055e2SEdward Tomasz Napierala */ 174097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 1754fe84775SEdward Tomasz Napierala if (!RACCT_IS_SLOPPY(i)) { 176097055e2SEdward Tomasz Napierala KASSERT(dest->r_resources[i] >= 0, 177097055e2SEdward Tomasz Napierala ("racct propagation meltdown: dest < 0")); 178097055e2SEdward Tomasz Napierala KASSERT(src->r_resources[i] >= 0, 179097055e2SEdward Tomasz Napierala ("racct propagation meltdown: src < 0")); 180097055e2SEdward Tomasz Napierala KASSERT(src->r_resources[i] <= dest->r_resources[i], 181097055e2SEdward Tomasz Napierala ("racct propagation meltdown: src > dest")); 182097055e2SEdward Tomasz Napierala } 1834fe84775SEdward Tomasz Napierala if (RACCT_IS_RECLAIMABLE(i)) { 184097055e2SEdward Tomasz Napierala dest->r_resources[i] -= src->r_resources[i]; 185097055e2SEdward Tomasz Napierala if (dest->r_resources[i] < 0) { 1864fe84775SEdward Tomasz Napierala KASSERT(RACCT_IS_SLOPPY(i), 187097055e2SEdward Tomasz Napierala ("racct_sub_racct: usage < 0")); 188097055e2SEdward Tomasz Napierala dest->r_resources[i] = 0; 189097055e2SEdward Tomasz Napierala } 190097055e2SEdward Tomasz Napierala } 191097055e2SEdward Tomasz Napierala } 192097055e2SEdward Tomasz Napierala } 193097055e2SEdward Tomasz Napierala 194097055e2SEdward Tomasz Napierala void 195097055e2SEdward Tomasz Napierala racct_create(struct racct **racctp) 196097055e2SEdward Tomasz Napierala { 197097055e2SEdward Tomasz Napierala 198097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, racct, create, racctp, 0, 0, 0, 0); 199097055e2SEdward Tomasz Napierala 200097055e2SEdward Tomasz Napierala KASSERT(*racctp == NULL, ("racct already allocated")); 201097055e2SEdward Tomasz Napierala 202097055e2SEdward Tomasz Napierala *racctp = uma_zalloc(racct_zone, M_WAITOK | M_ZERO); 203097055e2SEdward Tomasz Napierala } 204097055e2SEdward Tomasz Napierala 205097055e2SEdward Tomasz Napierala static void 206097055e2SEdward Tomasz Napierala racct_destroy_locked(struct racct **racctp) 207097055e2SEdward Tomasz Napierala { 208097055e2SEdward Tomasz Napierala int i; 209097055e2SEdward Tomasz Napierala struct racct *racct; 210097055e2SEdward Tomasz Napierala 211097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, racct, destroy, racctp, 0, 0, 0, 0); 212097055e2SEdward Tomasz Napierala 213097055e2SEdward Tomasz Napierala mtx_assert(&racct_lock, MA_OWNED); 214097055e2SEdward Tomasz Napierala KASSERT(racctp != NULL, ("NULL racctp")); 215097055e2SEdward Tomasz Napierala KASSERT(*racctp != NULL, ("NULL racct")); 216097055e2SEdward Tomasz Napierala 217097055e2SEdward Tomasz Napierala racct = *racctp; 218097055e2SEdward Tomasz Napierala 219097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 2204fe84775SEdward Tomasz Napierala if (RACCT_IS_SLOPPY(i)) 221097055e2SEdward Tomasz Napierala continue; 2224fe84775SEdward Tomasz Napierala if (!RACCT_IS_RECLAIMABLE(i)) 223097055e2SEdward Tomasz Napierala continue; 224097055e2SEdward Tomasz Napierala KASSERT(racct->r_resources[i] == 0, 225097055e2SEdward Tomasz Napierala ("destroying non-empty racct: " 226097055e2SEdward Tomasz Napierala "%ju allocated for resource %d\n", 227097055e2SEdward Tomasz Napierala racct->r_resources[i], i)); 228097055e2SEdward Tomasz Napierala } 229097055e2SEdward Tomasz Napierala uma_zfree(racct_zone, racct); 230097055e2SEdward Tomasz Napierala *racctp = NULL; 231097055e2SEdward Tomasz Napierala } 232097055e2SEdward Tomasz Napierala 233097055e2SEdward Tomasz Napierala void 234097055e2SEdward Tomasz Napierala racct_destroy(struct racct **racct) 235097055e2SEdward Tomasz Napierala { 236097055e2SEdward Tomasz Napierala 237097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 238097055e2SEdward Tomasz Napierala racct_destroy_locked(racct); 239097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 240097055e2SEdward Tomasz Napierala } 241097055e2SEdward Tomasz Napierala 242097055e2SEdward Tomasz Napierala /* 243097055e2SEdward Tomasz Napierala * Increase consumption of 'resource' by 'amount' for 'racct' 244097055e2SEdward Tomasz Napierala * and all its parents. Differently from other cases, 'amount' here 245097055e2SEdward Tomasz Napierala * may be less than zero. 246097055e2SEdward Tomasz Napierala */ 247097055e2SEdward Tomasz Napierala static void 248097055e2SEdward Tomasz Napierala racct_alloc_resource(struct racct *racct, int resource, 249097055e2SEdward Tomasz Napierala uint64_t amount) 250097055e2SEdward Tomasz Napierala { 251097055e2SEdward Tomasz Napierala 252097055e2SEdward Tomasz Napierala mtx_assert(&racct_lock, MA_OWNED); 253097055e2SEdward Tomasz Napierala KASSERT(racct != NULL, ("NULL racct")); 254097055e2SEdward Tomasz Napierala 255097055e2SEdward Tomasz Napierala racct->r_resources[resource] += amount; 256097055e2SEdward Tomasz Napierala if (racct->r_resources[resource] < 0) { 2574fe84775SEdward Tomasz Napierala KASSERT(RACCT_IS_SLOPPY(resource), 258097055e2SEdward Tomasz Napierala ("racct_alloc_resource: usage < 0")); 259097055e2SEdward Tomasz Napierala racct->r_resources[resource] = 0; 260097055e2SEdward Tomasz Napierala } 261097055e2SEdward Tomasz Napierala } 262097055e2SEdward Tomasz Napierala 2632d8696d1SEdward Tomasz Napierala static int 2642d8696d1SEdward Tomasz Napierala racct_add_locked(struct proc *p, int resource, uint64_t amount) 265097055e2SEdward Tomasz Napierala { 266097055e2SEdward Tomasz Napierala #ifdef RCTL 267097055e2SEdward Tomasz Napierala int error; 268097055e2SEdward Tomasz Napierala #endif 269097055e2SEdward Tomasz Napierala 270097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 271097055e2SEdward Tomasz Napierala return (0); 272097055e2SEdward Tomasz Napierala 273097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, add, p, resource, amount, 0, 0); 274097055e2SEdward Tomasz Napierala 275097055e2SEdward Tomasz Napierala /* 276097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 277097055e2SEdward Tomasz Napierala */ 278097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 279097055e2SEdward Tomasz Napierala 280097055e2SEdward Tomasz Napierala #ifdef RCTL 281097055e2SEdward Tomasz Napierala error = rctl_enforce(p, resource, amount); 2824fe84775SEdward Tomasz Napierala if (error && RACCT_IS_DENIABLE(resource)) { 283097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, add_failure, p, resource, 284097055e2SEdward Tomasz Napierala amount, 0, 0); 285097055e2SEdward Tomasz Napierala return (error); 286097055e2SEdward Tomasz Napierala } 287097055e2SEdward Tomasz Napierala #endif 288097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, amount); 289097055e2SEdward Tomasz Napierala racct_add_cred_locked(p->p_ucred, resource, amount); 290097055e2SEdward Tomasz Napierala 291097055e2SEdward Tomasz Napierala return (0); 292097055e2SEdward Tomasz Napierala } 293097055e2SEdward Tomasz Napierala 2942d8696d1SEdward Tomasz Napierala /* 2952d8696d1SEdward Tomasz Napierala * Increase allocation of 'resource' by 'amount' for process 'p'. 2962d8696d1SEdward Tomasz Napierala * Return 0 if it's below limits, or errno, if it's not. 2972d8696d1SEdward Tomasz Napierala */ 2982d8696d1SEdward Tomasz Napierala int 2992d8696d1SEdward Tomasz Napierala racct_add(struct proc *p, int resource, uint64_t amount) 3002d8696d1SEdward Tomasz Napierala { 3012d8696d1SEdward Tomasz Napierala int error; 3022d8696d1SEdward Tomasz Napierala 3032d8696d1SEdward Tomasz Napierala mtx_lock(&racct_lock); 3042d8696d1SEdward Tomasz Napierala error = racct_add_locked(p, resource, amount); 3052d8696d1SEdward Tomasz Napierala mtx_unlock(&racct_lock); 3062d8696d1SEdward Tomasz Napierala return (error); 3072d8696d1SEdward Tomasz Napierala } 3082d8696d1SEdward Tomasz Napierala 309097055e2SEdward Tomasz Napierala static void 310097055e2SEdward Tomasz Napierala racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount) 311097055e2SEdward Tomasz Napierala { 312097055e2SEdward Tomasz Napierala struct prison *pr; 313097055e2SEdward Tomasz Napierala 314097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, add_cred, cred, resource, amount, 315097055e2SEdward Tomasz Napierala 0, 0); 316097055e2SEdward Tomasz Napierala 317097055e2SEdward Tomasz Napierala racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, amount); 318097055e2SEdward Tomasz Napierala for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) 319a7ad07bfSEdward Tomasz Napierala racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource, 320a7ad07bfSEdward Tomasz Napierala amount); 321097055e2SEdward Tomasz Napierala racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, amount); 322097055e2SEdward Tomasz Napierala } 323097055e2SEdward Tomasz Napierala 324097055e2SEdward Tomasz Napierala /* 325097055e2SEdward Tomasz Napierala * Increase allocation of 'resource' by 'amount' for credential 'cred'. 326097055e2SEdward Tomasz Napierala * Doesn't check for limits and never fails. 327097055e2SEdward Tomasz Napierala * 328097055e2SEdward Tomasz Napierala * XXX: Shouldn't this ever return an error? 329097055e2SEdward Tomasz Napierala */ 330097055e2SEdward Tomasz Napierala void 331097055e2SEdward Tomasz Napierala racct_add_cred(struct ucred *cred, int resource, uint64_t amount) 332097055e2SEdward Tomasz Napierala { 333097055e2SEdward Tomasz Napierala 334097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 335097055e2SEdward Tomasz Napierala racct_add_cred_locked(cred, resource, amount); 336097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 337097055e2SEdward Tomasz Napierala } 338097055e2SEdward Tomasz Napierala 339097055e2SEdward Tomasz Napierala /* 340097055e2SEdward Tomasz Napierala * Increase allocation of 'resource' by 'amount' for process 'p'. 341097055e2SEdward Tomasz Napierala * Doesn't check for limits and never fails. 342097055e2SEdward Tomasz Napierala */ 343097055e2SEdward Tomasz Napierala void 344097055e2SEdward Tomasz Napierala racct_add_force(struct proc *p, int resource, uint64_t amount) 345097055e2SEdward Tomasz Napierala { 346097055e2SEdward Tomasz Napierala 347097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 348097055e2SEdward Tomasz Napierala return; 349097055e2SEdward Tomasz Napierala 350097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, add_force, p, resource, amount, 0, 0); 351097055e2SEdward Tomasz Napierala 352097055e2SEdward Tomasz Napierala /* 353097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 354097055e2SEdward Tomasz Napierala */ 355097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 356097055e2SEdward Tomasz Napierala 357097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 358097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, amount); 359097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 360097055e2SEdward Tomasz Napierala racct_add_cred(p->p_ucred, resource, amount); 361097055e2SEdward Tomasz Napierala } 362097055e2SEdward Tomasz Napierala 363097055e2SEdward Tomasz Napierala static int 364097055e2SEdward Tomasz Napierala racct_set_locked(struct proc *p, int resource, uint64_t amount) 365097055e2SEdward Tomasz Napierala { 366097055e2SEdward Tomasz Napierala int64_t diff; 367097055e2SEdward Tomasz Napierala #ifdef RCTL 368097055e2SEdward Tomasz Napierala int error; 369097055e2SEdward Tomasz Napierala #endif 370097055e2SEdward Tomasz Napierala 371097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 372097055e2SEdward Tomasz Napierala return (0); 373097055e2SEdward Tomasz Napierala 374097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0); 375097055e2SEdward Tomasz Napierala 376097055e2SEdward Tomasz Napierala /* 377097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 378097055e2SEdward Tomasz Napierala */ 379097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 380097055e2SEdward Tomasz Napierala 381097055e2SEdward Tomasz Napierala diff = amount - p->p_racct->r_resources[resource]; 382097055e2SEdward Tomasz Napierala #ifdef notyet 3834fe84775SEdward Tomasz Napierala KASSERT(diff >= 0 || RACCT_IS_RECLAIMABLE(resource), 384097055e2SEdward Tomasz Napierala ("racct_set: usage of non-reclaimable resource %d dropping", 385097055e2SEdward Tomasz Napierala resource)); 386097055e2SEdward Tomasz Napierala #endif 387097055e2SEdward Tomasz Napierala #ifdef RCTL 388097055e2SEdward Tomasz Napierala if (diff > 0) { 389097055e2SEdward Tomasz Napierala error = rctl_enforce(p, resource, diff); 3904fe84775SEdward Tomasz Napierala if (error && RACCT_IS_DENIABLE(resource)) { 391097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, set_failure, p, 392097055e2SEdward Tomasz Napierala resource, amount, 0, 0); 393097055e2SEdward Tomasz Napierala return (error); 394097055e2SEdward Tomasz Napierala } 395097055e2SEdward Tomasz Napierala } 396097055e2SEdward Tomasz Napierala #endif 397097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, diff); 398097055e2SEdward Tomasz Napierala if (diff > 0) 399097055e2SEdward Tomasz Napierala racct_add_cred_locked(p->p_ucred, resource, diff); 400097055e2SEdward Tomasz Napierala else if (diff < 0) 401097055e2SEdward Tomasz Napierala racct_sub_cred_locked(p->p_ucred, resource, -diff); 402097055e2SEdward Tomasz Napierala 403097055e2SEdward Tomasz Napierala return (0); 404097055e2SEdward Tomasz Napierala } 405097055e2SEdward Tomasz Napierala 406097055e2SEdward Tomasz Napierala /* 407097055e2SEdward Tomasz Napierala * Set allocation of 'resource' to 'amount' for process 'p'. 408097055e2SEdward Tomasz Napierala * Return 0 if it's below limits, or errno, if it's not. 409097055e2SEdward Tomasz Napierala * 410097055e2SEdward Tomasz Napierala * Note that decreasing the allocation always returns 0, 411097055e2SEdward Tomasz Napierala * even if it's above the limit. 412097055e2SEdward Tomasz Napierala */ 413097055e2SEdward Tomasz Napierala int 414097055e2SEdward Tomasz Napierala racct_set(struct proc *p, int resource, uint64_t amount) 415097055e2SEdward Tomasz Napierala { 416097055e2SEdward Tomasz Napierala int error; 417097055e2SEdward Tomasz Napierala 418097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 419097055e2SEdward Tomasz Napierala error = racct_set_locked(p, resource, amount); 420097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 421097055e2SEdward Tomasz Napierala return (error); 422097055e2SEdward Tomasz Napierala } 423097055e2SEdward Tomasz Napierala 424097055e2SEdward Tomasz Napierala void 425097055e2SEdward Tomasz Napierala racct_set_force(struct proc *p, int resource, uint64_t amount) 426097055e2SEdward Tomasz Napierala { 427097055e2SEdward Tomasz Napierala int64_t diff; 428097055e2SEdward Tomasz Napierala 429097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 430097055e2SEdward Tomasz Napierala return; 431097055e2SEdward Tomasz Napierala 432097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0); 433097055e2SEdward Tomasz Napierala 434097055e2SEdward Tomasz Napierala /* 435097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 436097055e2SEdward Tomasz Napierala */ 437097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 438097055e2SEdward Tomasz Napierala 439097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 440097055e2SEdward Tomasz Napierala diff = amount - p->p_racct->r_resources[resource]; 441097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, diff); 442097055e2SEdward Tomasz Napierala if (diff > 0) 443097055e2SEdward Tomasz Napierala racct_add_cred_locked(p->p_ucred, resource, diff); 444097055e2SEdward Tomasz Napierala else if (diff < 0) 445097055e2SEdward Tomasz Napierala racct_sub_cred_locked(p->p_ucred, resource, -diff); 446097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 447097055e2SEdward Tomasz Napierala } 448097055e2SEdward Tomasz Napierala 449097055e2SEdward Tomasz Napierala /* 450097055e2SEdward Tomasz Napierala * Returns amount of 'resource' the process 'p' can keep allocated. 451097055e2SEdward Tomasz Napierala * Allocating more than that would be denied, unless the resource 452097055e2SEdward Tomasz Napierala * is marked undeniable. Amount of already allocated resource does 453097055e2SEdward Tomasz Napierala * not matter. 454097055e2SEdward Tomasz Napierala */ 455097055e2SEdward Tomasz Napierala uint64_t 456097055e2SEdward Tomasz Napierala racct_get_limit(struct proc *p, int resource) 457097055e2SEdward Tomasz Napierala { 458097055e2SEdward Tomasz Napierala 459097055e2SEdward Tomasz Napierala #ifdef RCTL 460097055e2SEdward Tomasz Napierala return (rctl_get_limit(p, resource)); 461097055e2SEdward Tomasz Napierala #else 462097055e2SEdward Tomasz Napierala return (UINT64_MAX); 463097055e2SEdward Tomasz Napierala #endif 464097055e2SEdward Tomasz Napierala } 465097055e2SEdward Tomasz Napierala 466097055e2SEdward Tomasz Napierala /* 467097055e2SEdward Tomasz Napierala * Returns amount of 'resource' the process 'p' can keep allocated. 468097055e2SEdward Tomasz Napierala * Allocating more than that would be denied, unless the resource 469097055e2SEdward Tomasz Napierala * is marked undeniable. Amount of already allocated resource does 470097055e2SEdward Tomasz Napierala * matter. 471097055e2SEdward Tomasz Napierala */ 472097055e2SEdward Tomasz Napierala uint64_t 473097055e2SEdward Tomasz Napierala racct_get_available(struct proc *p, int resource) 474097055e2SEdward Tomasz Napierala { 475097055e2SEdward Tomasz Napierala 476097055e2SEdward Tomasz Napierala #ifdef RCTL 477097055e2SEdward Tomasz Napierala return (rctl_get_available(p, resource)); 478097055e2SEdward Tomasz Napierala #else 479097055e2SEdward Tomasz Napierala return (UINT64_MAX); 480097055e2SEdward Tomasz Napierala #endif 481097055e2SEdward Tomasz Napierala } 482097055e2SEdward Tomasz Napierala 483097055e2SEdward Tomasz Napierala /* 484097055e2SEdward Tomasz Napierala * Decrease allocation of 'resource' by 'amount' for process 'p'. 485097055e2SEdward Tomasz Napierala */ 486097055e2SEdward Tomasz Napierala void 487097055e2SEdward Tomasz Napierala racct_sub(struct proc *p, int resource, uint64_t amount) 488097055e2SEdward Tomasz Napierala { 489097055e2SEdward Tomasz Napierala 490097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 491097055e2SEdward Tomasz Napierala return; 492097055e2SEdward Tomasz Napierala 493097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, sub, p, resource, amount, 0, 0); 494097055e2SEdward Tomasz Napierala 495097055e2SEdward Tomasz Napierala /* 496097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 497097055e2SEdward Tomasz Napierala */ 498097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 4994fe84775SEdward Tomasz Napierala KASSERT(RACCT_IS_RECLAIMABLE(resource), 500097055e2SEdward Tomasz Napierala ("racct_sub: called for non-reclaimable resource %d", resource)); 501097055e2SEdward Tomasz Napierala 502097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 503097055e2SEdward Tomasz Napierala KASSERT(amount <= p->p_racct->r_resources[resource], 504097055e2SEdward Tomasz Napierala ("racct_sub: freeing %ju of resource %d, which is more " 505097055e2SEdward Tomasz Napierala "than allocated %jd for %s (pid %d)", amount, resource, 506097055e2SEdward Tomasz Napierala (intmax_t)p->p_racct->r_resources[resource], p->p_comm, p->p_pid)); 507097055e2SEdward Tomasz Napierala 508097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, -amount); 509097055e2SEdward Tomasz Napierala racct_sub_cred_locked(p->p_ucred, resource, amount); 510097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 511097055e2SEdward Tomasz Napierala } 512097055e2SEdward Tomasz Napierala 513097055e2SEdward Tomasz Napierala static void 514097055e2SEdward Tomasz Napierala racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount) 515097055e2SEdward Tomasz Napierala { 516097055e2SEdward Tomasz Napierala struct prison *pr; 517097055e2SEdward Tomasz Napierala 518097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, sub_cred, cred, resource, amount, 519097055e2SEdward Tomasz Napierala 0, 0); 520097055e2SEdward Tomasz Napierala 521097055e2SEdward Tomasz Napierala #ifdef notyet 5224fe84775SEdward Tomasz Napierala KASSERT(RACCT_IS_RECLAIMABLE(resource), 523097055e2SEdward Tomasz Napierala ("racct_sub_cred: called for non-reclaimable resource %d", 524097055e2SEdward Tomasz Napierala resource)); 525097055e2SEdward Tomasz Napierala #endif 526097055e2SEdward Tomasz Napierala 527097055e2SEdward Tomasz Napierala racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, -amount); 528097055e2SEdward Tomasz Napierala for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) 529a7ad07bfSEdward Tomasz Napierala racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource, 530a7ad07bfSEdward Tomasz Napierala -amount); 531097055e2SEdward Tomasz Napierala racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, -amount); 532097055e2SEdward Tomasz Napierala } 533097055e2SEdward Tomasz Napierala 534097055e2SEdward Tomasz Napierala /* 535097055e2SEdward Tomasz Napierala * Decrease allocation of 'resource' by 'amount' for credential 'cred'. 536097055e2SEdward Tomasz Napierala */ 537097055e2SEdward Tomasz Napierala void 538097055e2SEdward Tomasz Napierala racct_sub_cred(struct ucred *cred, int resource, uint64_t amount) 539097055e2SEdward Tomasz Napierala { 540097055e2SEdward Tomasz Napierala 541097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 542097055e2SEdward Tomasz Napierala racct_sub_cred_locked(cred, resource, amount); 543097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 544097055e2SEdward Tomasz Napierala } 545097055e2SEdward Tomasz Napierala 546097055e2SEdward Tomasz Napierala /* 547097055e2SEdward Tomasz Napierala * Inherit resource usage information from the parent process. 548097055e2SEdward Tomasz Napierala */ 549097055e2SEdward Tomasz Napierala int 550097055e2SEdward Tomasz Napierala racct_proc_fork(struct proc *parent, struct proc *child) 551097055e2SEdward Tomasz Napierala { 552097055e2SEdward Tomasz Napierala int i, error = 0; 553097055e2SEdward Tomasz Napierala 554097055e2SEdward Tomasz Napierala /* 555097055e2SEdward Tomasz Napierala * Create racct for the child process. 556097055e2SEdward Tomasz Napierala */ 557097055e2SEdward Tomasz Napierala racct_create(&child->p_racct); 558097055e2SEdward Tomasz Napierala 559097055e2SEdward Tomasz Napierala /* 560097055e2SEdward Tomasz Napierala * No resource accounting for kernel processes. 561097055e2SEdward Tomasz Napierala */ 562097055e2SEdward Tomasz Napierala if (child->p_flag & P_SYSTEM) 563097055e2SEdward Tomasz Napierala return (0); 564097055e2SEdward Tomasz Napierala 565097055e2SEdward Tomasz Napierala PROC_LOCK(parent); 566097055e2SEdward Tomasz Napierala PROC_LOCK(child); 567097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 568097055e2SEdward Tomasz Napierala 569c0c09362SEdward Tomasz Napierala #ifdef RCTL 570c0c09362SEdward Tomasz Napierala error = rctl_proc_fork(parent, child); 571c0c09362SEdward Tomasz Napierala if (error != 0) 572c0c09362SEdward Tomasz Napierala goto out; 573c0c09362SEdward Tomasz Napierala #endif 574c0c09362SEdward Tomasz Napierala 575097055e2SEdward Tomasz Napierala /* 576097055e2SEdward Tomasz Napierala * Inherit resource usage. 577097055e2SEdward Tomasz Napierala */ 578097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 579097055e2SEdward Tomasz Napierala if (parent->p_racct->r_resources[i] == 0 || 5804fe84775SEdward Tomasz Napierala !RACCT_IS_INHERITABLE(i)) 581097055e2SEdward Tomasz Napierala continue; 582097055e2SEdward Tomasz Napierala 583097055e2SEdward Tomasz Napierala error = racct_set_locked(child, i, 584097055e2SEdward Tomasz Napierala parent->p_racct->r_resources[i]); 585ac6fafe6SEdward Tomasz Napierala if (error != 0) 586097055e2SEdward Tomasz Napierala goto out; 587097055e2SEdward Tomasz Napierala } 588097055e2SEdward Tomasz Napierala 5892d8696d1SEdward Tomasz Napierala error = racct_add_locked(child, RACCT_NPROC, 1); 5902d8696d1SEdward Tomasz Napierala error += racct_add_locked(child, RACCT_NTHR, 1); 5912d8696d1SEdward Tomasz Napierala 592097055e2SEdward Tomasz Napierala out: 593097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 594097055e2SEdward Tomasz Napierala PROC_UNLOCK(child); 595097055e2SEdward Tomasz Napierala PROC_UNLOCK(parent); 596097055e2SEdward Tomasz Napierala 597097055e2SEdward Tomasz Napierala return (error); 598097055e2SEdward Tomasz Napierala } 599097055e2SEdward Tomasz Napierala 60072a401d9SEdward Tomasz Napierala /* 60172a401d9SEdward Tomasz Napierala * Called at the end of fork1(), to handle rules that require the process 60272a401d9SEdward Tomasz Napierala * to be fully initialized. 60372a401d9SEdward Tomasz Napierala */ 60472a401d9SEdward Tomasz Napierala void 60572a401d9SEdward Tomasz Napierala racct_proc_fork_done(struct proc *child) 60672a401d9SEdward Tomasz Napierala { 60772a401d9SEdward Tomasz Napierala 60872a401d9SEdward Tomasz Napierala #ifdef RCTL 60972a401d9SEdward Tomasz Napierala PROC_LOCK(child); 61072a401d9SEdward Tomasz Napierala mtx_lock(&racct_lock); 61172a401d9SEdward Tomasz Napierala rctl_enforce(child, RACCT_NPROC, 0); 61272a401d9SEdward Tomasz Napierala rctl_enforce(child, RACCT_NTHR, 0); 61372a401d9SEdward Tomasz Napierala mtx_unlock(&racct_lock); 61472a401d9SEdward Tomasz Napierala PROC_UNLOCK(child); 61572a401d9SEdward Tomasz Napierala #endif 61672a401d9SEdward Tomasz Napierala } 61772a401d9SEdward Tomasz Napierala 618097055e2SEdward Tomasz Napierala void 619097055e2SEdward Tomasz Napierala racct_proc_exit(struct proc *p) 620097055e2SEdward Tomasz Napierala { 6212419d7f9SEdward Tomasz Napierala int i; 622097055e2SEdward Tomasz Napierala uint64_t runtime; 623097055e2SEdward Tomasz Napierala 624097055e2SEdward Tomasz Napierala PROC_LOCK(p); 625097055e2SEdward Tomasz Napierala /* 626097055e2SEdward Tomasz Napierala * We don't need to calculate rux, proc_reap() has already done this. 627097055e2SEdward Tomasz Napierala */ 628097055e2SEdward Tomasz Napierala runtime = cputick2usec(p->p_rux.rux_runtime); 629097055e2SEdward Tomasz Napierala #ifdef notyet 630097055e2SEdward Tomasz Napierala KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime")); 631097055e2SEdward Tomasz Napierala #else 632097055e2SEdward Tomasz Napierala if (runtime < p->p_prev_runtime) 633097055e2SEdward Tomasz Napierala runtime = p->p_prev_runtime; 634097055e2SEdward Tomasz Napierala #endif 6352419d7f9SEdward Tomasz Napierala mtx_lock(&racct_lock); 6362419d7f9SEdward Tomasz Napierala racct_set_locked(p, RACCT_CPU, runtime); 637097055e2SEdward Tomasz Napierala 6382419d7f9SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 6392419d7f9SEdward Tomasz Napierala if (p->p_racct->r_resources[i] == 0) 6402419d7f9SEdward Tomasz Napierala continue; 6412419d7f9SEdward Tomasz Napierala if (!RACCT_IS_RECLAIMABLE(i)) 6422419d7f9SEdward Tomasz Napierala continue; 6432419d7f9SEdward Tomasz Napierala racct_set_locked(p, i, 0); 6442419d7f9SEdward Tomasz Napierala } 6452419d7f9SEdward Tomasz Napierala 6462419d7f9SEdward Tomasz Napierala mtx_unlock(&racct_lock); 647097055e2SEdward Tomasz Napierala PROC_UNLOCK(p); 648097055e2SEdward Tomasz Napierala 649097055e2SEdward Tomasz Napierala #ifdef RCTL 650097055e2SEdward Tomasz Napierala rctl_racct_release(p->p_racct); 651097055e2SEdward Tomasz Napierala #endif 652097055e2SEdward Tomasz Napierala racct_destroy(&p->p_racct); 653097055e2SEdward Tomasz Napierala } 654097055e2SEdward Tomasz Napierala 655097055e2SEdward Tomasz Napierala /* 656097055e2SEdward Tomasz Napierala * Called after credentials change, to move resource utilisation 657097055e2SEdward Tomasz Napierala * between raccts. 658097055e2SEdward Tomasz Napierala */ 659097055e2SEdward Tomasz Napierala void 660097055e2SEdward Tomasz Napierala racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred, 661097055e2SEdward Tomasz Napierala struct ucred *newcred) 662097055e2SEdward Tomasz Napierala { 663097055e2SEdward Tomasz Napierala struct uidinfo *olduip, *newuip; 664097055e2SEdward Tomasz Napierala struct loginclass *oldlc, *newlc; 665097055e2SEdward Tomasz Napierala struct prison *oldpr, *newpr, *pr; 666097055e2SEdward Tomasz Napierala 667097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_NOTOWNED); 668097055e2SEdward Tomasz Napierala 669097055e2SEdward Tomasz Napierala newuip = newcred->cr_ruidinfo; 670097055e2SEdward Tomasz Napierala olduip = oldcred->cr_ruidinfo; 671097055e2SEdward Tomasz Napierala newlc = newcred->cr_loginclass; 672097055e2SEdward Tomasz Napierala oldlc = oldcred->cr_loginclass; 673097055e2SEdward Tomasz Napierala newpr = newcred->cr_prison; 674097055e2SEdward Tomasz Napierala oldpr = oldcred->cr_prison; 675097055e2SEdward Tomasz Napierala 676097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 677097055e2SEdward Tomasz Napierala if (newuip != olduip) { 678097055e2SEdward Tomasz Napierala racct_sub_racct(olduip->ui_racct, p->p_racct); 679097055e2SEdward Tomasz Napierala racct_add_racct(newuip->ui_racct, p->p_racct); 680097055e2SEdward Tomasz Napierala } 681097055e2SEdward Tomasz Napierala if (newlc != oldlc) { 682097055e2SEdward Tomasz Napierala racct_sub_racct(oldlc->lc_racct, p->p_racct); 683097055e2SEdward Tomasz Napierala racct_add_racct(newlc->lc_racct, p->p_racct); 684097055e2SEdward Tomasz Napierala } 685097055e2SEdward Tomasz Napierala if (newpr != oldpr) { 686097055e2SEdward Tomasz Napierala for (pr = oldpr; pr != NULL; pr = pr->pr_parent) 687a7ad07bfSEdward Tomasz Napierala racct_sub_racct(pr->pr_prison_racct->prr_racct, 688a7ad07bfSEdward Tomasz Napierala p->p_racct); 689097055e2SEdward Tomasz Napierala for (pr = newpr; pr != NULL; pr = pr->pr_parent) 690a7ad07bfSEdward Tomasz Napierala racct_add_racct(pr->pr_prison_racct->prr_racct, 691a7ad07bfSEdward Tomasz Napierala p->p_racct); 692097055e2SEdward Tomasz Napierala } 693097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 694097055e2SEdward Tomasz Napierala 695097055e2SEdward Tomasz Napierala #ifdef RCTL 696097055e2SEdward Tomasz Napierala rctl_proc_ucred_changed(p, newcred); 697097055e2SEdward Tomasz Napierala #endif 698097055e2SEdward Tomasz Napierala } 699097055e2SEdward Tomasz Napierala 700097055e2SEdward Tomasz Napierala static void 701097055e2SEdward Tomasz Napierala racctd(void) 702097055e2SEdward Tomasz Napierala { 703097055e2SEdward Tomasz Napierala struct thread *td; 704097055e2SEdward Tomasz Napierala struct proc *p; 705097055e2SEdward Tomasz Napierala struct timeval wallclock; 706097055e2SEdward Tomasz Napierala uint64_t runtime; 707097055e2SEdward Tomasz Napierala 708097055e2SEdward Tomasz Napierala for (;;) { 709097055e2SEdward Tomasz Napierala sx_slock(&allproc_lock); 710097055e2SEdward Tomasz Napierala 711097055e2SEdward Tomasz Napierala FOREACH_PROC_IN_SYSTEM(p) { 712097055e2SEdward Tomasz Napierala if (p->p_state != PRS_NORMAL) 713097055e2SEdward Tomasz Napierala continue; 714097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 715097055e2SEdward Tomasz Napierala continue; 716097055e2SEdward Tomasz Napierala 717097055e2SEdward Tomasz Napierala microuptime(&wallclock); 718097055e2SEdward Tomasz Napierala timevalsub(&wallclock, &p->p_stats->p_start); 719097055e2SEdward Tomasz Napierala PROC_LOCK(p); 720097055e2SEdward Tomasz Napierala PROC_SLOCK(p); 721097055e2SEdward Tomasz Napierala FOREACH_THREAD_IN_PROC(p, td) { 722097055e2SEdward Tomasz Napierala ruxagg(p, td); 723097055e2SEdward Tomasz Napierala thread_lock(td); 724097055e2SEdward Tomasz Napierala thread_unlock(td); 725097055e2SEdward Tomasz Napierala } 726097055e2SEdward Tomasz Napierala runtime = cputick2usec(p->p_rux.rux_runtime); 727097055e2SEdward Tomasz Napierala PROC_SUNLOCK(p); 728097055e2SEdward Tomasz Napierala #ifdef notyet 729097055e2SEdward Tomasz Napierala KASSERT(runtime >= p->p_prev_runtime, 730097055e2SEdward Tomasz Napierala ("runtime < p_prev_runtime")); 731097055e2SEdward Tomasz Napierala #else 732097055e2SEdward Tomasz Napierala if (runtime < p->p_prev_runtime) 733097055e2SEdward Tomasz Napierala runtime = p->p_prev_runtime; 734097055e2SEdward Tomasz Napierala #endif 735097055e2SEdward Tomasz Napierala p->p_prev_runtime = runtime; 736097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 737097055e2SEdward Tomasz Napierala racct_set_locked(p, RACCT_CPU, runtime); 738097055e2SEdward Tomasz Napierala racct_set_locked(p, RACCT_WALLCLOCK, 739097055e2SEdward Tomasz Napierala wallclock.tv_sec * 1000000 + wallclock.tv_usec); 740097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 741097055e2SEdward Tomasz Napierala PROC_UNLOCK(p); 742097055e2SEdward Tomasz Napierala } 743097055e2SEdward Tomasz Napierala sx_sunlock(&allproc_lock); 744097055e2SEdward Tomasz Napierala pause("-", hz); 745097055e2SEdward Tomasz Napierala } 746097055e2SEdward Tomasz Napierala } 747097055e2SEdward Tomasz Napierala 748097055e2SEdward Tomasz Napierala static struct kproc_desc racctd_kp = { 749097055e2SEdward Tomasz Napierala "racctd", 750097055e2SEdward Tomasz Napierala racctd, 751097055e2SEdward Tomasz Napierala NULL 752097055e2SEdward Tomasz Napierala }; 753097055e2SEdward Tomasz Napierala SYSINIT(racctd, SI_SUB_RACCTD, SI_ORDER_FIRST, kproc_start, &racctd_kp); 754097055e2SEdward Tomasz Napierala 755097055e2SEdward Tomasz Napierala static void 756097055e2SEdward Tomasz Napierala racct_init(void) 757097055e2SEdward Tomasz Napierala { 758097055e2SEdward Tomasz Napierala 759097055e2SEdward Tomasz Napierala racct_zone = uma_zcreate("racct", sizeof(struct racct), 760097055e2SEdward Tomasz Napierala NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 761097055e2SEdward Tomasz Napierala /* 762097055e2SEdward Tomasz Napierala * XXX: Move this somewhere. 763097055e2SEdward Tomasz Napierala */ 764a7ad07bfSEdward Tomasz Napierala prison0.pr_prison_racct = prison_racct_find("0"); 765097055e2SEdward Tomasz Napierala } 766097055e2SEdward Tomasz Napierala SYSINIT(racct, SI_SUB_RACCT, SI_ORDER_FIRST, racct_init, NULL); 767097055e2SEdward Tomasz Napierala 768097055e2SEdward Tomasz Napierala #else /* !RACCT */ 769097055e2SEdward Tomasz Napierala 770097055e2SEdward Tomasz Napierala int 771097055e2SEdward Tomasz Napierala racct_add(struct proc *p, int resource, uint64_t amount) 772097055e2SEdward Tomasz Napierala { 773097055e2SEdward Tomasz Napierala 774097055e2SEdward Tomasz Napierala return (0); 775097055e2SEdward Tomasz Napierala } 776097055e2SEdward Tomasz Napierala 777097055e2SEdward Tomasz Napierala void 778097055e2SEdward Tomasz Napierala racct_add_cred(struct ucred *cred, int resource, uint64_t amount) 779097055e2SEdward Tomasz Napierala { 780097055e2SEdward Tomasz Napierala } 781097055e2SEdward Tomasz Napierala 782097055e2SEdward Tomasz Napierala void 783097055e2SEdward Tomasz Napierala racct_add_force(struct proc *p, int resource, uint64_t amount) 784097055e2SEdward Tomasz Napierala { 785097055e2SEdward Tomasz Napierala 786097055e2SEdward Tomasz Napierala return; 787097055e2SEdward Tomasz Napierala } 788097055e2SEdward Tomasz Napierala 789097055e2SEdward Tomasz Napierala int 790097055e2SEdward Tomasz Napierala racct_set(struct proc *p, int resource, uint64_t amount) 791097055e2SEdward Tomasz Napierala { 792097055e2SEdward Tomasz Napierala 793097055e2SEdward Tomasz Napierala return (0); 794097055e2SEdward Tomasz Napierala } 795097055e2SEdward Tomasz Napierala 796097055e2SEdward Tomasz Napierala void 797c98fe0a5SEdward Tomasz Napierala racct_set_force(struct proc *p, int resource, uint64_t amount) 798c98fe0a5SEdward Tomasz Napierala { 799c98fe0a5SEdward Tomasz Napierala } 800c98fe0a5SEdward Tomasz Napierala 801c98fe0a5SEdward Tomasz Napierala void 802097055e2SEdward Tomasz Napierala racct_sub(struct proc *p, int resource, uint64_t amount) 803097055e2SEdward Tomasz Napierala { 804097055e2SEdward Tomasz Napierala } 805097055e2SEdward Tomasz Napierala 806097055e2SEdward Tomasz Napierala void 807097055e2SEdward Tomasz Napierala racct_sub_cred(struct ucred *cred, int resource, uint64_t amount) 808097055e2SEdward Tomasz Napierala { 809097055e2SEdward Tomasz Napierala } 810097055e2SEdward Tomasz Napierala 811097055e2SEdward Tomasz Napierala uint64_t 812097055e2SEdward Tomasz Napierala racct_get_limit(struct proc *p, int resource) 813097055e2SEdward Tomasz Napierala { 814097055e2SEdward Tomasz Napierala 815097055e2SEdward Tomasz Napierala return (UINT64_MAX); 816097055e2SEdward Tomasz Napierala } 817097055e2SEdward Tomasz Napierala 818c98fe0a5SEdward Tomasz Napierala uint64_t 819c98fe0a5SEdward Tomasz Napierala racct_get_available(struct proc *p, int resource) 820c98fe0a5SEdward Tomasz Napierala { 821c98fe0a5SEdward Tomasz Napierala 822c98fe0a5SEdward Tomasz Napierala return (UINT64_MAX); 823c98fe0a5SEdward Tomasz Napierala } 824c98fe0a5SEdward Tomasz Napierala 825097055e2SEdward Tomasz Napierala void 826097055e2SEdward Tomasz Napierala racct_create(struct racct **racctp) 827097055e2SEdward Tomasz Napierala { 828097055e2SEdward Tomasz Napierala } 829097055e2SEdward Tomasz Napierala 830097055e2SEdward Tomasz Napierala void 831097055e2SEdward Tomasz Napierala racct_destroy(struct racct **racctp) 832097055e2SEdward Tomasz Napierala { 833097055e2SEdward Tomasz Napierala } 834097055e2SEdward Tomasz Napierala 835097055e2SEdward Tomasz Napierala int 836097055e2SEdward Tomasz Napierala racct_proc_fork(struct proc *parent, struct proc *child) 837097055e2SEdward Tomasz Napierala { 838097055e2SEdward Tomasz Napierala 839097055e2SEdward Tomasz Napierala return (0); 840097055e2SEdward Tomasz Napierala } 841097055e2SEdward Tomasz Napierala 842097055e2SEdward Tomasz Napierala void 84372a401d9SEdward Tomasz Napierala racct_proc_fork_done(struct proc *child) 84472a401d9SEdward Tomasz Napierala { 84572a401d9SEdward Tomasz Napierala } 84672a401d9SEdward Tomasz Napierala 84772a401d9SEdward Tomasz Napierala void 848097055e2SEdward Tomasz Napierala racct_proc_exit(struct proc *p) 849097055e2SEdward Tomasz Napierala { 850097055e2SEdward Tomasz Napierala } 851097055e2SEdward Tomasz Napierala 852097055e2SEdward Tomasz Napierala #endif /* !RACCT */ 853