kern_racct.c revision 220137
1/*-
2 * Copyright (c) 2010 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Edward Tomasz Napierala under sponsorship
6 * from the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/kern/kern_racct.c 220137 2011-03-29 17:47:25Z trasz $
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/kern/kern_racct.c 220137 2011-03-29 17:47:25Z trasz $");
34
35#include "opt_kdtrace.h"
36
37#include <sys/param.h>
38#include <sys/eventhandler.h>
39#include <sys/param.h>
40#include <sys/jail.h>
41#include <sys/kernel.h>
42#include <sys/kthread.h>
43#include <sys/lock.h>
44#include <sys/loginclass.h>
45#include <sys/malloc.h>
46#include <sys/mutex.h>
47#include <sys/proc.h>
48#include <sys/racct.h>
49#include <sys/resourcevar.h>
50#include <sys/sbuf.h>
51#include <sys/sched.h>
52#include <sys/sdt.h>
53#include <sys/sx.h>
54#include <sys/sysent.h>
55#include <sys/sysproto.h>
56#include <sys/systm.h>
57#include <sys/umtx.h>
58
59#ifdef RCTL
60#include <sys/rctl.h>
61#endif
62
63#ifdef RACCT
64
65FEATURE(racct, "Resource Accounting");
66
67static struct mtx racct_lock;
68MTX_SYSINIT(racct_lock, &racct_lock, "racct lock", MTX_DEF);
69
70static uma_zone_t racct_zone;
71
72static void racct_sub_racct(struct racct *dest, const struct racct *src);
73static void racct_sub_cred_locked(struct ucred *cred, int resource,
74		uint64_t amount);
75static void racct_add_cred_locked(struct ucred *cred, int resource,
76		uint64_t amount);
77
78SDT_PROVIDER_DEFINE(racct);
79SDT_PROBE_DEFINE3(racct, kernel, rusage, add, add, "struct proc *", "int",
80    "uint64_t");
81SDT_PROBE_DEFINE3(racct, kernel, rusage, add_failure, add-failure,
82    "struct proc *", "int", "uint64_t");
83SDT_PROBE_DEFINE3(racct, kernel, rusage, add_cred, add-cred, "struct ucred *",
84    "int", "uint64_t");
85SDT_PROBE_DEFINE3(racct, kernel, rusage, add_force, add-force, "struct proc *",
86    "int", "uint64_t");
87SDT_PROBE_DEFINE3(racct, kernel, rusage, set, set, "struct proc *", "int",
88    "uint64_t");
89SDT_PROBE_DEFINE3(racct, kernel, rusage, set_failure, set-failure,
90    "struct proc *", "int", "uint64_t");
91SDT_PROBE_DEFINE3(racct, kernel, rusage, sub, sub, "struct proc *", "int",
92    "uint64_t");
93SDT_PROBE_DEFINE3(racct, kernel, rusage, sub_cred, sub-cred, "struct ucred *",
94    "int", "uint64_t");
95SDT_PROBE_DEFINE1(racct, kernel, racct, create, create, "struct racct *");
96SDT_PROBE_DEFINE1(racct, kernel, racct, destroy, destroy, "struct racct *");
97SDT_PROBE_DEFINE2(racct, kernel, racct, join, join, "struct racct *",
98    "struct racct *");
99SDT_PROBE_DEFINE2(racct, kernel, racct, join_failure, join-failure,
100    "struct racct *", "struct racct *");
101SDT_PROBE_DEFINE2(racct, kernel, racct, leave, leave, "struct racct *",
102    "struct racct *");
103
104int racct_types[] = {
105	[RACCT_CPU] =
106		RACCT_IN_THOUSANDS,
107	[RACCT_FSIZE] =
108		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
109	[RACCT_DATA] =
110		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
111	[RACCT_STACK] =
112		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
113	[RACCT_CORE] =
114		RACCT_DENIABLE,
115	[RACCT_RSS] =
116		RACCT_RECLAIMABLE,
117	[RACCT_MEMLOCK] =
118		RACCT_RECLAIMABLE | RACCT_DENIABLE,
119	[RACCT_NPROC] =
120		RACCT_RECLAIMABLE | RACCT_DENIABLE,
121	[RACCT_NOFILE] =
122		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
123	[RACCT_SBSIZE] =
124		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
125	[RACCT_VMEM] =
126		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
127	[RACCT_NPTS] =
128		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
129	[RACCT_SWAP] =
130		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
131	[RACCT_NTHR] =
132		RACCT_RECLAIMABLE | RACCT_DENIABLE,
133	[RACCT_MSGQQUEUED] =
134		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
135	[RACCT_MSGQSIZE] =
136		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
137	[RACCT_NMSGQ] =
138		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
139	[RACCT_NSEM] =
140		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
141	[RACCT_NSEMOP] =
142		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
143	[RACCT_NSHM] =
144		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
145	[RACCT_SHMSIZE] =
146		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
147	[RACCT_WALLCLOCK] =
148		RACCT_IN_THOUSANDS };
149
150static void
151racct_add_racct(struct racct *dest, const struct racct *src)
152{
153	int i;
154
155	mtx_assert(&racct_lock, MA_OWNED);
156
157	/*
158	 * Update resource usage in dest.
159	 */
160	for (i = 0; i <= RACCT_MAX; i++) {
161		KASSERT(dest->r_resources[i] >= 0,
162		    ("racct propagation meltdown: dest < 0"));
163		KASSERT(src->r_resources[i] >= 0,
164		    ("racct propagation meltdown: src < 0"));
165		dest->r_resources[i] += src->r_resources[i];
166	}
167}
168
169static void
170racct_sub_racct(struct racct *dest, const struct racct *src)
171{
172	int i;
173
174	mtx_assert(&racct_lock, MA_OWNED);
175
176	/*
177	 * Update resource usage in dest.
178	 */
179	for (i = 0; i <= RACCT_MAX; i++) {
180		if (!racct_is_sloppy(i)) {
181			KASSERT(dest->r_resources[i] >= 0,
182			    ("racct propagation meltdown: dest < 0"));
183			KASSERT(src->r_resources[i] >= 0,
184			    ("racct propagation meltdown: src < 0"));
185			KASSERT(src->r_resources[i] <= dest->r_resources[i],
186			    ("racct propagation meltdown: src > dest"));
187		}
188		if (racct_is_reclaimable(i)) {
189			dest->r_resources[i] -= src->r_resources[i];
190			if (dest->r_resources[i] < 0) {
191				KASSERT(racct_is_sloppy(i),
192				    ("racct_sub_racct: usage < 0"));
193				dest->r_resources[i] = 0;
194			}
195		}
196	}
197}
198
199void
200racct_create(struct racct **racctp)
201{
202
203	SDT_PROBE(racct, kernel, racct, create, racctp, 0, 0, 0, 0);
204
205	KASSERT(*racctp == NULL, ("racct already allocated"));
206
207	*racctp = uma_zalloc(racct_zone, M_WAITOK | M_ZERO);
208}
209
210static void
211racct_destroy_locked(struct racct **racctp)
212{
213	int i;
214	struct racct *racct;
215
216	SDT_PROBE(racct, kernel, racct, destroy, racctp, 0, 0, 0, 0);
217
218	mtx_assert(&racct_lock, MA_OWNED);
219	KASSERT(racctp != NULL, ("NULL racctp"));
220	KASSERT(*racctp != NULL, ("NULL racct"));
221
222	racct = *racctp;
223
224	for (i = 0; i <= RACCT_MAX; i++) {
225		if (racct_is_sloppy(i))
226			continue;
227		if (!racct_is_reclaimable(i))
228			continue;
229		KASSERT(racct->r_resources[i] == 0,
230		    ("destroying non-empty racct: "
231		    "%ju allocated for resource %d\n",
232		    racct->r_resources[i], i));
233	}
234	uma_zfree(racct_zone, racct);
235	*racctp = NULL;
236}
237
238void
239racct_destroy(struct racct **racct)
240{
241
242	mtx_lock(&racct_lock);
243	racct_destroy_locked(racct);
244	mtx_unlock(&racct_lock);
245}
246
247/*
248 * Increase consumption of 'resource' by 'amount' for 'racct'
249 * and all its parents.  Differently from other cases, 'amount' here
250 * may be less than zero.
251 */
252static void
253racct_alloc_resource(struct racct *racct, int resource,
254    uint64_t amount)
255{
256
257	mtx_assert(&racct_lock, MA_OWNED);
258	KASSERT(racct != NULL, ("NULL racct"));
259
260	racct->r_resources[resource] += amount;
261	if (racct->r_resources[resource] < 0) {
262		KASSERT(racct_is_sloppy(resource),
263		    ("racct_alloc_resource: usage < 0"));
264		racct->r_resources[resource] = 0;
265	}
266}
267
268/*
269 * Increase allocation of 'resource' by 'amount' for process 'p'.
270 * Return 0 if it's below limits, or errno, if it's not.
271 */
272int
273racct_add(struct proc *p, int resource, uint64_t amount)
274{
275#ifdef RCTL
276	int error;
277#endif
278
279	if (p->p_flag & P_SYSTEM)
280		return (0);
281
282	SDT_PROBE(racct, kernel, rusage, add, p, resource, amount, 0, 0);
283
284	/*
285	 * We need proc lock to dereference p->p_ucred.
286	 */
287	PROC_LOCK_ASSERT(p, MA_OWNED);
288	KASSERT(amount >= 0, ("racct_add: invalid amount for resource %d: %ju",
289	    resource, amount));
290
291	mtx_lock(&racct_lock);
292#ifdef RCTL
293	error = rctl_enforce(p, resource, amount);
294	if (error && racct_is_deniable(resource)) {
295		SDT_PROBE(racct, kernel, rusage, add_failure, p, resource,
296		    amount, 0, 0);
297		mtx_unlock(&racct_lock);
298		return (error);
299	}
300#endif
301	racct_alloc_resource(p->p_racct, resource, amount);
302	racct_add_cred_locked(p->p_ucred, resource, amount);
303	mtx_unlock(&racct_lock);
304
305	return (0);
306}
307
308static void
309racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount)
310{
311	struct prison *pr;
312
313	SDT_PROBE(racct, kernel, rusage, add_cred, cred, resource, amount,
314	    0, 0);
315
316	KASSERT(amount >= 0,
317	    ("racct_add_cred: invalid amount for resource %d: %ju",
318	    resource, amount));
319
320	racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, amount);
321	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
322		racct_alloc_resource(pr->pr_racct, resource, amount);
323	racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, amount);
324}
325
326/*
327 * Increase allocation of 'resource' by 'amount' for credential 'cred'.
328 * Doesn't check for limits and never fails.
329 *
330 * XXX: Shouldn't this ever return an error?
331 */
332void
333racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
334{
335
336	mtx_lock(&racct_lock);
337	racct_add_cred_locked(cred, resource, amount);
338	mtx_unlock(&racct_lock);
339}
340
341/*
342 * Increase allocation of 'resource' by 'amount' for process 'p'.
343 * Doesn't check for limits and never fails.
344 */
345void
346racct_add_force(struct proc *p, int resource, uint64_t amount)
347{
348
349	if (p->p_flag & P_SYSTEM)
350		return;
351
352	SDT_PROBE(racct, kernel, rusage, add_force, p, resource, amount, 0, 0);
353
354	/*
355	 * We need proc lock to dereference p->p_ucred.
356	 */
357	PROC_LOCK_ASSERT(p, MA_OWNED);
358	KASSERT(amount >= 0,
359	    ("racct_add_force: invalid amount for resource %d: %ju",
360	    resource, amount));
361
362	mtx_lock(&racct_lock);
363	racct_alloc_resource(p->p_racct, resource, amount);
364	mtx_unlock(&racct_lock);
365	racct_add_cred(p->p_ucred, resource, amount);
366}
367
368static int
369racct_set_locked(struct proc *p, int resource, uint64_t amount)
370{
371	int64_t diff;
372#ifdef RCTL
373	int error;
374#endif
375
376	if (p->p_flag & P_SYSTEM)
377		return (0);
378
379	SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
380
381	/*
382	 * We need proc lock to dereference p->p_ucred.
383	 */
384	PROC_LOCK_ASSERT(p, MA_OWNED);
385	KASSERT(amount >= 0, ("racct_set: invalid amount for resource %d: %ju",
386	    resource, amount));
387
388	diff = amount - p->p_racct->r_resources[resource];
389#ifdef notyet
390	KASSERT(diff >= 0 || racct_is_reclaimable(resource),
391	    ("racct_set: usage of non-reclaimable resource %d dropping",
392	     resource));
393#endif
394#ifdef RCTL
395	if (diff > 0) {
396		error = rctl_enforce(p, resource, diff);
397		if (error && racct_is_deniable(resource)) {
398			SDT_PROBE(racct, kernel, rusage, set_failure, p,
399			    resource, amount, 0, 0);
400			return (error);
401		}
402	}
403#endif
404	racct_alloc_resource(p->p_racct, resource, diff);
405	if (diff > 0)
406		racct_add_cred_locked(p->p_ucred, resource, diff);
407	else if (diff < 0)
408		racct_sub_cred_locked(p->p_ucred, resource, -diff);
409
410	return (0);
411}
412
413/*
414 * Set allocation of 'resource' to 'amount' for process 'p'.
415 * Return 0 if it's below limits, or errno, if it's not.
416 *
417 * Note that decreasing the allocation always returns 0,
418 * even if it's above the limit.
419 */
420int
421racct_set(struct proc *p, int resource, uint64_t amount)
422{
423	int error;
424
425	mtx_lock(&racct_lock);
426	error = racct_set_locked(p, resource, amount);
427	mtx_unlock(&racct_lock);
428	return (error);
429}
430
431void
432racct_set_force(struct proc *p, int resource, uint64_t amount)
433{
434	int64_t diff;
435
436	if (p->p_flag & P_SYSTEM)
437		return;
438
439	SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
440
441	/*
442	 * We need proc lock to dereference p->p_ucred.
443	 */
444	PROC_LOCK_ASSERT(p, MA_OWNED);
445	KASSERT(amount >= 0,
446	    ("racct_set_force: invalid amount for resource %d: %ju",
447	    resource, amount));
448
449	mtx_lock(&racct_lock);
450	diff = amount - p->p_racct->r_resources[resource];
451	racct_alloc_resource(p->p_racct, resource, diff);
452	if (diff > 0)
453		racct_add_cred_locked(p->p_ucred, resource, diff);
454	else if (diff < 0)
455		racct_sub_cred_locked(p->p_ucred, resource, -diff);
456	mtx_unlock(&racct_lock);
457}
458
459/*
460 * Returns amount of 'resource' the process 'p' can keep allocated.
461 * Allocating more than that would be denied, unless the resource
462 * is marked undeniable.  Amount of already allocated resource does
463 * not matter.
464 */
465uint64_t
466racct_get_limit(struct proc *p, int resource)
467{
468
469#ifdef RCTL
470	return (rctl_get_limit(p, resource));
471#else
472	return (UINT64_MAX);
473#endif
474}
475
476/*
477 * Returns amount of 'resource' the process 'p' can keep allocated.
478 * Allocating more than that would be denied, unless the resource
479 * is marked undeniable.  Amount of already allocated resource does
480 * matter.
481 */
482uint64_t
483racct_get_available(struct proc *p, int resource)
484{
485
486#ifdef RCTL
487	return (rctl_get_available(p, resource));
488#else
489	return (UINT64_MAX);
490#endif
491}
492
493/*
494 * Decrease allocation of 'resource' by 'amount' for process 'p'.
495 */
496void
497racct_sub(struct proc *p, int resource, uint64_t amount)
498{
499
500	if (p->p_flag & P_SYSTEM)
501		return;
502
503	SDT_PROBE(racct, kernel, rusage, sub, p, resource, amount, 0, 0);
504
505	/*
506	 * We need proc lock to dereference p->p_ucred.
507	 */
508	PROC_LOCK_ASSERT(p, MA_OWNED);
509	KASSERT(amount >= 0, ("racct_sub: invalid amount for resource %d: %ju",
510	    resource, amount));
511	KASSERT(racct_is_reclaimable(resource),
512	    ("racct_sub: called for non-reclaimable resource %d", resource));
513
514	mtx_lock(&racct_lock);
515	KASSERT(amount <= p->p_racct->r_resources[resource],
516	    ("racct_sub: freeing %ju of resource %d, which is more "
517	     "than allocated %jd for %s (pid %d)", amount, resource,
518	    (intmax_t)p->p_racct->r_resources[resource], p->p_comm, p->p_pid));
519
520	racct_alloc_resource(p->p_racct, resource, -amount);
521	racct_sub_cred_locked(p->p_ucred, resource, amount);
522	mtx_unlock(&racct_lock);
523}
524
525static void
526racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount)
527{
528	struct prison *pr;
529
530	SDT_PROBE(racct, kernel, rusage, sub_cred, cred, resource, amount,
531	    0, 0);
532
533	KASSERT(amount >= 0,
534	    ("racct_sub_cred: invalid amount for resource %d: %ju",
535	    resource, amount));
536#ifdef notyet
537	KASSERT(racct_is_reclaimable(resource),
538	    ("racct_sub_cred: called for non-reclaimable resource %d",
539	     resource));
540#endif
541
542	racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, -amount);
543	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
544		racct_alloc_resource(pr->pr_racct, resource, -amount);
545	racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, -amount);
546}
547
548/*
549 * Decrease allocation of 'resource' by 'amount' for credential 'cred'.
550 */
551void
552racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
553{
554
555	mtx_lock(&racct_lock);
556	racct_sub_cred_locked(cred, resource, amount);
557	mtx_unlock(&racct_lock);
558}
559
560/*
561 * Inherit resource usage information from the parent process.
562 */
563int
564racct_proc_fork(struct proc *parent, struct proc *child)
565{
566	int i, error = 0;
567
568	/*
569	 * Create racct for the child process.
570	 */
571	racct_create(&child->p_racct);
572
573	/*
574	 * No resource accounting for kernel processes.
575	 */
576	if (child->p_flag & P_SYSTEM)
577		return (0);
578
579	PROC_LOCK(parent);
580	PROC_LOCK(child);
581	mtx_lock(&racct_lock);
582
583	/*
584	 * Inherit resource usage.
585	 */
586	for (i = 0; i <= RACCT_MAX; i++) {
587		if (parent->p_racct->r_resources[i] == 0 ||
588		    !racct_is_inheritable(i))
589			continue;
590
591		error = racct_set_locked(child, i,
592		    parent->p_racct->r_resources[i]);
593		if (error != 0) {
594			/*
595			 * XXX: The only purpose of these two lines is
596			 * to prevent from tripping checks in racct_destroy().
597			 */
598			for (i = 0; i <= RACCT_MAX; i++)
599				racct_set_locked(child, i, 0);
600			goto out;
601		}
602	}
603
604#ifdef RCTL
605	error = rctl_proc_fork(parent, child);
606	if (error != 0) {
607		/*
608		 * XXX: The only purpose of these two lines is to prevent from
609		 * tripping checks in racct_destroy().
610		 */
611		for (i = 0; i <= RACCT_MAX; i++)
612			racct_set_locked(child, i, 0);
613	}
614#endif
615
616out:
617	if (error != 0)
618		racct_destroy_locked(&child->p_racct);
619	mtx_unlock(&racct_lock);
620	PROC_UNLOCK(child);
621	PROC_UNLOCK(parent);
622
623	return (error);
624}
625
626void
627racct_proc_exit(struct proc *p)
628{
629	uint64_t runtime;
630
631	PROC_LOCK(p);
632	/*
633	 * We don't need to calculate rux, proc_reap() has already done this.
634	 */
635	runtime = cputick2usec(p->p_rux.rux_runtime);
636#ifdef notyet
637	KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime"));
638#else
639	if (runtime < p->p_prev_runtime)
640		runtime = p->p_prev_runtime;
641#endif
642	racct_set(p, RACCT_CPU, runtime);
643
644	/*
645	 * XXX: Free this some other way.
646	 */
647	racct_set(p, RACCT_FSIZE, 0);
648	racct_set(p, RACCT_NPTS, 0);
649	racct_set(p, RACCT_NTHR, 0);
650	racct_set(p, RACCT_RSS, 0);
651	PROC_UNLOCK(p);
652
653#ifdef RCTL
654	rctl_racct_release(p->p_racct);
655#endif
656	racct_destroy(&p->p_racct);
657}
658
659/*
660 * Called after credentials change, to move resource utilisation
661 * between raccts.
662 */
663void
664racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
665    struct ucred *newcred)
666{
667	struct uidinfo *olduip, *newuip;
668	struct loginclass *oldlc, *newlc;
669	struct prison *oldpr, *newpr, *pr;
670
671	PROC_LOCK_ASSERT(p, MA_NOTOWNED);
672
673	newuip = newcred->cr_ruidinfo;
674	olduip = oldcred->cr_ruidinfo;
675	newlc = newcred->cr_loginclass;
676	oldlc = oldcred->cr_loginclass;
677	newpr = newcred->cr_prison;
678	oldpr = oldcred->cr_prison;
679
680	mtx_lock(&racct_lock);
681	if (newuip != olduip) {
682		racct_sub_racct(olduip->ui_racct, p->p_racct);
683		racct_add_racct(newuip->ui_racct, p->p_racct);
684	}
685	if (newlc != oldlc) {
686		racct_sub_racct(oldlc->lc_racct, p->p_racct);
687		racct_add_racct(newlc->lc_racct, p->p_racct);
688	}
689	if (newpr != oldpr) {
690		for (pr = oldpr; pr != NULL; pr = pr->pr_parent)
691			racct_sub_racct(pr->pr_racct, p->p_racct);
692		for (pr = newpr; pr != NULL; pr = pr->pr_parent)
693			racct_add_racct(pr->pr_racct, p->p_racct);
694	}
695	mtx_unlock(&racct_lock);
696
697#ifdef RCTL
698	rctl_proc_ucred_changed(p, newcred);
699#endif
700}
701
702static void
703racctd(void)
704{
705	struct thread *td;
706	struct proc *p;
707	struct timeval wallclock;
708	uint64_t runtime;
709
710	for (;;) {
711		sx_slock(&allproc_lock);
712
713		FOREACH_PROC_IN_SYSTEM(p) {
714			if (p->p_state != PRS_NORMAL)
715				continue;
716			if (p->p_flag & P_SYSTEM)
717				continue;
718
719			microuptime(&wallclock);
720			timevalsub(&wallclock, &p->p_stats->p_start);
721			PROC_LOCK(p);
722			PROC_SLOCK(p);
723			FOREACH_THREAD_IN_PROC(p, td) {
724				ruxagg(p, td);
725				thread_lock(td);
726				thread_unlock(td);
727			}
728			runtime = cputick2usec(p->p_rux.rux_runtime);
729			PROC_SUNLOCK(p);
730#ifdef notyet
731			KASSERT(runtime >= p->p_prev_runtime,
732			    ("runtime < p_prev_runtime"));
733#else
734			if (runtime < p->p_prev_runtime)
735				runtime = p->p_prev_runtime;
736#endif
737			p->p_prev_runtime = runtime;
738			mtx_lock(&racct_lock);
739			racct_set_locked(p, RACCT_CPU, runtime);
740			racct_set_locked(p, RACCT_WALLCLOCK,
741			    wallclock.tv_sec * 1000000 + wallclock.tv_usec);
742			mtx_unlock(&racct_lock);
743			PROC_UNLOCK(p);
744		}
745		sx_sunlock(&allproc_lock);
746		pause("-", hz);
747	}
748}
749
750static struct kproc_desc racctd_kp = {
751	"racctd",
752	racctd,
753	NULL
754};
755SYSINIT(racctd, SI_SUB_RACCTD, SI_ORDER_FIRST, kproc_start, &racctd_kp);
756
757static void
758racct_init(void)
759{
760
761	racct_zone = uma_zcreate("racct", sizeof(struct racct),
762	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
763	/*
764	 * XXX: Move this somewhere.
765	 */
766	racct_create(&prison0.pr_racct);
767}
768SYSINIT(racct, SI_SUB_RACCT, SI_ORDER_FIRST, racct_init, NULL);
769
770#else /* !RACCT */
771
772int
773racct_add(struct proc *p, int resource, uint64_t amount)
774{
775
776	return (0);
777}
778
779void
780racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
781{
782}
783
784void
785racct_add_force(struct proc *p, int resource, uint64_t amount)
786{
787
788	return;
789}
790
791int
792racct_set(struct proc *p, int resource, uint64_t amount)
793{
794
795	return (0);
796}
797
798void
799racct_sub(struct proc *p, int resource, uint64_t amount)
800{
801}
802
803void
804racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
805{
806}
807
808uint64_t
809racct_get_limit(struct proc *p, int resource)
810{
811
812	return (UINT64_MAX);
813}
814
815void
816racct_create(struct racct **racctp)
817{
818}
819
820void
821racct_destroy(struct racct **racctp)
822{
823}
824
825int
826racct_proc_fork(struct proc *parent, struct proc *child)
827{
828
829	return (0);
830}
831
832void
833racct_proc_exit(struct proc *p)
834{
835}
836
837#endif /* !RACCT */
838