Deleted Added
sdiff udiff text old ( 298330 ) new ( 298414 )
full compact
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

--- 12 unchanged lines hidden (view full) ---

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_rctl.c 298330 2016-04-20 02:09:38Z cem $
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/kern/kern_rctl.c 298330 2016-04-20 02:09:38Z cem $");
34
35#include <sys/param.h>
36#include <sys/bus.h>
37#include <sys/malloc.h>
38#include <sys/queue.h>
39#include <sys/refcount.h>
40#include <sys/jail.h>
41#include <sys/kernel.h>

--- 165 unchanged lines hidden (view full) ---

207 { "throttle", RCTL_ACTION_THROTTLE },
208 { NULL, -1 }};
209
210static void rctl_init(void);
211SYSINIT(rctl, SI_SUB_RACCT, SI_ORDER_FIRST, rctl_init, NULL);
212
213static uma_zone_t rctl_rule_zone;
214static uma_zone_t rctl_rule_link_zone;
215static struct rwlock rctl_lock;
216RW_SYSINIT(rctl_lock, &rctl_lock, "RCTL lock");
217
218#define RCTL_RLOCK() rw_rlock(&rctl_lock)
219#define RCTL_RUNLOCK() rw_runlock(&rctl_lock)
220#define RCTL_WLOCK() rw_wlock(&rctl_lock)
221#define RCTL_WUNLOCK() rw_wunlock(&rctl_lock)
222#define RCTL_LOCK_ASSERT() rw_assert(&rctl_lock, RA_LOCKED)
223#define RCTL_WLOCK_ASSERT() rw_assert(&rctl_lock, RA_WLOCKED)
224
225static int rctl_rule_fully_specified(const struct rctl_rule *rule);
226static void rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule);
227
228static MALLOC_DEFINE(M_RCTL, "rctl", "Resource Limits");
229
230static int rctl_throttle_min_sysctl(SYSCTL_HANDLER_ARGS)
231{
232 int error, val = rctl_throttle_min;
233
234 error = sysctl_handle_int(oidp, &val, 0, req);
235 if (error || !req->newptr)
236 return (error);
237 if (val < 1 || val > rctl_throttle_max)
238 return (EINVAL);
239
240 RCTL_WLOCK();
241 rctl_throttle_min = val;
242 RCTL_WUNLOCK();
243
244 return (0);
245}
246
247static int rctl_throttle_max_sysctl(SYSCTL_HANDLER_ARGS)
248{
249 int error, val = rctl_throttle_max;
250
251 error = sysctl_handle_int(oidp, &val, 0, req);
252 if (error || !req->newptr)
253 return (error);
254 if (val < rctl_throttle_min)
255 return (EINVAL);
256
257 RCTL_WLOCK();
258 rctl_throttle_max = val;
259 RCTL_WUNLOCK();
260
261 return (0);
262}
263
264static int rctl_throttle_pct_sysctl(SYSCTL_HANDLER_ARGS)
265{
266 int error, val = rctl_throttle_pct;
267
268 error = sysctl_handle_int(oidp, &val, 0, req);
269 if (error || !req->newptr)
270 return (error);
271 if (val < 0)
272 return (EINVAL);
273
274 RCTL_WLOCK();
275 rctl_throttle_pct = val;
276 RCTL_WUNLOCK();
277
278 return (0);
279}
280
281static int rctl_throttle_pct2_sysctl(SYSCTL_HANDLER_ARGS)
282{
283 int error, val = rctl_throttle_pct2;
284
285 error = sysctl_handle_int(oidp, &val, 0, req);
286 if (error || !req->newptr)
287 return (error);
288 if (val < 0)
289 return (EINVAL);
290
291 RCTL_WLOCK();
292 rctl_throttle_pct2 = val;
293 RCTL_WUNLOCK();
294
295 return (0);
296}
297
298static const char *
299rctl_subject_type_name(int subject)
300{
301 int i;

--- 33 unchanged lines hidden (view full) ---

335}
336
337static struct racct *
338rctl_proc_rule_to_racct(const struct proc *p, const struct rctl_rule *rule)
339{
340 struct ucred *cred = p->p_ucred;
341
342 ASSERT_RACCT_ENABLED();
343 RCTL_LOCK_ASSERT();
344
345 switch (rule->rr_per) {
346 case RCTL_SUBJECT_TYPE_PROCESS:
347 return (p->p_racct);
348 case RCTL_SUBJECT_TYPE_USER:
349 return (cred->cr_ruidinfo->ui_racct);
350 case RCTL_SUBJECT_TYPE_LOGINCLASS:
351 return (cred->cr_loginclass->lc_racct);

--- 10 unchanged lines hidden (view full) ---

362 */
363static int64_t
364rctl_available_resource(const struct proc *p, const struct rctl_rule *rule)
365{
366 const struct racct *racct;
367 int64_t available;
368
369 ASSERT_RACCT_ENABLED();
370 RCTL_LOCK_ASSERT();
371
372 racct = rctl_proc_rule_to_racct(p, rule);
373 available = rule->rr_amount - racct->r_resources[rule->rr_resource];
374
375 return (available);
376}
377
378/*

--- 6 unchanged lines hidden (view full) ---

385void
386rctl_throttle_decay(struct racct *racct, int resource)
387{
388 struct rctl_rule *rule;
389 struct rctl_rule_link *link;
390 int64_t minavailable;
391
392 ASSERT_RACCT_ENABLED();
393
394 minavailable = INT64_MAX;
395
396 RCTL_RLOCK();
397
398 LIST_FOREACH(link, &racct->r_rule_links, rrl_next) {
399 rule = link->rrl_rule;
400
401 if (rule->rr_resource != resource)
402 continue;
403 if (rule->rr_action != RCTL_ACTION_THROTTLE)
404 continue;
405
406 if (rule->rr_amount < minavailable)
407 minavailable = rule->rr_amount;
408 }
409
410 RCTL_RUNLOCK();
411
412 if (racct->r_resources[resource] < minavailable) {
413 racct->r_resources[resource] = 0;
414 } else {
415 /*
416 * Cap utilization counter at ten times the limit. Otherwise,
417 * if we changed the rule lowering the allowed amount, it could
418 * take unreasonably long time for the accumulated resource
419 * usage to drop.

--- 11 unchanged lines hidden (view full) ---

431 */
432int64_t
433rctl_pcpu_available(const struct proc *p) {
434 struct rctl_rule *rule;
435 struct rctl_rule_link *link;
436 int64_t available, minavailable, limit;
437
438 ASSERT_RACCT_ENABLED();
439
440 minavailable = INT64_MAX;
441 limit = 0;
442
443 RCTL_RLOCK();
444
445 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
446 rule = link->rrl_rule;
447 if (rule->rr_resource != RACCT_PCTCPU)
448 continue;
449 if (rule->rr_action != RCTL_ACTION_DENY)
450 continue;
451 available = rctl_available_resource(p, rule);
452 if (available < minavailable) {
453 minavailable = available;
454 limit = rule->rr_amount;
455 }
456 }
457
458 RCTL_RUNLOCK();
459
460 /*
461 * Return slightly less than actual value of the available
462 * %cpu resource. This makes %cpu throttling more agressive
463 * and lets us act sooner than the limits are already exceeded.
464 */
465 if (limit != 0) {
466 if (limit > 2 * RCTL_PCPU_SHIFT)
467 minavailable -= RCTL_PCPU_SHIFT;

--- 43 unchanged lines hidden (view full) ---

511 struct rctl_rule *rule;
512 struct rctl_rule_link *link;
513 struct sbuf sb;
514 char *buf;
515 int64_t available;
516 uint64_t sleep_ms, sleep_ratio;
517 int should_deny = 0;
518
519
520 ASSERT_RACCT_ENABLED();
521
522 RCTL_RLOCK();
523
524 /*
525 * There may be more than one matching rule; go through all of them.
526 * Denial should be done last, after logging and sending signals.
527 */
528 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
529 rule = link->rrl_rule;
530 if (rule->rr_resource != resource)
531 continue;

--- 156 unchanged lines hidden (view full) ---

688 * are equal to their counterparts from sys/signal.h.
689 */
690 kern_psignal(p, rule->rr_action);
691 link->rrl_exceeded = 1;
692 continue;
693 }
694 }
695
696 RCTL_RUNLOCK();
697
698 if (should_deny) {
699 /*
700 * Return fake error code; the caller should change it
701 * into one proper for the situation - EFSIZ, ENOMEM etc.
702 */
703 return (EDOOFUS);
704 }
705
706 return (0);
707}
708
709uint64_t
710rctl_get_limit(struct proc *p, int resource)
711{
712 struct rctl_rule *rule;
713 struct rctl_rule_link *link;
714 uint64_t amount = UINT64_MAX;
715
716 ASSERT_RACCT_ENABLED();
717
718 RCTL_RLOCK();
719
720 /*
721 * There may be more than one matching rule; go through all of them.
722 * Denial should be done last, after logging and sending signals.
723 */
724 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
725 rule = link->rrl_rule;
726 if (rule->rr_resource != resource)
727 continue;
728 if (rule->rr_action != RCTL_ACTION_DENY)
729 continue;
730 if (rule->rr_amount < amount)
731 amount = rule->rr_amount;
732 }
733
734 RCTL_RUNLOCK();
735
736 return (amount);
737}
738
739uint64_t
740rctl_get_available(struct proc *p, int resource)
741{
742 struct rctl_rule *rule;
743 struct rctl_rule_link *link;
744 int64_t available, minavailable, allocated;
745
746 minavailable = INT64_MAX;
747
748 ASSERT_RACCT_ENABLED();
749
750 RCTL_RLOCK();
751
752 /*
753 * There may be more than one matching rule; go through all of them.
754 * Denial should be done last, after logging and sending signals.
755 */
756 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
757 rule = link->rrl_rule;
758 if (rule->rr_resource != resource)
759 continue;
760 if (rule->rr_action != RCTL_ACTION_DENY)
761 continue;
762 available = rctl_available_resource(p, rule);
763 if (available < minavailable)
764 minavailable = available;
765 }
766
767 RCTL_RUNLOCK();
768
769 /*
770 * XXX: Think about this _hard_.
771 */
772 allocated = p->p_racct->r_resources[resource];
773 if (minavailable < INT64_MAX - allocated)
774 minavailable += allocated;
775 if (minavailable < 0)
776 minavailable = 0;
777 return (minavailable);
778}
779
780static int
781rctl_rule_matches(const struct rctl_rule *rule, const struct rctl_rule *filter)
782{
783
784 ASSERT_RACCT_ENABLED();

--- 118 unchanged lines hidden (view full) ---

903 ASSERT_RACCT_ENABLED();
904 KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified"));
905
906 rctl_rule_acquire(rule);
907 link = uma_zalloc(rctl_rule_link_zone, M_WAITOK);
908 link->rrl_rule = rule;
909 link->rrl_exceeded = 0;
910
911 RCTL_WLOCK();
912 LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next);
913 RCTL_WUNLOCK();
914}
915
916static int
917rctl_racct_add_rule_locked(struct racct *racct, struct rctl_rule *rule)
918{
919 struct rctl_rule_link *link;
920
921 ASSERT_RACCT_ENABLED();
922 KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified"));
923 RCTL_WLOCK_ASSERT();
924
925 link = uma_zalloc(rctl_rule_link_zone, M_NOWAIT);
926 if (link == NULL)
927 return (ENOMEM);
928 rctl_rule_acquire(rule);
929 link->rrl_rule = rule;
930 link->rrl_exceeded = 0;
931
932 LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next);
933 return (0);
934}
935
936/*
937 * Remove limits for a rules matching the filter and release
938 * the refcounts for the rules, possibly freeing them. Returns
939 * the number of limit structures removed.
940 */
941static int
942rctl_racct_remove_rules(struct racct *racct,
943 const struct rctl_rule *filter)
944{
945 struct rctl_rule_link *link, *linktmp;
946 int removed = 0;
947
948 ASSERT_RACCT_ENABLED();
949 RCTL_WLOCK_ASSERT();
950
951 LIST_FOREACH_SAFE(link, &racct->r_rule_links, rrl_next, linktmp) {
952 if (!rctl_rule_matches(link->rrl_rule, filter))
953 continue;
954
955 LIST_REMOVE(link, rrl_next);
956 rctl_rule_release(link->rrl_rule);
957 uma_zfree(rctl_rule_link_zone, link);

--- 454 unchanged lines hidden (view full) ---

1412
1413 return (0);
1414}
1415
1416static void
1417rctl_rule_pre_callback(void)
1418{
1419
1420 RCTL_WLOCK();
1421}
1422
1423static void
1424rctl_rule_post_callback(void)
1425{
1426
1427 RCTL_WUNLOCK();
1428}
1429
1430static void
1431rctl_rule_remove_callback(struct racct *racct, void *arg2, void *arg3)
1432{
1433 struct rctl_rule *filter = (struct rctl_rule *)arg2;
1434 int found = 0;
1435
1436 ASSERT_RACCT_ENABLED();
1437 RCTL_WLOCK_ASSERT();
1438
1439 found += rctl_racct_remove_rules(racct, filter);
1440
1441 *((int *)arg3) += found;
1442}
1443
1444/*
1445 * Remove all rules that match the filter.

--- 4 unchanged lines hidden (view full) ---

1450 struct proc *p;
1451 int found = 0;
1452
1453 ASSERT_RACCT_ENABLED();
1454
1455 if (filter->rr_subject_type == RCTL_SUBJECT_TYPE_PROCESS &&
1456 filter->rr_subject.rs_proc != NULL) {
1457 p = filter->rr_subject.rs_proc;
1458 RCTL_WLOCK();
1459 found = rctl_racct_remove_rules(p->p_racct, filter);
1460 RCTL_WUNLOCK();
1461 if (found)
1462 return (0);
1463 return (ESRCH);
1464 }
1465
1466 loginclass_racct_foreach(rctl_rule_remove_callback,
1467 rctl_rule_pre_callback, rctl_rule_post_callback,
1468 filter, (void *)&found);
1469 ui_racct_foreach(rctl_rule_remove_callback,
1470 rctl_rule_pre_callback, rctl_rule_post_callback,
1471 filter, (void *)&found);
1472 prison_racct_foreach(rctl_rule_remove_callback,
1473 rctl_rule_pre_callback, rctl_rule_post_callback,
1474 filter, (void *)&found);
1475
1476 sx_assert(&allproc_lock, SA_LOCKED);
1477 RCTL_WLOCK();
1478 FOREACH_PROC_IN_SYSTEM(p) {
1479 found += rctl_racct_remove_rules(p->p_racct, filter);
1480 }
1481 RCTL_WUNLOCK();
1482
1483 if (found)
1484 return (0);
1485 return (ESRCH);
1486}
1487
1488/*
1489 * Appends a rule to the sbuf.

--- 115 unchanged lines hidden (view full) ---

1605 int i;
1606
1607 ASSERT_RACCT_ENABLED();
1608
1609 sb = sbuf_new_auto();
1610 for (i = 0; i <= RACCT_MAX; i++) {
1611 if (sloppy == 0 && RACCT_IS_SLOPPY(i))
1612 continue;
1613 amount = racct->r_resources[i];
1614 if (RACCT_IS_IN_MILLIONS(i))
1615 amount /= 1000000;
1616 sbuf_printf(sb, "%s=%jd,", rctl_resource_name(i), amount);
1617 }
1618 sbuf_setpos(sb, sbuf_len(sb) - 1);
1619 return (sb);
1620}
1621

--- 78 unchanged lines hidden (view full) ---

1700static void
1701rctl_get_rules_callback(struct racct *racct, void *arg2, void *arg3)
1702{
1703 struct rctl_rule *filter = (struct rctl_rule *)arg2;
1704 struct rctl_rule_link *link;
1705 struct sbuf *sb = (struct sbuf *)arg3;
1706
1707 ASSERT_RACCT_ENABLED();
1708 RCTL_LOCK_ASSERT();
1709
1710 LIST_FOREACH(link, &racct->r_rule_links, rrl_next) {
1711 if (!rctl_rule_matches(link->rrl_rule, filter))
1712 continue;
1713 rctl_rule_to_sbuf(sb, link->rrl_rule);
1714 sbuf_printf(sb, ",");
1715 }
1716}

--- 34 unchanged lines hidden (view full) ---

1751 return (E2BIG);
1752 }
1753
1754 buf = malloc(bufsize, M_RCTL, M_WAITOK);
1755 sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN);
1756 KASSERT(sb != NULL, ("sbuf_new failed"));
1757
1758 FOREACH_PROC_IN_SYSTEM(p) {
1759 RCTL_RLOCK();
1760 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
1761 /*
1762 * Non-process rules will be added to the buffer later.
1763 * Adding them here would result in duplicated output.
1764 */
1765 if (link->rrl_rule->rr_subject_type !=
1766 RCTL_SUBJECT_TYPE_PROCESS)
1767 continue;
1768 if (!rctl_rule_matches(link->rrl_rule, filter))
1769 continue;
1770 rctl_rule_to_sbuf(sb, link->rrl_rule);
1771 sbuf_printf(sb, ",");
1772 }
1773 RCTL_RUNLOCK();
1774 }
1775
1776 loginclass_racct_foreach(rctl_get_rules_callback,
1777 rctl_rule_pre_callback, rctl_rule_post_callback,
1778 filter, sb);
1779 ui_racct_foreach(rctl_get_rules_callback,
1780 rctl_rule_pre_callback, rctl_rule_post_callback,
1781 filter, sb);

--- 70 unchanged lines hidden (view full) ---

1852 sx_sunlock(&allproc_lock);
1853 return (E2BIG);
1854 }
1855
1856 buf = malloc(bufsize, M_RCTL, M_WAITOK);
1857 sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN);
1858 KASSERT(sb != NULL, ("sbuf_new failed"));
1859
1860 RCTL_RLOCK();
1861 LIST_FOREACH(link, &filter->rr_subject.rs_proc->p_racct->r_rule_links,
1862 rrl_next) {
1863 rctl_rule_to_sbuf(sb, link->rrl_rule);
1864 sbuf_printf(sb, ",");
1865 }
1866 RCTL_RUNLOCK();
1867 if (sbuf_error(sb) == ENOMEM) {
1868 error = ERANGE;
1869 sbuf_delete(sb);
1870 goto out;
1871 }
1872
1873 /*
1874 * Remove trailing ",".

--- 109 unchanged lines hidden (view full) ---

1984 LIST_INIT(&newrules);
1985
1986again:
1987 /*
1988 * First, count the rules that apply to the process with new
1989 * credentials.
1990 */
1991 rulecnt = 0;
1992 RCTL_RLOCK();
1993 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
1994 if (link->rrl_rule->rr_subject_type ==
1995 RCTL_SUBJECT_TYPE_PROCESS)
1996 rulecnt++;
1997 }
1998 LIST_FOREACH(link, &newuip->ui_racct->r_rule_links, rrl_next)
1999 rulecnt++;
2000 LIST_FOREACH(link, &newlc->lc_racct->r_rule_links, rrl_next)
2001 rulecnt++;
2002 LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next)
2003 rulecnt++;
2004 RCTL_RUNLOCK();
2005
2006 /*
2007 * Create temporary list. We've dropped the rctl_lock in order
2008 * to use M_WAITOK.
2009 */
2010 for (i = 0; i < rulecnt; i++) {
2011 newlink = uma_zalloc(rctl_rule_link_zone, M_WAITOK);
2012 newlink->rrl_rule = NULL;
2013 newlink->rrl_exceeded = 0;
2014 LIST_INSERT_HEAD(&newrules, newlink, rrl_next);
2015 }
2016
2017 newlink = LIST_FIRST(&newrules);
2018
2019 /*
2020 * Assign rules to the newly allocated list entries.
2021 */
2022 RCTL_WLOCK();
2023 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
2024 if (link->rrl_rule->rr_subject_type ==
2025 RCTL_SUBJECT_TYPE_PROCESS) {
2026 if (newlink == NULL)
2027 goto goaround;
2028 rctl_rule_acquire(link->rrl_rule);
2029 newlink->rrl_rule = link->rrl_rule;
2030 newlink->rrl_exceeded = link->rrl_exceeded;

--- 51 unchanged lines hidden (view full) ---

2082 */
2083 while (!LIST_EMPTY(&newrules)) {
2084 newlink = LIST_FIRST(&newrules);
2085 LIST_REMOVE(newlink, rrl_next);
2086 LIST_INSERT_HEAD(&p->p_racct->r_rule_links,
2087 newlink, rrl_next);
2088 }
2089
2090 RCTL_WUNLOCK();
2091
2092 return;
2093 }
2094
2095goaround:
2096 RCTL_WUNLOCK();
2097
2098 /*
2099 * Rule list changed while we were not holding the rctl_lock.
2100 * Free the new list and try again.
2101 */
2102 while (!LIST_EMPTY(&newrules)) {
2103 newlink = LIST_FIRST(&newrules);
2104 LIST_REMOVE(newlink, rrl_next);

--- 10 unchanged lines hidden (view full) ---

2115 */
2116int
2117rctl_proc_fork(struct proc *parent, struct proc *child)
2118{
2119 struct rctl_rule *rule;
2120 struct rctl_rule_link *link;
2121 int error;
2122
2123 LIST_INIT(&child->p_racct->r_rule_links);
2124
2125 ASSERT_RACCT_ENABLED();
2126 KASSERT(parent->p_racct != NULL, ("process without racct; p = %p", parent));
2127
2128 RCTL_WLOCK();
2129
2130 /*
2131 * Go through limits applicable to the parent and assign them
2132 * to the child. Rules with 'process' subject have to be duplicated
2133 * in order to make their rr_subject point to the new process.
2134 */
2135 LIST_FOREACH(link, &parent->p_racct->r_rule_links, rrl_next) {
2136 if (link->rrl_rule->rr_subject_type ==

--- 12 unchanged lines hidden (view full) ---

2149 } else {
2150 error = rctl_racct_add_rule_locked(child->p_racct,
2151 link->rrl_rule);
2152 if (error != 0)
2153 goto fail;
2154 }
2155 }
2156
2157 RCTL_WUNLOCK();
2158 return (0);
2159
2160fail:
2161 while (!LIST_EMPTY(&child->p_racct->r_rule_links)) {
2162 link = LIST_FIRST(&child->p_racct->r_rule_links);
2163 LIST_REMOVE(link, rrl_next);
2164 rctl_rule_release(link->rrl_rule);
2165 uma_zfree(rctl_rule_link_zone, link);
2166 }
2167 RCTL_WUNLOCK();
2168 return (EAGAIN);
2169}
2170
2171/*
2172 * Release rules attached to the racct.
2173 */
2174void
2175rctl_racct_release(struct racct *racct)
2176{
2177 struct rctl_rule_link *link;
2178
2179 ASSERT_RACCT_ENABLED();
2180
2181 RCTL_WLOCK();
2182 while (!LIST_EMPTY(&racct->r_rule_links)) {
2183 link = LIST_FIRST(&racct->r_rule_links);
2184 LIST_REMOVE(link, rrl_next);
2185 rctl_rule_release(link->rrl_rule);
2186 uma_zfree(rctl_rule_link_zone, link);
2187 }
2188 RCTL_WUNLOCK();
2189}
2190
2191static void
2192rctl_init(void)
2193{
2194
2195 if (!racct_enable)
2196 return;

--- 61 unchanged lines hidden ---