xref: /freebsd/sys/kern/kern_racct.c (revision 0e225211a0ce8a759c5af8575156a83755af00bf)
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