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> 38097055e2SEdward Tomasz Napierala #include <sys/eventhandler.h> 39097055e2SEdward Tomasz Napierala #include <sys/param.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/systm.h> 57097055e2SEdward Tomasz Napierala #include <sys/umtx.h> 58097055e2SEdward Tomasz Napierala 59097055e2SEdward Tomasz Napierala #ifdef RCTL 60097055e2SEdward Tomasz Napierala #include <sys/rctl.h> 61097055e2SEdward Tomasz Napierala #endif 62097055e2SEdward Tomasz Napierala 63097055e2SEdward Tomasz Napierala #ifdef RACCT 64097055e2SEdward Tomasz Napierala 65097055e2SEdward Tomasz Napierala FEATURE(racct, "Resource Accounting"); 66097055e2SEdward Tomasz Napierala 67097055e2SEdward Tomasz Napierala static struct mtx racct_lock; 68097055e2SEdward Tomasz Napierala MTX_SYSINIT(racct_lock, &racct_lock, "racct lock", MTX_DEF); 69097055e2SEdward Tomasz Napierala 70097055e2SEdward Tomasz Napierala static uma_zone_t racct_zone; 71097055e2SEdward Tomasz Napierala 72097055e2SEdward Tomasz Napierala static void racct_sub_racct(struct racct *dest, const struct racct *src); 73097055e2SEdward Tomasz Napierala static void racct_sub_cred_locked(struct ucred *cred, int resource, 74097055e2SEdward Tomasz Napierala uint64_t amount); 75097055e2SEdward Tomasz Napierala static void racct_add_cred_locked(struct ucred *cred, int resource, 76097055e2SEdward Tomasz Napierala uint64_t amount); 77097055e2SEdward Tomasz Napierala 78097055e2SEdward Tomasz Napierala SDT_PROVIDER_DEFINE(racct); 79097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, add, add, "struct proc *", "int", 80097055e2SEdward Tomasz Napierala "uint64_t"); 81097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, add_failure, add-failure, 82097055e2SEdward Tomasz Napierala "struct proc *", "int", "uint64_t"); 83097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, add_cred, add-cred, "struct ucred *", 84097055e2SEdward Tomasz Napierala "int", "uint64_t"); 85097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, add_force, add-force, "struct proc *", 86097055e2SEdward Tomasz Napierala "int", "uint64_t"); 87097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, set, set, "struct proc *", "int", 88097055e2SEdward Tomasz Napierala "uint64_t"); 89097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, set_failure, set-failure, 90097055e2SEdward Tomasz Napierala "struct proc *", "int", "uint64_t"); 91097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, sub, sub, "struct proc *", "int", 92097055e2SEdward Tomasz Napierala "uint64_t"); 93097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE3(racct, kernel, rusage, sub_cred, sub-cred, "struct ucred *", 94097055e2SEdward Tomasz Napierala "int", "uint64_t"); 95097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE1(racct, kernel, racct, create, create, "struct racct *"); 96097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE1(racct, kernel, racct, destroy, destroy, "struct racct *"); 97097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE2(racct, kernel, racct, join, join, "struct racct *", 98097055e2SEdward Tomasz Napierala "struct racct *"); 99097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE2(racct, kernel, racct, join_failure, join-failure, 100097055e2SEdward Tomasz Napierala "struct racct *", "struct racct *"); 101097055e2SEdward Tomasz Napierala SDT_PROBE_DEFINE2(racct, kernel, racct, leave, leave, "struct racct *", 102097055e2SEdward Tomasz Napierala "struct racct *"); 103097055e2SEdward Tomasz Napierala 104097055e2SEdward Tomasz Napierala int racct_types[] = { 105097055e2SEdward Tomasz Napierala [RACCT_CPU] = 10685a2f1b4SEdward Tomasz Napierala RACCT_IN_MILLIONS, 107097055e2SEdward Tomasz Napierala [RACCT_DATA] = 108097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 109097055e2SEdward Tomasz Napierala [RACCT_STACK] = 110097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 111097055e2SEdward Tomasz Napierala [RACCT_CORE] = 112097055e2SEdward Tomasz Napierala RACCT_DENIABLE, 113097055e2SEdward Tomasz Napierala [RACCT_RSS] = 114097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE, 115097055e2SEdward Tomasz Napierala [RACCT_MEMLOCK] = 116097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE, 117097055e2SEdward Tomasz Napierala [RACCT_NPROC] = 118097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE, 119097055e2SEdward Tomasz Napierala [RACCT_NOFILE] = 120097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 121097055e2SEdward Tomasz Napierala [RACCT_VMEM] = 122097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 123097055e2SEdward Tomasz Napierala [RACCT_NPTS] = 124097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 125097055e2SEdward Tomasz Napierala [RACCT_SWAP] = 126097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 127097055e2SEdward Tomasz Napierala [RACCT_NTHR] = 128097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE, 129097055e2SEdward Tomasz Napierala [RACCT_MSGQQUEUED] = 130097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 131097055e2SEdward Tomasz Napierala [RACCT_MSGQSIZE] = 132097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 133097055e2SEdward Tomasz Napierala [RACCT_NMSGQ] = 134097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 135097055e2SEdward Tomasz Napierala [RACCT_NSEM] = 136097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 137097055e2SEdward Tomasz Napierala [RACCT_NSEMOP] = 138097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE, 139097055e2SEdward Tomasz Napierala [RACCT_NSHM] = 140097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 141097055e2SEdward Tomasz Napierala [RACCT_SHMSIZE] = 142097055e2SEdward Tomasz Napierala RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY, 143097055e2SEdward Tomasz Napierala [RACCT_WALLCLOCK] = 14485a2f1b4SEdward Tomasz Napierala RACCT_IN_MILLIONS }; 145097055e2SEdward Tomasz Napierala 146097055e2SEdward Tomasz Napierala static void 147097055e2SEdward Tomasz Napierala racct_add_racct(struct racct *dest, const struct racct *src) 148097055e2SEdward Tomasz Napierala { 149097055e2SEdward Tomasz Napierala int i; 150097055e2SEdward Tomasz Napierala 151097055e2SEdward Tomasz Napierala mtx_assert(&racct_lock, MA_OWNED); 152097055e2SEdward Tomasz Napierala 153097055e2SEdward Tomasz Napierala /* 154097055e2SEdward Tomasz Napierala * Update resource usage in dest. 155097055e2SEdward Tomasz Napierala */ 156097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 157097055e2SEdward Tomasz Napierala KASSERT(dest->r_resources[i] >= 0, 158097055e2SEdward Tomasz Napierala ("racct propagation meltdown: dest < 0")); 159097055e2SEdward Tomasz Napierala KASSERT(src->r_resources[i] >= 0, 160097055e2SEdward Tomasz Napierala ("racct propagation meltdown: src < 0")); 161097055e2SEdward Tomasz Napierala dest->r_resources[i] += src->r_resources[i]; 162097055e2SEdward Tomasz Napierala } 163097055e2SEdward Tomasz Napierala } 164097055e2SEdward Tomasz Napierala 165097055e2SEdward Tomasz Napierala static void 166097055e2SEdward Tomasz Napierala racct_sub_racct(struct racct *dest, const struct racct *src) 167097055e2SEdward Tomasz Napierala { 168097055e2SEdward Tomasz Napierala int i; 169097055e2SEdward Tomasz Napierala 170097055e2SEdward Tomasz Napierala mtx_assert(&racct_lock, MA_OWNED); 171097055e2SEdward Tomasz Napierala 172097055e2SEdward Tomasz Napierala /* 173097055e2SEdward Tomasz Napierala * Update resource usage in dest. 174097055e2SEdward Tomasz Napierala */ 175097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 1764fe84775SEdward Tomasz Napierala if (!RACCT_IS_SLOPPY(i)) { 177097055e2SEdward Tomasz Napierala KASSERT(dest->r_resources[i] >= 0, 178097055e2SEdward Tomasz Napierala ("racct propagation meltdown: dest < 0")); 179097055e2SEdward Tomasz Napierala KASSERT(src->r_resources[i] >= 0, 180097055e2SEdward Tomasz Napierala ("racct propagation meltdown: src < 0")); 181097055e2SEdward Tomasz Napierala KASSERT(src->r_resources[i] <= dest->r_resources[i], 182097055e2SEdward Tomasz Napierala ("racct propagation meltdown: src > dest")); 183097055e2SEdward Tomasz Napierala } 1844fe84775SEdward Tomasz Napierala if (RACCT_IS_RECLAIMABLE(i)) { 185097055e2SEdward Tomasz Napierala dest->r_resources[i] -= src->r_resources[i]; 186097055e2SEdward Tomasz Napierala if (dest->r_resources[i] < 0) { 1874fe84775SEdward Tomasz Napierala KASSERT(RACCT_IS_SLOPPY(i), 188097055e2SEdward Tomasz Napierala ("racct_sub_racct: usage < 0")); 189097055e2SEdward Tomasz Napierala dest->r_resources[i] = 0; 190097055e2SEdward Tomasz Napierala } 191097055e2SEdward Tomasz Napierala } 192097055e2SEdward Tomasz Napierala } 193097055e2SEdward Tomasz Napierala } 194097055e2SEdward Tomasz Napierala 195097055e2SEdward Tomasz Napierala void 196097055e2SEdward Tomasz Napierala racct_create(struct racct **racctp) 197097055e2SEdward Tomasz Napierala { 198097055e2SEdward Tomasz Napierala 199097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, racct, create, racctp, 0, 0, 0, 0); 200097055e2SEdward Tomasz Napierala 201097055e2SEdward Tomasz Napierala KASSERT(*racctp == NULL, ("racct already allocated")); 202097055e2SEdward Tomasz Napierala 203097055e2SEdward Tomasz Napierala *racctp = uma_zalloc(racct_zone, M_WAITOK | M_ZERO); 204097055e2SEdward Tomasz Napierala } 205097055e2SEdward Tomasz Napierala 206097055e2SEdward Tomasz Napierala static void 207097055e2SEdward Tomasz Napierala racct_destroy_locked(struct racct **racctp) 208097055e2SEdward Tomasz Napierala { 209097055e2SEdward Tomasz Napierala int i; 210097055e2SEdward Tomasz Napierala struct racct *racct; 211097055e2SEdward Tomasz Napierala 212097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, racct, destroy, racctp, 0, 0, 0, 0); 213097055e2SEdward Tomasz Napierala 214097055e2SEdward Tomasz Napierala mtx_assert(&racct_lock, MA_OWNED); 215097055e2SEdward Tomasz Napierala KASSERT(racctp != NULL, ("NULL racctp")); 216097055e2SEdward Tomasz Napierala KASSERT(*racctp != NULL, ("NULL racct")); 217097055e2SEdward Tomasz Napierala 218097055e2SEdward Tomasz Napierala racct = *racctp; 219097055e2SEdward Tomasz Napierala 220097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 2214fe84775SEdward Tomasz Napierala if (RACCT_IS_SLOPPY(i)) 222097055e2SEdward Tomasz Napierala continue; 2234fe84775SEdward Tomasz Napierala if (!RACCT_IS_RECLAIMABLE(i)) 224097055e2SEdward Tomasz Napierala continue; 225097055e2SEdward Tomasz Napierala KASSERT(racct->r_resources[i] == 0, 226097055e2SEdward Tomasz Napierala ("destroying non-empty racct: " 227097055e2SEdward Tomasz Napierala "%ju allocated for resource %d\n", 228097055e2SEdward Tomasz Napierala racct->r_resources[i], i)); 229097055e2SEdward Tomasz Napierala } 230097055e2SEdward Tomasz Napierala uma_zfree(racct_zone, racct); 231097055e2SEdward Tomasz Napierala *racctp = NULL; 232097055e2SEdward Tomasz Napierala } 233097055e2SEdward Tomasz Napierala 234097055e2SEdward Tomasz Napierala void 235097055e2SEdward Tomasz Napierala racct_destroy(struct racct **racct) 236097055e2SEdward Tomasz Napierala { 237097055e2SEdward Tomasz Napierala 238097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 239097055e2SEdward Tomasz Napierala racct_destroy_locked(racct); 240097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 241097055e2SEdward Tomasz Napierala } 242097055e2SEdward Tomasz Napierala 243097055e2SEdward Tomasz Napierala /* 244097055e2SEdward Tomasz Napierala * Increase consumption of 'resource' by 'amount' for 'racct' 245097055e2SEdward Tomasz Napierala * and all its parents. Differently from other cases, 'amount' here 246097055e2SEdward Tomasz Napierala * may be less than zero. 247097055e2SEdward Tomasz Napierala */ 248097055e2SEdward Tomasz Napierala static void 249097055e2SEdward Tomasz Napierala racct_alloc_resource(struct racct *racct, int resource, 250097055e2SEdward Tomasz Napierala uint64_t amount) 251097055e2SEdward Tomasz Napierala { 252097055e2SEdward Tomasz Napierala 253097055e2SEdward Tomasz Napierala mtx_assert(&racct_lock, MA_OWNED); 254097055e2SEdward Tomasz Napierala KASSERT(racct != NULL, ("NULL racct")); 255097055e2SEdward Tomasz Napierala 256097055e2SEdward Tomasz Napierala racct->r_resources[resource] += amount; 257097055e2SEdward Tomasz Napierala if (racct->r_resources[resource] < 0) { 2584fe84775SEdward Tomasz Napierala KASSERT(RACCT_IS_SLOPPY(resource), 259097055e2SEdward Tomasz Napierala ("racct_alloc_resource: usage < 0")); 260097055e2SEdward Tomasz Napierala racct->r_resources[resource] = 0; 261097055e2SEdward Tomasz Napierala } 262097055e2SEdward Tomasz Napierala } 263097055e2SEdward Tomasz Napierala 264097055e2SEdward Tomasz Napierala /* 265097055e2SEdward Tomasz Napierala * Increase allocation of 'resource' by 'amount' for process 'p'. 266097055e2SEdward Tomasz Napierala * Return 0 if it's below limits, or errno, if it's not. 267097055e2SEdward Tomasz Napierala */ 268097055e2SEdward Tomasz Napierala int 269097055e2SEdward Tomasz Napierala racct_add(struct proc *p, int resource, uint64_t amount) 270097055e2SEdward Tomasz Napierala { 271097055e2SEdward Tomasz Napierala #ifdef RCTL 272097055e2SEdward Tomasz Napierala int error; 273097055e2SEdward Tomasz Napierala #endif 274097055e2SEdward Tomasz Napierala 275097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 276097055e2SEdward Tomasz Napierala return (0); 277097055e2SEdward Tomasz Napierala 278097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, add, p, resource, amount, 0, 0); 279097055e2SEdward Tomasz Napierala 280097055e2SEdward Tomasz Napierala /* 281097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 282097055e2SEdward Tomasz Napierala */ 283097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 284097055e2SEdward Tomasz Napierala 285097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 286097055e2SEdward Tomasz Napierala #ifdef RCTL 287097055e2SEdward Tomasz Napierala error = rctl_enforce(p, resource, amount); 2884fe84775SEdward Tomasz Napierala if (error && RACCT_IS_DENIABLE(resource)) { 289097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, add_failure, p, resource, 290097055e2SEdward Tomasz Napierala amount, 0, 0); 291097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 292097055e2SEdward Tomasz Napierala return (error); 293097055e2SEdward Tomasz Napierala } 294097055e2SEdward Tomasz Napierala #endif 295097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, amount); 296097055e2SEdward Tomasz Napierala racct_add_cred_locked(p->p_ucred, resource, amount); 297097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 298097055e2SEdward Tomasz Napierala 299097055e2SEdward Tomasz Napierala return (0); 300097055e2SEdward Tomasz Napierala } 301097055e2SEdward Tomasz Napierala 302097055e2SEdward Tomasz Napierala static void 303097055e2SEdward Tomasz Napierala racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount) 304097055e2SEdward Tomasz Napierala { 305097055e2SEdward Tomasz Napierala struct prison *pr; 306097055e2SEdward Tomasz Napierala 307097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, add_cred, cred, resource, amount, 308097055e2SEdward Tomasz Napierala 0, 0); 309097055e2SEdward Tomasz Napierala 310097055e2SEdward Tomasz Napierala racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, amount); 311097055e2SEdward Tomasz Napierala for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) 312a7ad07bfSEdward Tomasz Napierala racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource, 313a7ad07bfSEdward Tomasz Napierala amount); 314097055e2SEdward Tomasz Napierala racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, amount); 315097055e2SEdward Tomasz Napierala } 316097055e2SEdward Tomasz Napierala 317097055e2SEdward Tomasz Napierala /* 318097055e2SEdward Tomasz Napierala * Increase allocation of 'resource' by 'amount' for credential 'cred'. 319097055e2SEdward Tomasz Napierala * Doesn't check for limits and never fails. 320097055e2SEdward Tomasz Napierala * 321097055e2SEdward Tomasz Napierala * XXX: Shouldn't this ever return an error? 322097055e2SEdward Tomasz Napierala */ 323097055e2SEdward Tomasz Napierala void 324097055e2SEdward Tomasz Napierala racct_add_cred(struct ucred *cred, int resource, uint64_t amount) 325097055e2SEdward Tomasz Napierala { 326097055e2SEdward Tomasz Napierala 327097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 328097055e2SEdward Tomasz Napierala racct_add_cred_locked(cred, resource, amount); 329097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 330097055e2SEdward Tomasz Napierala } 331097055e2SEdward Tomasz Napierala 332097055e2SEdward Tomasz Napierala /* 333097055e2SEdward Tomasz Napierala * Increase allocation of 'resource' by 'amount' for process 'p'. 334097055e2SEdward Tomasz Napierala * Doesn't check for limits and never fails. 335097055e2SEdward Tomasz Napierala */ 336097055e2SEdward Tomasz Napierala void 337097055e2SEdward Tomasz Napierala racct_add_force(struct proc *p, int resource, uint64_t amount) 338097055e2SEdward Tomasz Napierala { 339097055e2SEdward Tomasz Napierala 340097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 341097055e2SEdward Tomasz Napierala return; 342097055e2SEdward Tomasz Napierala 343097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, add_force, p, resource, amount, 0, 0); 344097055e2SEdward Tomasz Napierala 345097055e2SEdward Tomasz Napierala /* 346097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 347097055e2SEdward Tomasz Napierala */ 348097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 349097055e2SEdward Tomasz Napierala 350097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 351097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, amount); 352097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 353097055e2SEdward Tomasz Napierala racct_add_cred(p->p_ucred, resource, amount); 354097055e2SEdward Tomasz Napierala } 355097055e2SEdward Tomasz Napierala 356097055e2SEdward Tomasz Napierala static int 357097055e2SEdward Tomasz Napierala racct_set_locked(struct proc *p, int resource, uint64_t amount) 358097055e2SEdward Tomasz Napierala { 359097055e2SEdward Tomasz Napierala int64_t diff; 360097055e2SEdward Tomasz Napierala #ifdef RCTL 361097055e2SEdward Tomasz Napierala int error; 362097055e2SEdward Tomasz Napierala #endif 363097055e2SEdward Tomasz Napierala 364097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 365097055e2SEdward Tomasz Napierala return (0); 366097055e2SEdward Tomasz Napierala 367097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0); 368097055e2SEdward Tomasz Napierala 369097055e2SEdward Tomasz Napierala /* 370097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 371097055e2SEdward Tomasz Napierala */ 372097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 373097055e2SEdward Tomasz Napierala 374097055e2SEdward Tomasz Napierala diff = amount - p->p_racct->r_resources[resource]; 375097055e2SEdward Tomasz Napierala #ifdef notyet 3764fe84775SEdward Tomasz Napierala KASSERT(diff >= 0 || RACCT_IS_RECLAIMABLE(resource), 377097055e2SEdward Tomasz Napierala ("racct_set: usage of non-reclaimable resource %d dropping", 378097055e2SEdward Tomasz Napierala resource)); 379097055e2SEdward Tomasz Napierala #endif 380097055e2SEdward Tomasz Napierala #ifdef RCTL 381097055e2SEdward Tomasz Napierala if (diff > 0) { 382097055e2SEdward Tomasz Napierala error = rctl_enforce(p, resource, diff); 3834fe84775SEdward Tomasz Napierala if (error && RACCT_IS_DENIABLE(resource)) { 384097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, set_failure, p, 385097055e2SEdward Tomasz Napierala resource, amount, 0, 0); 386097055e2SEdward Tomasz Napierala return (error); 387097055e2SEdward Tomasz Napierala } 388097055e2SEdward Tomasz Napierala } 389097055e2SEdward Tomasz Napierala #endif 390097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, diff); 391097055e2SEdward Tomasz Napierala if (diff > 0) 392097055e2SEdward Tomasz Napierala racct_add_cred_locked(p->p_ucred, resource, diff); 393097055e2SEdward Tomasz Napierala else if (diff < 0) 394097055e2SEdward Tomasz Napierala racct_sub_cred_locked(p->p_ucred, resource, -diff); 395097055e2SEdward Tomasz Napierala 396097055e2SEdward Tomasz Napierala return (0); 397097055e2SEdward Tomasz Napierala } 398097055e2SEdward Tomasz Napierala 399097055e2SEdward Tomasz Napierala /* 400097055e2SEdward Tomasz Napierala * Set allocation of 'resource' to 'amount' for process 'p'. 401097055e2SEdward Tomasz Napierala * Return 0 if it's below limits, or errno, if it's not. 402097055e2SEdward Tomasz Napierala * 403097055e2SEdward Tomasz Napierala * Note that decreasing the allocation always returns 0, 404097055e2SEdward Tomasz Napierala * even if it's above the limit. 405097055e2SEdward Tomasz Napierala */ 406097055e2SEdward Tomasz Napierala int 407097055e2SEdward Tomasz Napierala racct_set(struct proc *p, int resource, uint64_t amount) 408097055e2SEdward Tomasz Napierala { 409097055e2SEdward Tomasz Napierala int error; 410097055e2SEdward Tomasz Napierala 411097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 412097055e2SEdward Tomasz Napierala error = racct_set_locked(p, resource, amount); 413097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 414097055e2SEdward Tomasz Napierala return (error); 415097055e2SEdward Tomasz Napierala } 416097055e2SEdward Tomasz Napierala 417097055e2SEdward Tomasz Napierala void 418097055e2SEdward Tomasz Napierala racct_set_force(struct proc *p, int resource, uint64_t amount) 419097055e2SEdward Tomasz Napierala { 420097055e2SEdward Tomasz Napierala int64_t diff; 421097055e2SEdward Tomasz Napierala 422097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 423097055e2SEdward Tomasz Napierala return; 424097055e2SEdward Tomasz Napierala 425097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0); 426097055e2SEdward Tomasz Napierala 427097055e2SEdward Tomasz Napierala /* 428097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 429097055e2SEdward Tomasz Napierala */ 430097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 431097055e2SEdward Tomasz Napierala 432097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 433097055e2SEdward Tomasz Napierala diff = amount - p->p_racct->r_resources[resource]; 434097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, diff); 435097055e2SEdward Tomasz Napierala if (diff > 0) 436097055e2SEdward Tomasz Napierala racct_add_cred_locked(p->p_ucred, resource, diff); 437097055e2SEdward Tomasz Napierala else if (diff < 0) 438097055e2SEdward Tomasz Napierala racct_sub_cred_locked(p->p_ucred, resource, -diff); 439097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 440097055e2SEdward Tomasz Napierala } 441097055e2SEdward Tomasz Napierala 442097055e2SEdward Tomasz Napierala /* 443097055e2SEdward Tomasz Napierala * Returns amount of 'resource' the process 'p' can keep allocated. 444097055e2SEdward Tomasz Napierala * Allocating more than that would be denied, unless the resource 445097055e2SEdward Tomasz Napierala * is marked undeniable. Amount of already allocated resource does 446097055e2SEdward Tomasz Napierala * not matter. 447097055e2SEdward Tomasz Napierala */ 448097055e2SEdward Tomasz Napierala uint64_t 449097055e2SEdward Tomasz Napierala racct_get_limit(struct proc *p, int resource) 450097055e2SEdward Tomasz Napierala { 451097055e2SEdward Tomasz Napierala 452097055e2SEdward Tomasz Napierala #ifdef RCTL 453097055e2SEdward Tomasz Napierala return (rctl_get_limit(p, resource)); 454097055e2SEdward Tomasz Napierala #else 455097055e2SEdward Tomasz Napierala return (UINT64_MAX); 456097055e2SEdward Tomasz Napierala #endif 457097055e2SEdward Tomasz Napierala } 458097055e2SEdward Tomasz Napierala 459097055e2SEdward Tomasz Napierala /* 460097055e2SEdward Tomasz Napierala * Returns amount of 'resource' the process 'p' can keep allocated. 461097055e2SEdward Tomasz Napierala * Allocating more than that would be denied, unless the resource 462097055e2SEdward Tomasz Napierala * is marked undeniable. Amount of already allocated resource does 463097055e2SEdward Tomasz Napierala * matter. 464097055e2SEdward Tomasz Napierala */ 465097055e2SEdward Tomasz Napierala uint64_t 466097055e2SEdward Tomasz Napierala racct_get_available(struct proc *p, int resource) 467097055e2SEdward Tomasz Napierala { 468097055e2SEdward Tomasz Napierala 469097055e2SEdward Tomasz Napierala #ifdef RCTL 470097055e2SEdward Tomasz Napierala return (rctl_get_available(p, resource)); 471097055e2SEdward Tomasz Napierala #else 472097055e2SEdward Tomasz Napierala return (UINT64_MAX); 473097055e2SEdward Tomasz Napierala #endif 474097055e2SEdward Tomasz Napierala } 475097055e2SEdward Tomasz Napierala 476097055e2SEdward Tomasz Napierala /* 477097055e2SEdward Tomasz Napierala * Decrease allocation of 'resource' by 'amount' for process 'p'. 478097055e2SEdward Tomasz Napierala */ 479097055e2SEdward Tomasz Napierala void 480097055e2SEdward Tomasz Napierala racct_sub(struct proc *p, int resource, uint64_t amount) 481097055e2SEdward Tomasz Napierala { 482097055e2SEdward Tomasz Napierala 483097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 484097055e2SEdward Tomasz Napierala return; 485097055e2SEdward Tomasz Napierala 486097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, sub, p, resource, amount, 0, 0); 487097055e2SEdward Tomasz Napierala 488097055e2SEdward Tomasz Napierala /* 489097055e2SEdward Tomasz Napierala * We need proc lock to dereference p->p_ucred. 490097055e2SEdward Tomasz Napierala */ 491097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_OWNED); 4924fe84775SEdward Tomasz Napierala KASSERT(RACCT_IS_RECLAIMABLE(resource), 493097055e2SEdward Tomasz Napierala ("racct_sub: called for non-reclaimable resource %d", resource)); 494097055e2SEdward Tomasz Napierala 495097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 496097055e2SEdward Tomasz Napierala KASSERT(amount <= p->p_racct->r_resources[resource], 497097055e2SEdward Tomasz Napierala ("racct_sub: freeing %ju of resource %d, which is more " 498097055e2SEdward Tomasz Napierala "than allocated %jd for %s (pid %d)", amount, resource, 499097055e2SEdward Tomasz Napierala (intmax_t)p->p_racct->r_resources[resource], p->p_comm, p->p_pid)); 500097055e2SEdward Tomasz Napierala 501097055e2SEdward Tomasz Napierala racct_alloc_resource(p->p_racct, resource, -amount); 502097055e2SEdward Tomasz Napierala racct_sub_cred_locked(p->p_ucred, resource, amount); 503097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 504097055e2SEdward Tomasz Napierala } 505097055e2SEdward Tomasz Napierala 506097055e2SEdward Tomasz Napierala static void 507097055e2SEdward Tomasz Napierala racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount) 508097055e2SEdward Tomasz Napierala { 509097055e2SEdward Tomasz Napierala struct prison *pr; 510097055e2SEdward Tomasz Napierala 511097055e2SEdward Tomasz Napierala SDT_PROBE(racct, kernel, rusage, sub_cred, cred, resource, amount, 512097055e2SEdward Tomasz Napierala 0, 0); 513097055e2SEdward Tomasz Napierala 514097055e2SEdward Tomasz Napierala #ifdef notyet 5154fe84775SEdward Tomasz Napierala KASSERT(RACCT_IS_RECLAIMABLE(resource), 516097055e2SEdward Tomasz Napierala ("racct_sub_cred: called for non-reclaimable resource %d", 517097055e2SEdward Tomasz Napierala resource)); 518097055e2SEdward Tomasz Napierala #endif 519097055e2SEdward Tomasz Napierala 520097055e2SEdward Tomasz Napierala racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, -amount); 521097055e2SEdward Tomasz Napierala for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) 522a7ad07bfSEdward Tomasz Napierala racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource, 523a7ad07bfSEdward Tomasz Napierala -amount); 524097055e2SEdward Tomasz Napierala racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, -amount); 525097055e2SEdward Tomasz Napierala } 526097055e2SEdward Tomasz Napierala 527097055e2SEdward Tomasz Napierala /* 528097055e2SEdward Tomasz Napierala * Decrease allocation of 'resource' by 'amount' for credential 'cred'. 529097055e2SEdward Tomasz Napierala */ 530097055e2SEdward Tomasz Napierala void 531097055e2SEdward Tomasz Napierala racct_sub_cred(struct ucred *cred, int resource, uint64_t amount) 532097055e2SEdward Tomasz Napierala { 533097055e2SEdward Tomasz Napierala 534097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 535097055e2SEdward Tomasz Napierala racct_sub_cred_locked(cred, resource, amount); 536097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 537097055e2SEdward Tomasz Napierala } 538097055e2SEdward Tomasz Napierala 539097055e2SEdward Tomasz Napierala /* 540097055e2SEdward Tomasz Napierala * Inherit resource usage information from the parent process. 541097055e2SEdward Tomasz Napierala */ 542097055e2SEdward Tomasz Napierala int 543097055e2SEdward Tomasz Napierala racct_proc_fork(struct proc *parent, struct proc *child) 544097055e2SEdward Tomasz Napierala { 545097055e2SEdward Tomasz Napierala int i, error = 0; 546097055e2SEdward Tomasz Napierala 547097055e2SEdward Tomasz Napierala /* 548097055e2SEdward Tomasz Napierala * Create racct for the child process. 549097055e2SEdward Tomasz Napierala */ 550097055e2SEdward Tomasz Napierala racct_create(&child->p_racct); 551097055e2SEdward Tomasz Napierala 552097055e2SEdward Tomasz Napierala /* 553097055e2SEdward Tomasz Napierala * No resource accounting for kernel processes. 554097055e2SEdward Tomasz Napierala */ 555097055e2SEdward Tomasz Napierala if (child->p_flag & P_SYSTEM) 556097055e2SEdward Tomasz Napierala return (0); 557097055e2SEdward Tomasz Napierala 558097055e2SEdward Tomasz Napierala PROC_LOCK(parent); 559097055e2SEdward Tomasz Napierala PROC_LOCK(child); 560097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 561097055e2SEdward Tomasz Napierala 562097055e2SEdward Tomasz Napierala /* 563097055e2SEdward Tomasz Napierala * Inherit resource usage. 564097055e2SEdward Tomasz Napierala */ 565097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 566097055e2SEdward Tomasz Napierala if (parent->p_racct->r_resources[i] == 0 || 5674fe84775SEdward Tomasz Napierala !RACCT_IS_INHERITABLE(i)) 568097055e2SEdward Tomasz Napierala continue; 569097055e2SEdward Tomasz Napierala 570097055e2SEdward Tomasz Napierala error = racct_set_locked(child, i, 571097055e2SEdward Tomasz Napierala parent->p_racct->r_resources[i]); 572097055e2SEdward Tomasz Napierala if (error != 0) { 573097055e2SEdward Tomasz Napierala /* 574097055e2SEdward Tomasz Napierala * XXX: The only purpose of these two lines is 575097055e2SEdward Tomasz Napierala * to prevent from tripping checks in racct_destroy(). 576097055e2SEdward Tomasz Napierala */ 577097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) 578097055e2SEdward Tomasz Napierala racct_set_locked(child, i, 0); 579097055e2SEdward Tomasz Napierala goto out; 580097055e2SEdward Tomasz Napierala } 581097055e2SEdward Tomasz Napierala } 582097055e2SEdward Tomasz Napierala 583097055e2SEdward Tomasz Napierala #ifdef RCTL 584097055e2SEdward Tomasz Napierala error = rctl_proc_fork(parent, child); 585097055e2SEdward Tomasz Napierala if (error != 0) { 586097055e2SEdward Tomasz Napierala /* 587097055e2SEdward Tomasz Napierala * XXX: The only purpose of these two lines is to prevent from 588097055e2SEdward Tomasz Napierala * tripping checks in racct_destroy(). 589097055e2SEdward Tomasz Napierala */ 590097055e2SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) 591097055e2SEdward Tomasz Napierala racct_set_locked(child, i, 0); 592097055e2SEdward Tomasz Napierala } 593097055e2SEdward Tomasz Napierala #endif 594097055e2SEdward Tomasz Napierala 595097055e2SEdward Tomasz Napierala out: 596097055e2SEdward Tomasz Napierala if (error != 0) 597097055e2SEdward Tomasz Napierala racct_destroy_locked(&child->p_racct); 598097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 599097055e2SEdward Tomasz Napierala PROC_UNLOCK(child); 600097055e2SEdward Tomasz Napierala PROC_UNLOCK(parent); 601097055e2SEdward Tomasz Napierala 602097055e2SEdward Tomasz Napierala return (error); 603097055e2SEdward Tomasz Napierala } 604097055e2SEdward Tomasz Napierala 605097055e2SEdward Tomasz Napierala void 606097055e2SEdward Tomasz Napierala racct_proc_exit(struct proc *p) 607097055e2SEdward Tomasz Napierala { 608*2419d7f9SEdward Tomasz Napierala int i; 609097055e2SEdward Tomasz Napierala uint64_t runtime; 610097055e2SEdward Tomasz Napierala 611097055e2SEdward Tomasz Napierala PROC_LOCK(p); 612097055e2SEdward Tomasz Napierala /* 613097055e2SEdward Tomasz Napierala * We don't need to calculate rux, proc_reap() has already done this. 614097055e2SEdward Tomasz Napierala */ 615097055e2SEdward Tomasz Napierala runtime = cputick2usec(p->p_rux.rux_runtime); 616097055e2SEdward Tomasz Napierala #ifdef notyet 617097055e2SEdward Tomasz Napierala KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime")); 618097055e2SEdward Tomasz Napierala #else 619097055e2SEdward Tomasz Napierala if (runtime < p->p_prev_runtime) 620097055e2SEdward Tomasz Napierala runtime = p->p_prev_runtime; 621097055e2SEdward Tomasz Napierala #endif 622*2419d7f9SEdward Tomasz Napierala mtx_lock(&racct_lock); 623*2419d7f9SEdward Tomasz Napierala racct_set_locked(p, RACCT_CPU, runtime); 624097055e2SEdward Tomasz Napierala 625*2419d7f9SEdward Tomasz Napierala for (i = 0; i <= RACCT_MAX; i++) { 626*2419d7f9SEdward Tomasz Napierala if (p->p_racct->r_resources[i] == 0) 627*2419d7f9SEdward Tomasz Napierala continue; 628*2419d7f9SEdward Tomasz Napierala if (!RACCT_IS_RECLAIMABLE(i)) 629*2419d7f9SEdward Tomasz Napierala continue; 630*2419d7f9SEdward Tomasz Napierala racct_set_locked(p, i, 0); 631*2419d7f9SEdward Tomasz Napierala } 632*2419d7f9SEdward Tomasz Napierala 633*2419d7f9SEdward Tomasz Napierala mtx_unlock(&racct_lock); 634097055e2SEdward Tomasz Napierala PROC_UNLOCK(p); 635097055e2SEdward Tomasz Napierala 636097055e2SEdward Tomasz Napierala #ifdef RCTL 637097055e2SEdward Tomasz Napierala rctl_racct_release(p->p_racct); 638097055e2SEdward Tomasz Napierala #endif 639097055e2SEdward Tomasz Napierala racct_destroy(&p->p_racct); 640097055e2SEdward Tomasz Napierala } 641097055e2SEdward Tomasz Napierala 642097055e2SEdward Tomasz Napierala /* 643097055e2SEdward Tomasz Napierala * Called after credentials change, to move resource utilisation 644097055e2SEdward Tomasz Napierala * between raccts. 645097055e2SEdward Tomasz Napierala */ 646097055e2SEdward Tomasz Napierala void 647097055e2SEdward Tomasz Napierala racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred, 648097055e2SEdward Tomasz Napierala struct ucred *newcred) 649097055e2SEdward Tomasz Napierala { 650097055e2SEdward Tomasz Napierala struct uidinfo *olduip, *newuip; 651097055e2SEdward Tomasz Napierala struct loginclass *oldlc, *newlc; 652097055e2SEdward Tomasz Napierala struct prison *oldpr, *newpr, *pr; 653097055e2SEdward Tomasz Napierala 654097055e2SEdward Tomasz Napierala PROC_LOCK_ASSERT(p, MA_NOTOWNED); 655097055e2SEdward Tomasz Napierala 656097055e2SEdward Tomasz Napierala newuip = newcred->cr_ruidinfo; 657097055e2SEdward Tomasz Napierala olduip = oldcred->cr_ruidinfo; 658097055e2SEdward Tomasz Napierala newlc = newcred->cr_loginclass; 659097055e2SEdward Tomasz Napierala oldlc = oldcred->cr_loginclass; 660097055e2SEdward Tomasz Napierala newpr = newcred->cr_prison; 661097055e2SEdward Tomasz Napierala oldpr = oldcred->cr_prison; 662097055e2SEdward Tomasz Napierala 663097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 664097055e2SEdward Tomasz Napierala if (newuip != olduip) { 665097055e2SEdward Tomasz Napierala racct_sub_racct(olduip->ui_racct, p->p_racct); 666097055e2SEdward Tomasz Napierala racct_add_racct(newuip->ui_racct, p->p_racct); 667097055e2SEdward Tomasz Napierala } 668097055e2SEdward Tomasz Napierala if (newlc != oldlc) { 669097055e2SEdward Tomasz Napierala racct_sub_racct(oldlc->lc_racct, p->p_racct); 670097055e2SEdward Tomasz Napierala racct_add_racct(newlc->lc_racct, p->p_racct); 671097055e2SEdward Tomasz Napierala } 672097055e2SEdward Tomasz Napierala if (newpr != oldpr) { 673097055e2SEdward Tomasz Napierala for (pr = oldpr; pr != NULL; pr = pr->pr_parent) 674a7ad07bfSEdward Tomasz Napierala racct_sub_racct(pr->pr_prison_racct->prr_racct, 675a7ad07bfSEdward Tomasz Napierala p->p_racct); 676097055e2SEdward Tomasz Napierala for (pr = newpr; pr != NULL; pr = pr->pr_parent) 677a7ad07bfSEdward Tomasz Napierala racct_add_racct(pr->pr_prison_racct->prr_racct, 678a7ad07bfSEdward Tomasz Napierala p->p_racct); 679097055e2SEdward Tomasz Napierala } 680097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 681097055e2SEdward Tomasz Napierala 682097055e2SEdward Tomasz Napierala #ifdef RCTL 683097055e2SEdward Tomasz Napierala rctl_proc_ucred_changed(p, newcred); 684097055e2SEdward Tomasz Napierala #endif 685097055e2SEdward Tomasz Napierala } 686097055e2SEdward Tomasz Napierala 687097055e2SEdward Tomasz Napierala static void 688097055e2SEdward Tomasz Napierala racctd(void) 689097055e2SEdward Tomasz Napierala { 690097055e2SEdward Tomasz Napierala struct thread *td; 691097055e2SEdward Tomasz Napierala struct proc *p; 692097055e2SEdward Tomasz Napierala struct timeval wallclock; 693097055e2SEdward Tomasz Napierala uint64_t runtime; 694097055e2SEdward Tomasz Napierala 695097055e2SEdward Tomasz Napierala for (;;) { 696097055e2SEdward Tomasz Napierala sx_slock(&allproc_lock); 697097055e2SEdward Tomasz Napierala 698097055e2SEdward Tomasz Napierala FOREACH_PROC_IN_SYSTEM(p) { 699097055e2SEdward Tomasz Napierala if (p->p_state != PRS_NORMAL) 700097055e2SEdward Tomasz Napierala continue; 701097055e2SEdward Tomasz Napierala if (p->p_flag & P_SYSTEM) 702097055e2SEdward Tomasz Napierala continue; 703097055e2SEdward Tomasz Napierala 704097055e2SEdward Tomasz Napierala microuptime(&wallclock); 705097055e2SEdward Tomasz Napierala timevalsub(&wallclock, &p->p_stats->p_start); 706097055e2SEdward Tomasz Napierala PROC_LOCK(p); 707097055e2SEdward Tomasz Napierala PROC_SLOCK(p); 708097055e2SEdward Tomasz Napierala FOREACH_THREAD_IN_PROC(p, td) { 709097055e2SEdward Tomasz Napierala ruxagg(p, td); 710097055e2SEdward Tomasz Napierala thread_lock(td); 711097055e2SEdward Tomasz Napierala thread_unlock(td); 712097055e2SEdward Tomasz Napierala } 713097055e2SEdward Tomasz Napierala runtime = cputick2usec(p->p_rux.rux_runtime); 714097055e2SEdward Tomasz Napierala PROC_SUNLOCK(p); 715097055e2SEdward Tomasz Napierala #ifdef notyet 716097055e2SEdward Tomasz Napierala KASSERT(runtime >= p->p_prev_runtime, 717097055e2SEdward Tomasz Napierala ("runtime < p_prev_runtime")); 718097055e2SEdward Tomasz Napierala #else 719097055e2SEdward Tomasz Napierala if (runtime < p->p_prev_runtime) 720097055e2SEdward Tomasz Napierala runtime = p->p_prev_runtime; 721097055e2SEdward Tomasz Napierala #endif 722097055e2SEdward Tomasz Napierala p->p_prev_runtime = runtime; 723097055e2SEdward Tomasz Napierala mtx_lock(&racct_lock); 724097055e2SEdward Tomasz Napierala racct_set_locked(p, RACCT_CPU, runtime); 725097055e2SEdward Tomasz Napierala racct_set_locked(p, RACCT_WALLCLOCK, 726097055e2SEdward Tomasz Napierala wallclock.tv_sec * 1000000 + wallclock.tv_usec); 727097055e2SEdward Tomasz Napierala mtx_unlock(&racct_lock); 728097055e2SEdward Tomasz Napierala PROC_UNLOCK(p); 729097055e2SEdward Tomasz Napierala } 730097055e2SEdward Tomasz Napierala sx_sunlock(&allproc_lock); 731097055e2SEdward Tomasz Napierala pause("-", hz); 732097055e2SEdward Tomasz Napierala } 733097055e2SEdward Tomasz Napierala } 734097055e2SEdward Tomasz Napierala 735097055e2SEdward Tomasz Napierala static struct kproc_desc racctd_kp = { 736097055e2SEdward Tomasz Napierala "racctd", 737097055e2SEdward Tomasz Napierala racctd, 738097055e2SEdward Tomasz Napierala NULL 739097055e2SEdward Tomasz Napierala }; 740097055e2SEdward Tomasz Napierala SYSINIT(racctd, SI_SUB_RACCTD, SI_ORDER_FIRST, kproc_start, &racctd_kp); 741097055e2SEdward Tomasz Napierala 742097055e2SEdward Tomasz Napierala static void 743097055e2SEdward Tomasz Napierala racct_init(void) 744097055e2SEdward Tomasz Napierala { 745097055e2SEdward Tomasz Napierala 746097055e2SEdward Tomasz Napierala racct_zone = uma_zcreate("racct", sizeof(struct racct), 747097055e2SEdward Tomasz Napierala NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 748097055e2SEdward Tomasz Napierala /* 749097055e2SEdward Tomasz Napierala * XXX: Move this somewhere. 750097055e2SEdward Tomasz Napierala */ 751a7ad07bfSEdward Tomasz Napierala prison0.pr_prison_racct = prison_racct_find("0"); 752097055e2SEdward Tomasz Napierala } 753097055e2SEdward Tomasz Napierala SYSINIT(racct, SI_SUB_RACCT, SI_ORDER_FIRST, racct_init, NULL); 754097055e2SEdward Tomasz Napierala 755097055e2SEdward Tomasz Napierala #else /* !RACCT */ 756097055e2SEdward Tomasz Napierala 757097055e2SEdward Tomasz Napierala int 758097055e2SEdward Tomasz Napierala racct_add(struct proc *p, int resource, uint64_t amount) 759097055e2SEdward Tomasz Napierala { 760097055e2SEdward Tomasz Napierala 761097055e2SEdward Tomasz Napierala return (0); 762097055e2SEdward Tomasz Napierala } 763097055e2SEdward Tomasz Napierala 764097055e2SEdward Tomasz Napierala void 765097055e2SEdward Tomasz Napierala racct_add_cred(struct ucred *cred, int resource, uint64_t amount) 766097055e2SEdward Tomasz Napierala { 767097055e2SEdward Tomasz Napierala } 768097055e2SEdward Tomasz Napierala 769097055e2SEdward Tomasz Napierala void 770097055e2SEdward Tomasz Napierala racct_add_force(struct proc *p, int resource, uint64_t amount) 771097055e2SEdward Tomasz Napierala { 772097055e2SEdward Tomasz Napierala 773097055e2SEdward Tomasz Napierala return; 774097055e2SEdward Tomasz Napierala } 775097055e2SEdward Tomasz Napierala 776097055e2SEdward Tomasz Napierala int 777097055e2SEdward Tomasz Napierala racct_set(struct proc *p, int resource, uint64_t amount) 778097055e2SEdward Tomasz Napierala { 779097055e2SEdward Tomasz Napierala 780097055e2SEdward Tomasz Napierala return (0); 781097055e2SEdward Tomasz Napierala } 782097055e2SEdward Tomasz Napierala 783097055e2SEdward Tomasz Napierala void 784c98fe0a5SEdward Tomasz Napierala racct_set_force(struct proc *p, int resource, uint64_t amount) 785c98fe0a5SEdward Tomasz Napierala { 786c98fe0a5SEdward Tomasz Napierala } 787c98fe0a5SEdward Tomasz Napierala 788c98fe0a5SEdward Tomasz Napierala void 789097055e2SEdward Tomasz Napierala racct_sub(struct proc *p, int resource, uint64_t amount) 790097055e2SEdward Tomasz Napierala { 791097055e2SEdward Tomasz Napierala } 792097055e2SEdward Tomasz Napierala 793097055e2SEdward Tomasz Napierala void 794097055e2SEdward Tomasz Napierala racct_sub_cred(struct ucred *cred, int resource, uint64_t amount) 795097055e2SEdward Tomasz Napierala { 796097055e2SEdward Tomasz Napierala } 797097055e2SEdward Tomasz Napierala 798097055e2SEdward Tomasz Napierala uint64_t 799097055e2SEdward Tomasz Napierala racct_get_limit(struct proc *p, int resource) 800097055e2SEdward Tomasz Napierala { 801097055e2SEdward Tomasz Napierala 802097055e2SEdward Tomasz Napierala return (UINT64_MAX); 803097055e2SEdward Tomasz Napierala } 804097055e2SEdward Tomasz Napierala 805c98fe0a5SEdward Tomasz Napierala uint64_t 806c98fe0a5SEdward Tomasz Napierala racct_get_available(struct proc *p, int resource) 807c98fe0a5SEdward Tomasz Napierala { 808c98fe0a5SEdward Tomasz Napierala 809c98fe0a5SEdward Tomasz Napierala return (UINT64_MAX); 810c98fe0a5SEdward Tomasz Napierala } 811c98fe0a5SEdward Tomasz Napierala 812097055e2SEdward Tomasz Napierala void 813097055e2SEdward Tomasz Napierala racct_create(struct racct **racctp) 814097055e2SEdward Tomasz Napierala { 815097055e2SEdward Tomasz Napierala } 816097055e2SEdward Tomasz Napierala 817097055e2SEdward Tomasz Napierala void 818097055e2SEdward Tomasz Napierala racct_destroy(struct racct **racctp) 819097055e2SEdward Tomasz Napierala { 820097055e2SEdward Tomasz Napierala } 821097055e2SEdward Tomasz Napierala 822097055e2SEdward Tomasz Napierala int 823097055e2SEdward Tomasz Napierala racct_proc_fork(struct proc *parent, struct proc *child) 824097055e2SEdward Tomasz Napierala { 825097055e2SEdward Tomasz Napierala 826097055e2SEdward Tomasz Napierala return (0); 827097055e2SEdward Tomasz Napierala } 828097055e2SEdward Tomasz Napierala 829097055e2SEdward Tomasz Napierala void 830097055e2SEdward Tomasz Napierala racct_proc_exit(struct proc *p) 831097055e2SEdward Tomasz Napierala { 832097055e2SEdward Tomasz Napierala } 833097055e2SEdward Tomasz Napierala 834097055e2SEdward Tomasz Napierala #endif /* !RACCT */ 835