kern_racct.c revision 223844
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 223844 2011-07-07 17:44:42Z trasz $
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/kern/kern_racct.c 223844 2011-07-07 17:44:42Z 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_DATA] =
108		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
109	[RACCT_STACK] =
110		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
111	[RACCT_CORE] =
112		RACCT_DENIABLE,
113	[RACCT_RSS] =
114		RACCT_RECLAIMABLE,
115	[RACCT_MEMLOCK] =
116		RACCT_RECLAIMABLE | RACCT_DENIABLE,
117	[RACCT_NPROC] =
118		RACCT_RECLAIMABLE | RACCT_DENIABLE,
119	[RACCT_NOFILE] =
120		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
121	[RACCT_VMEM] =
122		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
123	[RACCT_NPTS] =
124		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
125	[RACCT_SWAP] =
126		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
127	[RACCT_NTHR] =
128		RACCT_RECLAIMABLE | RACCT_DENIABLE,
129	[RACCT_MSGQQUEUED] =
130		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
131	[RACCT_MSGQSIZE] =
132		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
133	[RACCT_NMSGQ] =
134		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
135	[RACCT_NSEM] =
136		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
137	[RACCT_NSEMOP] =
138		RACCT_RECLAIMABLE | RACCT_INHERITABLE | RACCT_DENIABLE,
139	[RACCT_NSHM] =
140		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
141	[RACCT_SHMSIZE] =
142		RACCT_RECLAIMABLE | RACCT_DENIABLE | RACCT_SLOPPY,
143	[RACCT_WALLCLOCK] =
144		RACCT_IN_THOUSANDS };
145
146static void
147racct_add_racct(struct racct *dest, const struct racct *src)
148{
149	int i;
150
151	mtx_assert(&racct_lock, MA_OWNED);
152
153	/*
154	 * Update resource usage in dest.
155	 */
156	for (i = 0; i <= RACCT_MAX; i++) {
157		KASSERT(dest->r_resources[i] >= 0,
158		    ("racct propagation meltdown: dest < 0"));
159		KASSERT(src->r_resources[i] >= 0,
160		    ("racct propagation meltdown: src < 0"));
161		dest->r_resources[i] += src->r_resources[i];
162	}
163}
164
165static void
166racct_sub_racct(struct racct *dest, const struct racct *src)
167{
168	int i;
169
170	mtx_assert(&racct_lock, MA_OWNED);
171
172	/*
173	 * Update resource usage in dest.
174	 */
175	for (i = 0; i <= RACCT_MAX; i++) {
176		if (!RACCT_IS_SLOPPY(i)) {
177			KASSERT(dest->r_resources[i] >= 0,
178			    ("racct propagation meltdown: dest < 0"));
179			KASSERT(src->r_resources[i] >= 0,
180			    ("racct propagation meltdown: src < 0"));
181			KASSERT(src->r_resources[i] <= dest->r_resources[i],
182			    ("racct propagation meltdown: src > dest"));
183		}
184		if (RACCT_IS_RECLAIMABLE(i)) {
185			dest->r_resources[i] -= src->r_resources[i];
186			if (dest->r_resources[i] < 0) {
187				KASSERT(RACCT_IS_SLOPPY(i),
188				    ("racct_sub_racct: usage < 0"));
189				dest->r_resources[i] = 0;
190			}
191		}
192	}
193}
194
195void
196racct_create(struct racct **racctp)
197{
198
199	SDT_PROBE(racct, kernel, racct, create, racctp, 0, 0, 0, 0);
200
201	KASSERT(*racctp == NULL, ("racct already allocated"));
202
203	*racctp = uma_zalloc(racct_zone, M_WAITOK | M_ZERO);
204}
205
206static void
207racct_destroy_locked(struct racct **racctp)
208{
209	int i;
210	struct racct *racct;
211
212	SDT_PROBE(racct, kernel, racct, destroy, racctp, 0, 0, 0, 0);
213
214	mtx_assert(&racct_lock, MA_OWNED);
215	KASSERT(racctp != NULL, ("NULL racctp"));
216	KASSERT(*racctp != NULL, ("NULL racct"));
217
218	racct = *racctp;
219
220	for (i = 0; i <= RACCT_MAX; i++) {
221		if (RACCT_IS_SLOPPY(i))
222			continue;
223		if (!RACCT_IS_RECLAIMABLE(i))
224			continue;
225		KASSERT(racct->r_resources[i] == 0,
226		    ("destroying non-empty racct: "
227		    "%ju allocated for resource %d\n",
228		    racct->r_resources[i], i));
229	}
230	uma_zfree(racct_zone, racct);
231	*racctp = NULL;
232}
233
234void
235racct_destroy(struct racct **racct)
236{
237
238	mtx_lock(&racct_lock);
239	racct_destroy_locked(racct);
240	mtx_unlock(&racct_lock);
241}
242
243/*
244 * Increase consumption of 'resource' by 'amount' for 'racct'
245 * and all its parents.  Differently from other cases, 'amount' here
246 * may be less than zero.
247 */
248static void
249racct_alloc_resource(struct racct *racct, int resource,
250    uint64_t amount)
251{
252
253	mtx_assert(&racct_lock, MA_OWNED);
254	KASSERT(racct != NULL, ("NULL racct"));
255
256	racct->r_resources[resource] += amount;
257	if (racct->r_resources[resource] < 0) {
258		KASSERT(RACCT_IS_SLOPPY(resource),
259		    ("racct_alloc_resource: usage < 0"));
260		racct->r_resources[resource] = 0;
261	}
262}
263
264/*
265 * Increase allocation of 'resource' by 'amount' for process 'p'.
266 * Return 0 if it's below limits, or errno, if it's not.
267 */
268int
269racct_add(struct proc *p, int resource, uint64_t amount)
270{
271#ifdef RCTL
272	int error;
273#endif
274
275	if (p->p_flag & P_SYSTEM)
276		return (0);
277
278	SDT_PROBE(racct, kernel, rusage, add, p, resource, amount, 0, 0);
279
280	/*
281	 * We need proc lock to dereference p->p_ucred.
282	 */
283	PROC_LOCK_ASSERT(p, MA_OWNED);
284
285	mtx_lock(&racct_lock);
286#ifdef RCTL
287	error = rctl_enforce(p, resource, amount);
288	if (error && RACCT_IS_DENIABLE(resource)) {
289		SDT_PROBE(racct, kernel, rusage, add_failure, p, resource,
290		    amount, 0, 0);
291		mtx_unlock(&racct_lock);
292		return (error);
293	}
294#endif
295	racct_alloc_resource(p->p_racct, resource, amount);
296	racct_add_cred_locked(p->p_ucred, resource, amount);
297	mtx_unlock(&racct_lock);
298
299	return (0);
300}
301
302static void
303racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount)
304{
305	struct prison *pr;
306
307	SDT_PROBE(racct, kernel, rusage, add_cred, cred, resource, amount,
308	    0, 0);
309
310	racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, amount);
311	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
312		racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource,
313		    amount);
314	racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, amount);
315}
316
317/*
318 * Increase allocation of 'resource' by 'amount' for credential 'cred'.
319 * Doesn't check for limits and never fails.
320 *
321 * XXX: Shouldn't this ever return an error?
322 */
323void
324racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
325{
326
327	mtx_lock(&racct_lock);
328	racct_add_cred_locked(cred, resource, amount);
329	mtx_unlock(&racct_lock);
330}
331
332/*
333 * Increase allocation of 'resource' by 'amount' for process 'p'.
334 * Doesn't check for limits and never fails.
335 */
336void
337racct_add_force(struct proc *p, int resource, uint64_t amount)
338{
339
340	if (p->p_flag & P_SYSTEM)
341		return;
342
343	SDT_PROBE(racct, kernel, rusage, add_force, p, resource, amount, 0, 0);
344
345	/*
346	 * We need proc lock to dereference p->p_ucred.
347	 */
348	PROC_LOCK_ASSERT(p, MA_OWNED);
349
350	mtx_lock(&racct_lock);
351	racct_alloc_resource(p->p_racct, resource, amount);
352	mtx_unlock(&racct_lock);
353	racct_add_cred(p->p_ucred, resource, amount);
354}
355
356static int
357racct_set_locked(struct proc *p, int resource, uint64_t amount)
358{
359	int64_t diff;
360#ifdef RCTL
361	int error;
362#endif
363
364	if (p->p_flag & P_SYSTEM)
365		return (0);
366
367	SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
368
369	/*
370	 * We need proc lock to dereference p->p_ucred.
371	 */
372	PROC_LOCK_ASSERT(p, MA_OWNED);
373
374	diff = amount - p->p_racct->r_resources[resource];
375#ifdef notyet
376	KASSERT(diff >= 0 || RACCT_IS_RECLAIMABLE(resource),
377	    ("racct_set: usage of non-reclaimable resource %d dropping",
378	     resource));
379#endif
380#ifdef RCTL
381	if (diff > 0) {
382		error = rctl_enforce(p, resource, diff);
383		if (error && RACCT_IS_DENIABLE(resource)) {
384			SDT_PROBE(racct, kernel, rusage, set_failure, p,
385			    resource, amount, 0, 0);
386			return (error);
387		}
388	}
389#endif
390	racct_alloc_resource(p->p_racct, resource, diff);
391	if (diff > 0)
392		racct_add_cred_locked(p->p_ucred, resource, diff);
393	else if (diff < 0)
394		racct_sub_cred_locked(p->p_ucred, resource, -diff);
395
396	return (0);
397}
398
399/*
400 * Set allocation of 'resource' to 'amount' for process 'p'.
401 * Return 0 if it's below limits, or errno, if it's not.
402 *
403 * Note that decreasing the allocation always returns 0,
404 * even if it's above the limit.
405 */
406int
407racct_set(struct proc *p, int resource, uint64_t amount)
408{
409	int error;
410
411	mtx_lock(&racct_lock);
412	error = racct_set_locked(p, resource, amount);
413	mtx_unlock(&racct_lock);
414	return (error);
415}
416
417void
418racct_set_force(struct proc *p, int resource, uint64_t amount)
419{
420	int64_t diff;
421
422	if (p->p_flag & P_SYSTEM)
423		return;
424
425	SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
426
427	/*
428	 * We need proc lock to dereference p->p_ucred.
429	 */
430	PROC_LOCK_ASSERT(p, MA_OWNED);
431
432	mtx_lock(&racct_lock);
433	diff = amount - p->p_racct->r_resources[resource];
434	racct_alloc_resource(p->p_racct, resource, diff);
435	if (diff > 0)
436		racct_add_cred_locked(p->p_ucred, resource, diff);
437	else if (diff < 0)
438		racct_sub_cred_locked(p->p_ucred, resource, -diff);
439	mtx_unlock(&racct_lock);
440}
441
442/*
443 * Returns amount of 'resource' the process 'p' can keep allocated.
444 * Allocating more than that would be denied, unless the resource
445 * is marked undeniable.  Amount of already allocated resource does
446 * not matter.
447 */
448uint64_t
449racct_get_limit(struct proc *p, int resource)
450{
451
452#ifdef RCTL
453	return (rctl_get_limit(p, resource));
454#else
455	return (UINT64_MAX);
456#endif
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 * matter.
464 */
465uint64_t
466racct_get_available(struct proc *p, int resource)
467{
468
469#ifdef RCTL
470	return (rctl_get_available(p, resource));
471#else
472	return (UINT64_MAX);
473#endif
474}
475
476/*
477 * Decrease allocation of 'resource' by 'amount' for process 'p'.
478 */
479void
480racct_sub(struct proc *p, int resource, uint64_t amount)
481{
482
483	if (p->p_flag & P_SYSTEM)
484		return;
485
486	SDT_PROBE(racct, kernel, rusage, sub, p, resource, amount, 0, 0);
487
488	/*
489	 * We need proc lock to dereference p->p_ucred.
490	 */
491	PROC_LOCK_ASSERT(p, MA_OWNED);
492	KASSERT(RACCT_IS_RECLAIMABLE(resource),
493	    ("racct_sub: called for non-reclaimable resource %d", resource));
494
495	mtx_lock(&racct_lock);
496	KASSERT(amount <= p->p_racct->r_resources[resource],
497	    ("racct_sub: freeing %ju of resource %d, which is more "
498	     "than allocated %jd for %s (pid %d)", amount, resource,
499	    (intmax_t)p->p_racct->r_resources[resource], p->p_comm, p->p_pid));
500
501	racct_alloc_resource(p->p_racct, resource, -amount);
502	racct_sub_cred_locked(p->p_ucred, resource, amount);
503	mtx_unlock(&racct_lock);
504}
505
506static void
507racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount)
508{
509	struct prison *pr;
510
511	SDT_PROBE(racct, kernel, rusage, sub_cred, cred, resource, amount,
512	    0, 0);
513
514#ifdef notyet
515	KASSERT(RACCT_IS_RECLAIMABLE(resource),
516	    ("racct_sub_cred: called for non-reclaimable resource %d",
517	     resource));
518#endif
519
520	racct_alloc_resource(cred->cr_ruidinfo->ui_racct, resource, -amount);
521	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
522		racct_alloc_resource(pr->pr_prison_racct->prr_racct, resource,
523		    -amount);
524	racct_alloc_resource(cred->cr_loginclass->lc_racct, resource, -amount);
525}
526
527/*
528 * Decrease allocation of 'resource' by 'amount' for credential 'cred'.
529 */
530void
531racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
532{
533
534	mtx_lock(&racct_lock);
535	racct_sub_cred_locked(cred, resource, amount);
536	mtx_unlock(&racct_lock);
537}
538
539/*
540 * Inherit resource usage information from the parent process.
541 */
542int
543racct_proc_fork(struct proc *parent, struct proc *child)
544{
545	int i, error = 0;
546
547	/*
548	 * Create racct for the child process.
549	 */
550	racct_create(&child->p_racct);
551
552	/*
553	 * No resource accounting for kernel processes.
554	 */
555	if (child->p_flag & P_SYSTEM)
556		return (0);
557
558	PROC_LOCK(parent);
559	PROC_LOCK(child);
560	mtx_lock(&racct_lock);
561
562	/*
563	 * Inherit resource usage.
564	 */
565	for (i = 0; i <= RACCT_MAX; i++) {
566		if (parent->p_racct->r_resources[i] == 0 ||
567		    !RACCT_IS_INHERITABLE(i))
568			continue;
569
570		error = racct_set_locked(child, i,
571		    parent->p_racct->r_resources[i]);
572		if (error != 0) {
573			/*
574			 * XXX: The only purpose of these two lines is
575			 * to prevent from tripping checks in racct_destroy().
576			 */
577			for (i = 0; i <= RACCT_MAX; i++)
578				racct_set_locked(child, i, 0);
579			goto out;
580		}
581	}
582
583#ifdef RCTL
584	error = rctl_proc_fork(parent, child);
585	if (error != 0) {
586		/*
587		 * XXX: The only purpose of these two lines is to prevent from
588		 * tripping checks in racct_destroy().
589		 */
590		for (i = 0; i <= RACCT_MAX; i++)
591			racct_set_locked(child, i, 0);
592	}
593#endif
594
595out:
596	if (error != 0)
597		racct_destroy_locked(&child->p_racct);
598	mtx_unlock(&racct_lock);
599	PROC_UNLOCK(child);
600	PROC_UNLOCK(parent);
601
602	return (error);
603}
604
605void
606racct_proc_exit(struct proc *p)
607{
608	uint64_t runtime;
609
610	PROC_LOCK(p);
611	/*
612	 * We don't need to calculate rux, proc_reap() has already done this.
613	 */
614	runtime = cputick2usec(p->p_rux.rux_runtime);
615#ifdef notyet
616	KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime"));
617#else
618	if (runtime < p->p_prev_runtime)
619		runtime = p->p_prev_runtime;
620#endif
621	racct_set(p, RACCT_CPU, runtime);
622
623	/*
624	 * XXX: Free this some other way.
625	 */
626	racct_set(p, RACCT_NPTS, 0);
627	racct_set(p, RACCT_NTHR, 0);
628	racct_set(p, RACCT_RSS, 0);
629	PROC_UNLOCK(p);
630
631#ifdef RCTL
632	rctl_racct_release(p->p_racct);
633#endif
634	racct_destroy(&p->p_racct);
635}
636
637/*
638 * Called after credentials change, to move resource utilisation
639 * between raccts.
640 */
641void
642racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
643    struct ucred *newcred)
644{
645	struct uidinfo *olduip, *newuip;
646	struct loginclass *oldlc, *newlc;
647	struct prison *oldpr, *newpr, *pr;
648
649	PROC_LOCK_ASSERT(p, MA_NOTOWNED);
650
651	newuip = newcred->cr_ruidinfo;
652	olduip = oldcred->cr_ruidinfo;
653	newlc = newcred->cr_loginclass;
654	oldlc = oldcred->cr_loginclass;
655	newpr = newcred->cr_prison;
656	oldpr = oldcred->cr_prison;
657
658	mtx_lock(&racct_lock);
659	if (newuip != olduip) {
660		racct_sub_racct(olduip->ui_racct, p->p_racct);
661		racct_add_racct(newuip->ui_racct, p->p_racct);
662	}
663	if (newlc != oldlc) {
664		racct_sub_racct(oldlc->lc_racct, p->p_racct);
665		racct_add_racct(newlc->lc_racct, p->p_racct);
666	}
667	if (newpr != oldpr) {
668		for (pr = oldpr; pr != NULL; pr = pr->pr_parent)
669			racct_sub_racct(pr->pr_prison_racct->prr_racct,
670			    p->p_racct);
671		for (pr = newpr; pr != NULL; pr = pr->pr_parent)
672			racct_add_racct(pr->pr_prison_racct->prr_racct,
673			    p->p_racct);
674	}
675	mtx_unlock(&racct_lock);
676
677#ifdef RCTL
678	rctl_proc_ucred_changed(p, newcred);
679#endif
680}
681
682static void
683racctd(void)
684{
685	struct thread *td;
686	struct proc *p;
687	struct timeval wallclock;
688	uint64_t runtime;
689
690	for (;;) {
691		sx_slock(&allproc_lock);
692
693		FOREACH_PROC_IN_SYSTEM(p) {
694			if (p->p_state != PRS_NORMAL)
695				continue;
696			if (p->p_flag & P_SYSTEM)
697				continue;
698
699			microuptime(&wallclock);
700			timevalsub(&wallclock, &p->p_stats->p_start);
701			PROC_LOCK(p);
702			PROC_SLOCK(p);
703			FOREACH_THREAD_IN_PROC(p, td) {
704				ruxagg(p, td);
705				thread_lock(td);
706				thread_unlock(td);
707			}
708			runtime = cputick2usec(p->p_rux.rux_runtime);
709			PROC_SUNLOCK(p);
710#ifdef notyet
711			KASSERT(runtime >= p->p_prev_runtime,
712			    ("runtime < p_prev_runtime"));
713#else
714			if (runtime < p->p_prev_runtime)
715				runtime = p->p_prev_runtime;
716#endif
717			p->p_prev_runtime = runtime;
718			mtx_lock(&racct_lock);
719			racct_set_locked(p, RACCT_CPU, runtime);
720			racct_set_locked(p, RACCT_WALLCLOCK,
721			    wallclock.tv_sec * 1000000 + wallclock.tv_usec);
722			mtx_unlock(&racct_lock);
723			PROC_UNLOCK(p);
724		}
725		sx_sunlock(&allproc_lock);
726		pause("-", hz);
727	}
728}
729
730static struct kproc_desc racctd_kp = {
731	"racctd",
732	racctd,
733	NULL
734};
735SYSINIT(racctd, SI_SUB_RACCTD, SI_ORDER_FIRST, kproc_start, &racctd_kp);
736
737static void
738racct_init(void)
739{
740
741	racct_zone = uma_zcreate("racct", sizeof(struct racct),
742	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
743	/*
744	 * XXX: Move this somewhere.
745	 */
746	prison0.pr_prison_racct = prison_racct_find("0");
747}
748SYSINIT(racct, SI_SUB_RACCT, SI_ORDER_FIRST, racct_init, NULL);
749
750#else /* !RACCT */
751
752int
753racct_add(struct proc *p, int resource, uint64_t amount)
754{
755
756	return (0);
757}
758
759void
760racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
761{
762}
763
764void
765racct_add_force(struct proc *p, int resource, uint64_t amount)
766{
767
768	return;
769}
770
771int
772racct_set(struct proc *p, int resource, uint64_t amount)
773{
774
775	return (0);
776}
777
778void
779racct_set_force(struct proc *p, int resource, uint64_t amount)
780{
781}
782
783void
784racct_sub(struct proc *p, int resource, uint64_t amount)
785{
786}
787
788void
789racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
790{
791}
792
793uint64_t
794racct_get_limit(struct proc *p, int resource)
795{
796
797	return (UINT64_MAX);
798}
799
800uint64_t
801racct_get_available(struct proc *p, int resource)
802{
803
804	return (UINT64_MAX);
805}
806
807void
808racct_create(struct racct **racctp)
809{
810}
811
812void
813racct_destroy(struct racct **racctp)
814{
815}
816
817int
818racct_proc_fork(struct proc *parent, struct proc *child)
819{
820
821	return (0);
822}
823
824void
825racct_proc_exit(struct proc *p)
826{
827}
828
829#endif /* !RACCT */
830