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