xref: /freebsd/sys/kern/kern_racct.c (revision a7ad07bff3f0501e3ea483955122f5da37519674)
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] =
106097055e2SEdward Tomasz Napierala 		RACCT_IN_THOUSANDS,
107097055e2SEdward Tomasz Napierala 	[RACCT_FSIZE] =
108097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
109097055e2SEdward Tomasz Napierala 	[RACCT_DATA] =
110097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
111097055e2SEdward Tomasz Napierala 	[RACCT_STACK] =
112097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
113097055e2SEdward Tomasz Napierala 	[RACCT_CORE] =
114097055e2SEdward Tomasz Napierala 		RACCT_DENIABLE,
115097055e2SEdward Tomasz Napierala 	[RACCT_RSS] =
116097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE,
117097055e2SEdward Tomasz Napierala 	[RACCT_MEMLOCK] =
118097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE,
119097055e2SEdward Tomasz Napierala 	[RACCT_NPROC] =
120097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE,
121097055e2SEdward Tomasz Napierala 	[RACCT_NOFILE] =
122097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
123097055e2SEdward Tomasz Napierala 	[RACCT_SBSIZE] =
124097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
125097055e2SEdward Tomasz Napierala 	[RACCT_VMEM] =
126097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
127097055e2SEdward Tomasz Napierala 	[RACCT_NPTS] =
128097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
129097055e2SEdward Tomasz Napierala 	[RACCT_SWAP] =
130097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
131097055e2SEdward Tomasz Napierala 	[RACCT_NTHR] =
132097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE,
133097055e2SEdward Tomasz Napierala 	[RACCT_MSGQQUEUED] =
134097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
135097055e2SEdward Tomasz Napierala 	[RACCT_MSGQSIZE] =
136097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
137097055e2SEdward Tomasz Napierala 	[RACCT_NMSGQ] =
138097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
139097055e2SEdward Tomasz Napierala 	[RACCT_NSEM] =
140097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
141097055e2SEdward Tomasz Napierala 	[RACCT_NSEMOP] =
142097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
143097055e2SEdward Tomasz Napierala 	[RACCT_NSHM] =
144097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
145097055e2SEdward Tomasz Napierala 	[RACCT_SHMSIZE] =
146097055e2SEdward Tomasz Napierala 		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
147097055e2SEdward Tomasz Napierala 	[RACCT_WALLCLOCK] =
148097055e2SEdward Tomasz Napierala 		RACCT_IN_THOUSANDS };
149097055e2SEdward Tomasz Napierala 
150097055e2SEdward Tomasz Napierala static void
151097055e2SEdward Tomasz Napierala racct_add_racct(struct racct *dest, const struct racct *src)
152097055e2SEdward Tomasz Napierala {
153097055e2SEdward Tomasz Napierala 	int i;
154097055e2SEdward Tomasz Napierala 
155097055e2SEdward Tomasz Napierala 	mtx_assert(&racct_lock, MA_OWNED);
156097055e2SEdward Tomasz Napierala 
157097055e2SEdward Tomasz Napierala 	/*
158097055e2SEdward Tomasz Napierala 	 * Update resource usage in dest.
159097055e2SEdward Tomasz Napierala 	 */
160097055e2SEdward Tomasz Napierala 	for (i = 0; i <= RACCT_MAX; i++) {
161097055e2SEdward Tomasz Napierala 		KASSERT(dest->r_resources[i] >= 0,
162097055e2SEdward Tomasz Napierala 		    ("racct propagation meltdown: dest < 0"));
163097055e2SEdward Tomasz Napierala 		KASSERT(src->r_resources[i] >= 0,
164097055e2SEdward Tomasz Napierala 		    ("racct propagation meltdown: src < 0"));
165097055e2SEdward Tomasz Napierala 		dest->r_resources[i] += src->r_resources[i];
166097055e2SEdward Tomasz Napierala 	}
167097055e2SEdward Tomasz Napierala }
168097055e2SEdward Tomasz Napierala 
169097055e2SEdward Tomasz Napierala static void
170097055e2SEdward Tomasz Napierala racct_sub_racct(struct racct *dest, const struct racct *src)
171097055e2SEdward Tomasz Napierala {
172097055e2SEdward Tomasz Napierala 	int i;
173097055e2SEdward Tomasz Napierala 
174097055e2SEdward Tomasz Napierala 	mtx_assert(&racct_lock, MA_OWNED);
175097055e2SEdward Tomasz Napierala 
176097055e2SEdward Tomasz Napierala 	/*
177097055e2SEdward Tomasz Napierala 	 * Update resource usage in dest.
178097055e2SEdward Tomasz Napierala 	 */
179097055e2SEdward Tomasz Napierala 	for (i = 0; i <= RACCT_MAX; i++) {
180097055e2SEdward Tomasz Napierala 		if (!racct_is_sloppy(i)) {
181097055e2SEdward Tomasz Napierala 			KASSERT(dest->r_resources[i] >= 0,
182097055e2SEdward Tomasz Napierala 			    ("racct propagation meltdown: dest < 0"));
183097055e2SEdward Tomasz Napierala 			KASSERT(src->r_resources[i] >= 0,
184097055e2SEdward Tomasz Napierala 			    ("racct propagation meltdown: src < 0"));
185097055e2SEdward Tomasz Napierala 			KASSERT(src->r_resources[i] <= dest->r_resources[i],
186097055e2SEdward Tomasz Napierala 			    ("racct propagation meltdown: src > dest"));
187097055e2SEdward Tomasz Napierala 		}
188097055e2SEdward Tomasz Napierala 		if (racct_is_reclaimable(i)) {
189097055e2SEdward Tomasz Napierala 			dest->r_resources[i] -= src->r_resources[i];
190097055e2SEdward Tomasz Napierala 			if (dest->r_resources[i] < 0) {
191097055e2SEdward Tomasz Napierala 				KASSERT(racct_is_sloppy(i),
192097055e2SEdward Tomasz Napierala 				    ("racct_sub_racct: usage < 0"));
193097055e2SEdward Tomasz Napierala 				dest->r_resources[i] = 0;
194097055e2SEdward Tomasz Napierala 			}
195097055e2SEdward Tomasz Napierala 		}
196097055e2SEdward Tomasz Napierala 	}
197097055e2SEdward Tomasz Napierala }
198097055e2SEdward Tomasz Napierala 
199097055e2SEdward Tomasz Napierala void
200097055e2SEdward Tomasz Napierala racct_create(struct racct **racctp)
201097055e2SEdward Tomasz Napierala {
202097055e2SEdward Tomasz Napierala 
203097055e2SEdward Tomasz Napierala 	SDT_PROBE(racct, kernel, racct, create, racctp, 0, 0, 0, 0);
204097055e2SEdward Tomasz Napierala 
205097055e2SEdward Tomasz Napierala 	KASSERT(*racctp == NULL, ("racct already allocated"));
206097055e2SEdward Tomasz Napierala 
207097055e2SEdward Tomasz Napierala 	*racctp = uma_zalloc(racct_zone, M_WAITOK | M_ZERO);
208097055e2SEdward Tomasz Napierala }
209097055e2SEdward Tomasz Napierala 
210097055e2SEdward Tomasz Napierala static void
211097055e2SEdward Tomasz Napierala racct_destroy_locked(struct racct **racctp)
212097055e2SEdward Tomasz Napierala {
213097055e2SEdward Tomasz Napierala 	int i;
214097055e2SEdward Tomasz Napierala 	struct racct *racct;
215097055e2SEdward Tomasz Napierala 
216097055e2SEdward Tomasz Napierala 	SDT_PROBE(racct, kernel, racct, destroy, racctp, 0, 0, 0, 0);
217097055e2SEdward Tomasz Napierala 
218097055e2SEdward Tomasz Napierala 	mtx_assert(&racct_lock, MA_OWNED);
219097055e2SEdward Tomasz Napierala 	KASSERT(racctp != NULL, ("NULL racctp"));
220097055e2SEdward Tomasz Napierala 	KASSERT(*racctp != NULL, ("NULL racct"));
221097055e2SEdward Tomasz Napierala 
222097055e2SEdward Tomasz Napierala 	racct = *racctp;
223097055e2SEdward Tomasz Napierala 
224097055e2SEdward Tomasz Napierala 	for (i = 0; i <= RACCT_MAX; i++) {
225097055e2SEdward Tomasz Napierala 		if (racct_is_sloppy(i))
226097055e2SEdward Tomasz Napierala 			continue;
227097055e2SEdward Tomasz Napierala 		if (!racct_is_reclaimable(i))
228097055e2SEdward Tomasz Napierala 			continue;
229097055e2SEdward Tomasz Napierala 		KASSERT(racct->r_resources[i] == 0,
230097055e2SEdward Tomasz Napierala 		    ("destroying non-empty racct: "
231097055e2SEdward Tomasz Napierala 		    "%ju allocated for resource %d\n",
232097055e2SEdward Tomasz Napierala 		    racct->r_resources[i], i));
233097055e2SEdward Tomasz Napierala 	}
234097055e2SEdward Tomasz Napierala 	uma_zfree(racct_zone, racct);
235097055e2SEdward Tomasz Napierala 	*racctp = NULL;
236097055e2SEdward Tomasz Napierala }
237097055e2SEdward Tomasz Napierala 
238097055e2SEdward Tomasz Napierala void
239097055e2SEdward Tomasz Napierala racct_destroy(struct racct **racct)
240097055e2SEdward Tomasz Napierala {
241097055e2SEdward Tomasz Napierala 
242097055e2SEdward Tomasz Napierala 	mtx_lock(&racct_lock);
243097055e2SEdward Tomasz Napierala 	racct_destroy_locked(racct);
244097055e2SEdward Tomasz Napierala 	mtx_unlock(&racct_lock);
245097055e2SEdward Tomasz Napierala }
246097055e2SEdward Tomasz Napierala 
247097055e2SEdward Tomasz Napierala /*
248097055e2SEdward Tomasz Napierala  * Increase consumption of 'resource' by 'amount' for 'racct'
249097055e2SEdward Tomasz Napierala  * and all its parents.  Differently from other cases, 'amount' here
250097055e2SEdward Tomasz Napierala  * may be less than zero.
251097055e2SEdward Tomasz Napierala  */
252097055e2SEdward Tomasz Napierala static void
253097055e2SEdward Tomasz Napierala racct_alloc_resource(struct racct *racct, int resource,
254097055e2SEdward Tomasz Napierala     uint64_t amount)
255097055e2SEdward Tomasz Napierala {
256097055e2SEdward Tomasz Napierala 
257097055e2SEdward Tomasz Napierala 	mtx_assert(&racct_lock, MA_OWNED);
258097055e2SEdward Tomasz Napierala 	KASSERT(racct != NULL, ("NULL racct"));
259097055e2SEdward Tomasz Napierala 
260097055e2SEdward Tomasz Napierala 	racct->r_resources[resource] += amount;
261097055e2SEdward Tomasz Napierala 	if (racct->r_resources[resource] < 0) {
262097055e2SEdward Tomasz Napierala 		KASSERT(racct_is_sloppy(resource),
263097055e2SEdward Tomasz Napierala 		    ("racct_alloc_resource: usage < 0"));
264097055e2SEdward Tomasz Napierala 		racct->r_resources[resource] = 0;
265097055e2SEdward Tomasz Napierala 	}
266097055e2SEdward Tomasz Napierala }
267097055e2SEdward Tomasz Napierala 
268097055e2SEdward Tomasz Napierala /*
269097055e2SEdward Tomasz Napierala  * Increase allocation of 'resource' by 'amount' for process 'p'.
270097055e2SEdward Tomasz Napierala  * Return 0 if it's below limits, or errno, if it's not.
271097055e2SEdward Tomasz Napierala  */
272097055e2SEdward Tomasz Napierala int
273097055e2SEdward Tomasz Napierala racct_add(struct proc *p, int resource, uint64_t amount)
274097055e2SEdward Tomasz Napierala {
275097055e2SEdward Tomasz Napierala #ifdef RCTL
276097055e2SEdward Tomasz Napierala 	int error;
277097055e2SEdward Tomasz Napierala #endif
278097055e2SEdward Tomasz Napierala 
279097055e2SEdward Tomasz Napierala 	if (p->p_flag & P_SYSTEM)
280097055e2SEdward Tomasz Napierala 		return (0);
281097055e2SEdward Tomasz Napierala 
282097055e2SEdward Tomasz Napierala 	SDT_PROBE(racct, kernel, rusage, add, p, resource, amount, 0, 0);
283097055e2SEdward Tomasz Napierala 
284097055e2SEdward Tomasz Napierala 	/*
285097055e2SEdward Tomasz Napierala 	 * We need proc lock to dereference p->p_ucred.
286097055e2SEdward Tomasz Napierala 	 */
287097055e2SEdward Tomasz Napierala 	PROC_LOCK_ASSERT(p, MA_OWNED);
288097055e2SEdward Tomasz Napierala 
289097055e2SEdward Tomasz Napierala 	mtx_lock(&racct_lock);
290097055e2SEdward Tomasz Napierala #ifdef RCTL
291097055e2SEdward Tomasz Napierala 	error = rctl_enforce(p, resource, amount);
292097055e2SEdward Tomasz Napierala 	if (error && racct_is_deniable(resource)) {
293097055e2SEdward Tomasz Napierala 		SDT_PROBE(racct, kernel, rusage, add_failure, p, resource,
294097055e2SEdward Tomasz Napierala 		    amount, 0, 0);
295097055e2SEdward Tomasz Napierala 		mtx_unlock(&racct_lock);
296097055e2SEdward Tomasz Napierala 		return (error);
297097055e2SEdward Tomasz Napierala 	}
298097055e2SEdward Tomasz Napierala #endif
299097055e2SEdward Tomasz Napierala 	racct_alloc_resource(p->p_racct, resource, amount);
300097055e2SEdward Tomasz Napierala 	racct_add_cred_locked(p->p_ucred, resource, amount);
301097055e2SEdward Tomasz Napierala 	mtx_unlock(&racct_lock);
302097055e2SEdward Tomasz Napierala 
303097055e2SEdward Tomasz Napierala 	return (0);
304097055e2SEdward Tomasz Napierala }
305097055e2SEdward Tomasz Napierala 
306097055e2SEdward Tomasz Napierala static void
307097055e2SEdward Tomasz Napierala racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount)
308097055e2SEdward Tomasz Napierala {
309097055e2SEdward Tomasz Napierala 	struct prison *pr;
310097055e2SEdward Tomasz Napierala 
311097055e2SEdward Tomasz Napierala 	SDT_PROBE(racct, kernel, rusage, add_cred, cred, resource, amount,
312097055e2SEdward Tomasz Napierala 	    0, 0);
313097055e2SEdward Tomasz Napierala 
314097055e2SEdward Tomasz Napierala 	racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, amount);
315097055e2SEdward Tomasz Napierala 	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
316*a7ad07bfSEdward Tomasz Napierala 		racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource,
317*a7ad07bfSEdward Tomasz Napierala 		    amount);
318097055e2SEdward Tomasz Napierala 	racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, amount);
319097055e2SEdward Tomasz Napierala }
320097055e2SEdward Tomasz Napierala 
321097055e2SEdward Tomasz Napierala /*
322097055e2SEdward Tomasz Napierala  * Increase allocation of 'resource' by 'amount' for credential 'cred'.
323097055e2SEdward Tomasz Napierala  * Doesn't check for limits and never fails.
324097055e2SEdward Tomasz Napierala  *
325097055e2SEdward Tomasz Napierala  * XXX: Shouldn't this ever return an error?
326097055e2SEdward Tomasz Napierala  */
327097055e2SEdward Tomasz Napierala void
328097055e2SEdward Tomasz Napierala racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
329097055e2SEdward Tomasz Napierala {
330097055e2SEdward Tomasz Napierala 
331097055e2SEdward Tomasz Napierala 	mtx_lock(&racct_lock);
332097055e2SEdward Tomasz Napierala 	racct_add_cred_locked(cred, resource, amount);
333097055e2SEdward Tomasz Napierala 	mtx_unlock(&racct_lock);
334097055e2SEdward Tomasz Napierala }
335097055e2SEdward Tomasz Napierala 
336097055e2SEdward Tomasz Napierala /*
337097055e2SEdward Tomasz Napierala  * Increase allocation of 'resource' by 'amount' for process 'p'.
338097055e2SEdward Tomasz Napierala  * Doesn't check for limits and never fails.
339097055e2SEdward Tomasz Napierala  */
340097055e2SEdward Tomasz Napierala void
341097055e2SEdward Tomasz Napierala racct_add_force(struct proc *p, int resource, uint64_t amount)
342097055e2SEdward Tomasz Napierala {
343097055e2SEdward Tomasz Napierala 
344097055e2SEdward Tomasz Napierala 	if (p->p_flag & P_SYSTEM)
345097055e2SEdward Tomasz Napierala 		return;
346097055e2SEdward Tomasz Napierala 
347097055e2SEdward Tomasz Napierala 	SDT_PROBE(racct, kernel, rusage, add_force, p, resource, amount, 0, 0);
348097055e2SEdward Tomasz Napierala 
349097055e2SEdward Tomasz Napierala 	/*
350097055e2SEdward Tomasz Napierala 	 * We need proc lock to dereference p->p_ucred.
351097055e2SEdward Tomasz Napierala 	 */
352097055e2SEdward Tomasz Napierala 	PROC_LOCK_ASSERT(p, MA_OWNED);
353097055e2SEdward Tomasz Napierala 
354097055e2SEdward Tomasz Napierala 	mtx_lock(&racct_lock);
355097055e2SEdward Tomasz Napierala 	racct_alloc_resource(p->p_racct, resource, amount);
356097055e2SEdward Tomasz Napierala 	mtx_unlock(&racct_lock);
357097055e2SEdward Tomasz Napierala 	racct_add_cred(p->p_ucred, resource, amount);
358097055e2SEdward Tomasz Napierala }
359097055e2SEdward Tomasz Napierala 
360097055e2SEdward Tomasz Napierala static int
361097055e2SEdward Tomasz Napierala racct_set_locked(struct proc *p, int resource, uint64_t amount)
362097055e2SEdward Tomasz Napierala {
363097055e2SEdward Tomasz Napierala 	int64_t diff;
364097055e2SEdward Tomasz Napierala #ifdef RCTL
365097055e2SEdward Tomasz Napierala 	int error;
366097055e2SEdward Tomasz Napierala #endif
367097055e2SEdward Tomasz Napierala 
368097055e2SEdward Tomasz Napierala 	if (p->p_flag & P_SYSTEM)
369097055e2SEdward Tomasz Napierala 		return (0);
370097055e2SEdward Tomasz Napierala 
371097055e2SEdward Tomasz Napierala 	SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
372097055e2SEdward Tomasz Napierala 
373097055e2SEdward Tomasz Napierala 	/*
374097055e2SEdward Tomasz Napierala 	 * We need proc lock to dereference p->p_ucred.
375097055e2SEdward Tomasz Napierala 	 */
376097055e2SEdward Tomasz Napierala 	PROC_LOCK_ASSERT(p, MA_OWNED);
377097055e2SEdward Tomasz Napierala 
378097055e2SEdward Tomasz Napierala 	diff = amount - p->p_racct->r_resources[resource];
379097055e2SEdward Tomasz Napierala #ifdef notyet
380097055e2SEdward Tomasz Napierala 	KASSERT(diff >= 0 || racct_is_reclaimable(resource),
381097055e2SEdward Tomasz Napierala 	    ("racct_set: usage of non-reclaimable resource %d dropping",
382097055e2SEdward Tomasz Napierala 	     resource));
383097055e2SEdward Tomasz Napierala #endif
384097055e2SEdward Tomasz Napierala #ifdef RCTL
385097055e2SEdward Tomasz Napierala 	if (diff > 0) {
386097055e2SEdward Tomasz Napierala 		error = rctl_enforce(p, resource, diff);
387097055e2SEdward Tomasz Napierala 		if (error && racct_is_deniable(resource)) {
388097055e2SEdward Tomasz Napierala 			SDT_PROBE(racct, kernel, rusage, set_failure, p,
389097055e2SEdward Tomasz Napierala 			    resource, amount, 0, 0);
390097055e2SEdward Tomasz Napierala 			return (error);
391097055e2SEdward Tomasz Napierala 		}
392097055e2SEdward Tomasz Napierala 	}
393097055e2SEdward Tomasz Napierala #endif
394097055e2SEdward Tomasz Napierala 	racct_alloc_resource(p->p_racct, resource, diff);
395097055e2SEdward Tomasz Napierala 	if (diff > 0)
396097055e2SEdward Tomasz Napierala 		racct_add_cred_locked(p->p_ucred, resource, diff);
397097055e2SEdward Tomasz Napierala 	else if (diff < 0)
398097055e2SEdward Tomasz Napierala 		racct_sub_cred_locked(p->p_ucred, resource, -diff);
399097055e2SEdward Tomasz Napierala 
400097055e2SEdward Tomasz Napierala 	return (0);
401097055e2SEdward Tomasz Napierala }
402097055e2SEdward Tomasz Napierala 
403097055e2SEdward Tomasz Napierala /*
404097055e2SEdward Tomasz Napierala  * Set allocation of 'resource' to 'amount' for process 'p'.
405097055e2SEdward Tomasz Napierala  * Return 0 if it's below limits, or errno, if it's not.
406097055e2SEdward Tomasz Napierala  *
407097055e2SEdward Tomasz Napierala  * Note that decreasing the allocation always returns 0,
408097055e2SEdward Tomasz Napierala  * even if it's above the limit.
409097055e2SEdward Tomasz Napierala  */
410097055e2SEdward Tomasz Napierala int
411097055e2SEdward Tomasz Napierala racct_set(struct proc *p, int resource, uint64_t amount)
412097055e2SEdward Tomasz Napierala {
413097055e2SEdward Tomasz Napierala 	int error;
414097055e2SEdward Tomasz Napierala 
415097055e2SEdward Tomasz Napierala 	mtx_lock(&racct_lock);
416097055e2SEdward Tomasz Napierala 	error = racct_set_locked(p, resource, amount);
417097055e2SEdward Tomasz Napierala 	mtx_unlock(&racct_lock);
418097055e2SEdward Tomasz Napierala 	return (error);
419097055e2SEdward Tomasz Napierala }
420097055e2SEdward Tomasz Napierala 
421097055e2SEdward Tomasz Napierala void
422097055e2SEdward Tomasz Napierala racct_set_force(struct proc *p, int resource, uint64_t amount)
423097055e2SEdward Tomasz Napierala {
424097055e2SEdward Tomasz Napierala 	int64_t diff;
425097055e2SEdward Tomasz Napierala 
426097055e2SEdward Tomasz Napierala 	if (p->p_flag & P_SYSTEM)
427097055e2SEdward Tomasz Napierala 		return;
428097055e2SEdward Tomasz Napierala 
429097055e2SEdward Tomasz Napierala 	SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
430097055e2SEdward Tomasz Napierala 
431097055e2SEdward Tomasz Napierala 	/*
432097055e2SEdward Tomasz Napierala 	 * We need proc lock to dereference p->p_ucred.
433097055e2SEdward Tomasz Napierala 	 */
434097055e2SEdward Tomasz Napierala 	PROC_LOCK_ASSERT(p, MA_OWNED);
435097055e2SEdward Tomasz Napierala 
436097055e2SEdward Tomasz Napierala 	mtx_lock(&racct_lock);
437097055e2SEdward Tomasz Napierala 	diff = amount - p->p_racct->r_resources[resource];
438097055e2SEdward Tomasz Napierala 	racct_alloc_resource(p->p_racct, resource, diff);
439097055e2SEdward Tomasz Napierala 	if (diff > 0)
440097055e2SEdward Tomasz Napierala 		racct_add_cred_locked(p->p_ucred, resource, diff);
441097055e2SEdward Tomasz Napierala 	else if (diff < 0)
442097055e2SEdward Tomasz Napierala 		racct_sub_cred_locked(p->p_ucred, resource, -diff);
443097055e2SEdward Tomasz Napierala 	mtx_unlock(&racct_lock);
444097055e2SEdward Tomasz Napierala }
445097055e2SEdward Tomasz Napierala 
446097055e2SEdward Tomasz Napierala /*
447097055e2SEdward Tomasz Napierala  * Returns amount of 'resource' the process 'p' can keep allocated.
448097055e2SEdward Tomasz Napierala  * Allocating more than that would be denied, unless the resource
449097055e2SEdward Tomasz Napierala  * is marked undeniable.  Amount of already allocated resource does
450097055e2SEdward Tomasz Napierala  * not matter.
451097055e2SEdward Tomasz Napierala  */
452097055e2SEdward Tomasz Napierala uint64_t
453097055e2SEdward Tomasz Napierala racct_get_limit(struct proc *p, int resource)
454097055e2SEdward Tomasz Napierala {
455097055e2SEdward Tomasz Napierala 
456097055e2SEdward Tomasz Napierala #ifdef RCTL
457097055e2SEdward Tomasz Napierala 	return (rctl_get_limit(p, resource));
458097055e2SEdward Tomasz Napierala #else
459097055e2SEdward Tomasz Napierala 	return (UINT64_MAX);
460097055e2SEdward Tomasz Napierala #endif
461097055e2SEdward Tomasz Napierala }
462097055e2SEdward Tomasz Napierala 
463097055e2SEdward Tomasz Napierala /*
464097055e2SEdward Tomasz Napierala  * Returns amount of 'resource' the process 'p' can keep allocated.
465097055e2SEdward Tomasz Napierala  * Allocating more than that would be denied, unless the resource
466097055e2SEdward Tomasz Napierala  * is marked undeniable.  Amount of already allocated resource does
467097055e2SEdward Tomasz Napierala  * matter.
468097055e2SEdward Tomasz Napierala  */
469097055e2SEdward Tomasz Napierala uint64_t
470097055e2SEdward Tomasz Napierala racct_get_available(struct proc *p, int resource)
471097055e2SEdward Tomasz Napierala {
472097055e2SEdward Tomasz Napierala 
473097055e2SEdward Tomasz Napierala #ifdef RCTL
474097055e2SEdward Tomasz Napierala 	return (rctl_get_available(p, resource));
475097055e2SEdward Tomasz Napierala #else
476097055e2SEdward Tomasz Napierala 	return (UINT64_MAX);
477097055e2SEdward Tomasz Napierala #endif
478097055e2SEdward Tomasz Napierala }
479097055e2SEdward Tomasz Napierala 
480097055e2SEdward Tomasz Napierala /*
481097055e2SEdward Tomasz Napierala  * Decrease allocation of 'resource' by 'amount' for process 'p'.
482097055e2SEdward Tomasz Napierala  */
483097055e2SEdward Tomasz Napierala void
484097055e2SEdward Tomasz Napierala racct_sub(struct proc *p, int resource, uint64_t amount)
485097055e2SEdward Tomasz Napierala {
486097055e2SEdward Tomasz Napierala 
487097055e2SEdward Tomasz Napierala 	if (p->p_flag & P_SYSTEM)
488097055e2SEdward Tomasz Napierala 		return;
489097055e2SEdward Tomasz Napierala 
490097055e2SEdward Tomasz Napierala 	SDT_PROBE(racct, kernel, rusage, sub, p, resource, amount, 0, 0);
491097055e2SEdward Tomasz Napierala 
492097055e2SEdward Tomasz Napierala 	/*
493097055e2SEdward Tomasz Napierala 	 * We need proc lock to dereference p->p_ucred.
494097055e2SEdward Tomasz Napierala 	 */
495097055e2SEdward Tomasz Napierala 	PROC_LOCK_ASSERT(p, MA_OWNED);
496097055e2SEdward Tomasz Napierala 	KASSERT(racct_is_reclaimable(resource),
497097055e2SEdward Tomasz Napierala 	    ("racct_sub: called for non-reclaimable resource %d", resource));
498097055e2SEdward Tomasz Napierala 
499097055e2SEdward Tomasz Napierala 	mtx_lock(&racct_lock);
500097055e2SEdward Tomasz Napierala 	KASSERT(amount <= p->p_racct->r_resources[resource],
501097055e2SEdward Tomasz Napierala 	    ("racct_sub: freeing %ju of resource %d, which is more "
502097055e2SEdward Tomasz Napierala 	     "than allocated %jd for %s (pid %d)", amount, resource,
503097055e2SEdward Tomasz Napierala 	    (intmax_t)p->p_racct->r_resources[resource], p->p_comm, p->p_pid));
504097055e2SEdward Tomasz Napierala 
505097055e2SEdward Tomasz Napierala 	racct_alloc_resource(p->p_racct, resource, -amount);
506097055e2SEdward Tomasz Napierala 	racct_sub_cred_locked(p->p_ucred, resource, amount);
507097055e2SEdward Tomasz Napierala 	mtx_unlock(&racct_lock);
508097055e2SEdward Tomasz Napierala }
509097055e2SEdward Tomasz Napierala 
510097055e2SEdward Tomasz Napierala static void
511097055e2SEdward Tomasz Napierala racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount)
512097055e2SEdward Tomasz Napierala {
513097055e2SEdward Tomasz Napierala 	struct prison *pr;
514097055e2SEdward Tomasz Napierala 
515097055e2SEdward Tomasz Napierala 	SDT_PROBE(racct, kernel, rusage, sub_cred, cred, resource, amount,
516097055e2SEdward Tomasz Napierala 	    0, 0);
517097055e2SEdward Tomasz Napierala 
518097055e2SEdward Tomasz Napierala #ifdef notyet
519097055e2SEdward Tomasz Napierala 	KASSERT(racct_is_reclaimable(resource),
520097055e2SEdward Tomasz Napierala 	    ("racct_sub_cred: called for non-reclaimable resource %d",
521097055e2SEdward Tomasz Napierala 	     resource));
522097055e2SEdward Tomasz Napierala #endif
523097055e2SEdward Tomasz Napierala 
524097055e2SEdward Tomasz Napierala 	racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, -amount);
525097055e2SEdward Tomasz Napierala 	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
526*a7ad07bfSEdward Tomasz Napierala 		racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource,
527*a7ad07bfSEdward Tomasz Napierala 		    -amount);
528097055e2SEdward Tomasz Napierala 	racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, -amount);
529097055e2SEdward Tomasz Napierala }
530097055e2SEdward Tomasz Napierala 
531097055e2SEdward Tomasz Napierala /*
532097055e2SEdward Tomasz Napierala  * Decrease allocation of 'resource' by 'amount' for credential 'cred'.
533097055e2SEdward Tomasz Napierala  */
534097055e2SEdward Tomasz Napierala void
535097055e2SEdward Tomasz Napierala racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
536097055e2SEdward Tomasz Napierala {
537097055e2SEdward Tomasz Napierala 
538097055e2SEdward Tomasz Napierala 	mtx_lock(&racct_lock);
539097055e2SEdward Tomasz Napierala 	racct_sub_cred_locked(cred, resource, amount);
540097055e2SEdward Tomasz Napierala 	mtx_unlock(&racct_lock);
541097055e2SEdward Tomasz Napierala }
542097055e2SEdward Tomasz Napierala 
543097055e2SEdward Tomasz Napierala /*
544097055e2SEdward Tomasz Napierala  * Inherit resource usage information from the parent process.
545097055e2SEdward Tomasz Napierala  */
546097055e2SEdward Tomasz Napierala int
547097055e2SEdward Tomasz Napierala racct_proc_fork(struct proc *parent, struct proc *child)
548097055e2SEdward Tomasz Napierala {
549097055e2SEdward Tomasz Napierala 	int i, error = 0;
550097055e2SEdward Tomasz Napierala 
551097055e2SEdward Tomasz Napierala 	/*
552097055e2SEdward Tomasz Napierala 	 * Create racct for the child process.
553097055e2SEdward Tomasz Napierala 	 */
554097055e2SEdward Tomasz Napierala 	racct_create(&child->p_racct);
555097055e2SEdward Tomasz Napierala 
556097055e2SEdward Tomasz Napierala 	/*
557097055e2SEdward Tomasz Napierala 	 * No resource accounting for kernel processes.
558097055e2SEdward Tomasz Napierala 	 */
559097055e2SEdward Tomasz Napierala 	if (child->p_flag & P_SYSTEM)
560097055e2SEdward Tomasz Napierala 		return (0);
561097055e2SEdward Tomasz Napierala 
562097055e2SEdward Tomasz Napierala 	PROC_LOCK(parent);
563097055e2SEdward Tomasz Napierala 	PROC_LOCK(child);
564097055e2SEdward Tomasz Napierala 	mtx_lock(&racct_lock);
565097055e2SEdward Tomasz Napierala 
566097055e2SEdward Tomasz Napierala 	/*
567097055e2SEdward Tomasz Napierala 	 * Inherit resource usage.
568097055e2SEdward Tomasz Napierala 	 */
569097055e2SEdward Tomasz Napierala 	for (i = 0; i <= RACCT_MAX; i++) {
570097055e2SEdward Tomasz Napierala 		if (parent->p_racct->r_resources[i] == 0 ||
571097055e2SEdward Tomasz Napierala 		    !racct_is_inheritable(i))
572097055e2SEdward Tomasz Napierala 			continue;
573097055e2SEdward Tomasz Napierala 
574097055e2SEdward Tomasz Napierala 		error = racct_set_locked(child, i,
575097055e2SEdward Tomasz Napierala 		    parent->p_racct->r_resources[i]);
576097055e2SEdward Tomasz Napierala 		if (error != 0) {
577097055e2SEdward Tomasz Napierala 			/*
578097055e2SEdward Tomasz Napierala 			 * XXX: The only purpose of these two lines is
579097055e2SEdward Tomasz Napierala 			 * to prevent from tripping checks in racct_destroy().
580097055e2SEdward Tomasz Napierala 			 */
581097055e2SEdward Tomasz Napierala 			for (i = 0; i <= RACCT_MAX; i++)
582097055e2SEdward Tomasz Napierala 				racct_set_locked(child, i, 0);
583097055e2SEdward Tomasz Napierala 			goto out;
584097055e2SEdward Tomasz Napierala 		}
585097055e2SEdward Tomasz Napierala 	}
586097055e2SEdward Tomasz Napierala 
587097055e2SEdward Tomasz Napierala #ifdef RCTL
588097055e2SEdward Tomasz Napierala 	error = rctl_proc_fork(parent, child);
589097055e2SEdward Tomasz Napierala 	if (error != 0) {
590097055e2SEdward Tomasz Napierala 		/*
591097055e2SEdward Tomasz Napierala 		 * XXX: The only purpose of these two lines is to prevent from
592097055e2SEdward Tomasz Napierala 		 * tripping checks in racct_destroy().
593097055e2SEdward Tomasz Napierala 		 */
594097055e2SEdward Tomasz Napierala 		for (i = 0; i <= RACCT_MAX; i++)
595097055e2SEdward Tomasz Napierala 			racct_set_locked(child, i, 0);
596097055e2SEdward Tomasz Napierala 	}
597097055e2SEdward Tomasz Napierala #endif
598097055e2SEdward Tomasz Napierala 
599097055e2SEdward Tomasz Napierala out:
600097055e2SEdward Tomasz Napierala 	if (error != 0)
601097055e2SEdward Tomasz Napierala 		racct_destroy_locked(&child->p_racct);
602097055e2SEdward Tomasz Napierala 	mtx_unlock(&racct_lock);
603097055e2SEdward Tomasz Napierala 	PROC_UNLOCK(child);
604097055e2SEdward Tomasz Napierala 	PROC_UNLOCK(parent);
605097055e2SEdward Tomasz Napierala 
606097055e2SEdward Tomasz Napierala 	return (error);
607097055e2SEdward Tomasz Napierala }
608097055e2SEdward Tomasz Napierala 
609097055e2SEdward Tomasz Napierala void
610097055e2SEdward Tomasz Napierala racct_proc_exit(struct proc *p)
611097055e2SEdward Tomasz Napierala {
612097055e2SEdward Tomasz Napierala 	uint64_t runtime;
613097055e2SEdward Tomasz Napierala 
614097055e2SEdward Tomasz Napierala 	PROC_LOCK(p);
615097055e2SEdward Tomasz Napierala 	/*
616097055e2SEdward Tomasz Napierala 	 * We don't need to calculate rux, proc_reap() has already done this.
617097055e2SEdward Tomasz Napierala 	 */
618097055e2SEdward Tomasz Napierala 	runtime = cputick2usec(p->p_rux.rux_runtime);
619097055e2SEdward Tomasz Napierala #ifdef notyet
620097055e2SEdward Tomasz Napierala 	KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime"));
621097055e2SEdward Tomasz Napierala #else
622097055e2SEdward Tomasz Napierala 	if (runtime < p->p_prev_runtime)
623097055e2SEdward Tomasz Napierala 		runtime = p->p_prev_runtime;
624097055e2SEdward Tomasz Napierala #endif
625097055e2SEdward Tomasz Napierala 	racct_set(p, RACCT_CPU, runtime);
626097055e2SEdward Tomasz Napierala 
627097055e2SEdward Tomasz Napierala 	/*
628097055e2SEdward Tomasz Napierala 	 * XXX: Free this some other way.
629097055e2SEdward Tomasz Napierala 	 */
630097055e2SEdward Tomasz Napierala 	racct_set(p, RACCT_FSIZE, 0);
631097055e2SEdward Tomasz Napierala 	racct_set(p, RACCT_NPTS, 0);
632097055e2SEdward Tomasz Napierala 	racct_set(p, RACCT_NTHR, 0);
633097055e2SEdward Tomasz Napierala 	racct_set(p, RACCT_RSS, 0);
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)
674*a7ad07bfSEdward Tomasz Napierala 			racct_sub_racct(pr->pr_prison_racct->prr_racct,
675*a7ad07bfSEdward Tomasz Napierala 			    p->p_racct);
676097055e2SEdward Tomasz Napierala 		for (pr = newpr; pr != NULL; pr = pr->pr_parent)
677*a7ad07bfSEdward Tomasz Napierala 			racct_add_racct(pr->pr_prison_racct->prr_racct,
678*a7ad07bfSEdward 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 	 */
751*a7ad07bfSEdward 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