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 298414 2016-04-21 16:22:52Z trasz $ |
30 */ 31 32#include <sys/cdefs.h> |
33__FBSDID("$FreeBSD: head/sys/kern/kern_rctl.c 298414 2016-04-21 16:22:52Z trasz $"); |
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; |
215 |
216static int rctl_rule_fully_specified(const struct rctl_rule *rule); 217static void rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule); 218 219static MALLOC_DEFINE(M_RCTL, "rctl", "Resource Limits"); 220 221static int rctl_throttle_min_sysctl(SYSCTL_HANDLER_ARGS) 222{ 223 int error, val = rctl_throttle_min; 224 225 error = sysctl_handle_int(oidp, &val, 0, req); 226 if (error || !req->newptr) 227 return (error); 228 if (val < 1 || val > rctl_throttle_max) 229 return (EINVAL); 230 |
231 RACCT_LOCK(); |
232 rctl_throttle_min = val; |
233 RACCT_UNLOCK(); |
234 235 return (0); 236} 237 238static int rctl_throttle_max_sysctl(SYSCTL_HANDLER_ARGS) 239{ 240 int error, val = rctl_throttle_max; 241 242 error = sysctl_handle_int(oidp, &val, 0, req); 243 if (error || !req->newptr) 244 return (error); 245 if (val < rctl_throttle_min) 246 return (EINVAL); 247 |
248 RACCT_LOCK(); |
249 rctl_throttle_max = val; |
250 RACCT_UNLOCK(); |
251 252 return (0); 253} 254 255static int rctl_throttle_pct_sysctl(SYSCTL_HANDLER_ARGS) 256{ 257 int error, val = rctl_throttle_pct; 258 259 error = sysctl_handle_int(oidp, &val, 0, req); 260 if (error || !req->newptr) 261 return (error); 262 if (val < 0) 263 return (EINVAL); 264 |
265 RACCT_LOCK(); |
266 rctl_throttle_pct = val; |
267 RACCT_UNLOCK(); |
268 269 return (0); 270} 271 272static int rctl_throttle_pct2_sysctl(SYSCTL_HANDLER_ARGS) 273{ 274 int error, val = rctl_throttle_pct2; 275 276 error = sysctl_handle_int(oidp, &val, 0, req); 277 if (error || !req->newptr) 278 return (error); 279 if (val < 0) 280 return (EINVAL); 281 |
282 RACCT_LOCK(); |
283 rctl_throttle_pct2 = val; |
284 RACCT_UNLOCK(); |
285 286 return (0); 287} 288 289static const char * 290rctl_subject_type_name(int subject) 291{ 292 int i; --- 33 unchanged lines hidden (view full) --- 326} 327 328static struct racct * 329rctl_proc_rule_to_racct(const struct proc *p, const struct rctl_rule *rule) 330{ 331 struct ucred *cred = p->p_ucred; 332 333 ASSERT_RACCT_ENABLED(); |
334 RACCT_LOCK_ASSERT(); |
335 336 switch (rule->rr_per) { 337 case RCTL_SUBJECT_TYPE_PROCESS: 338 return (p->p_racct); 339 case RCTL_SUBJECT_TYPE_USER: 340 return (cred->cr_ruidinfo->ui_racct); 341 case RCTL_SUBJECT_TYPE_LOGINCLASS: 342 return (cred->cr_loginclass->lc_racct); --- 10 unchanged lines hidden (view full) --- 353 */ 354static int64_t 355rctl_available_resource(const struct proc *p, const struct rctl_rule *rule) 356{ 357 const struct racct *racct; 358 int64_t available; 359 360 ASSERT_RACCT_ENABLED(); |
361 RACCT_LOCK_ASSERT(); |
362 363 racct = rctl_proc_rule_to_racct(p, rule); 364 available = rule->rr_amount - racct->r_resources[rule->rr_resource]; 365 366 return (available); 367} 368 369/* --- 6 unchanged lines hidden (view full) --- 376void 377rctl_throttle_decay(struct racct *racct, int resource) 378{ 379 struct rctl_rule *rule; 380 struct rctl_rule_link *link; 381 int64_t minavailable; 382 383 ASSERT_RACCT_ENABLED(); |
384 RACCT_LOCK_ASSERT(); |
385 386 minavailable = INT64_MAX; 387 |
388 LIST_FOREACH(link, &racct->r_rule_links, rrl_next) { 389 rule = link->rrl_rule; 390 391 if (rule->rr_resource != resource) 392 continue; 393 if (rule->rr_action != RCTL_ACTION_THROTTLE) 394 continue; 395 396 if (rule->rr_amount < minavailable) 397 minavailable = rule->rr_amount; 398 } 399 |
400 if (racct->r_resources[resource] < minavailable) { 401 racct->r_resources[resource] = 0; 402 } else { 403 /* 404 * Cap utilization counter at ten times the limit. Otherwise, 405 * if we changed the rule lowering the allowed amount, it could 406 * take unreasonably long time for the accumulated resource 407 * usage to drop. --- 11 unchanged lines hidden (view full) --- 419 */ 420int64_t 421rctl_pcpu_available(const struct proc *p) { 422 struct rctl_rule *rule; 423 struct rctl_rule_link *link; 424 int64_t available, minavailable, limit; 425 426 ASSERT_RACCT_ENABLED(); |
427 RACCT_LOCK_ASSERT(); |
428 429 minavailable = INT64_MAX; 430 limit = 0; 431 |
432 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 433 rule = link->rrl_rule; 434 if (rule->rr_resource != RACCT_PCTCPU) 435 continue; 436 if (rule->rr_action != RCTL_ACTION_DENY) 437 continue; 438 available = rctl_available_resource(p, rule); 439 if (available < minavailable) { 440 minavailable = available; 441 limit = rule->rr_amount; 442 } 443 } 444 |
445 /* 446 * Return slightly less than actual value of the available 447 * %cpu resource. This makes %cpu throttling more agressive 448 * and lets us act sooner than the limits are already exceeded. 449 */ 450 if (limit != 0) { 451 if (limit > 2 * RCTL_PCPU_SHIFT) 452 minavailable -= RCTL_PCPU_SHIFT; --- 43 unchanged lines hidden (view full) --- 496 struct rctl_rule *rule; 497 struct rctl_rule_link *link; 498 struct sbuf sb; 499 char *buf; 500 int64_t available; 501 uint64_t sleep_ms, sleep_ratio; 502 int should_deny = 0; 503 |
504 ASSERT_RACCT_ENABLED(); |
505 RACCT_LOCK_ASSERT(); |
506 |
507 /* 508 * There may be more than one matching rule; go through all of them. 509 * Denial should be done last, after logging and sending signals. 510 */ 511 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 512 rule = link->rrl_rule; 513 if (rule->rr_resource != resource) 514 continue; --- 156 unchanged lines hidden (view full) --- 671 * are equal to their counterparts from sys/signal.h. 672 */ 673 kern_psignal(p, rule->rr_action); 674 link->rrl_exceeded = 1; 675 continue; 676 } 677 } 678 |
679 if (should_deny) { 680 /* 681 * Return fake error code; the caller should change it 682 * into one proper for the situation - EFSIZ, ENOMEM etc. 683 */ 684 return (EDOOFUS); 685 } 686 687 return (0); 688} 689 690uint64_t 691rctl_get_limit(struct proc *p, int resource) 692{ 693 struct rctl_rule *rule; 694 struct rctl_rule_link *link; 695 uint64_t amount = UINT64_MAX; 696 697 ASSERT_RACCT_ENABLED(); |
698 RACCT_LOCK_ASSERT(); |
699 |
700 /* 701 * There may be more than one matching rule; go through all of them. 702 * Denial should be done last, after logging and sending signals. 703 */ 704 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 705 rule = link->rrl_rule; 706 if (rule->rr_resource != resource) 707 continue; 708 if (rule->rr_action != RCTL_ACTION_DENY) 709 continue; 710 if (rule->rr_amount < amount) 711 amount = rule->rr_amount; 712 } 713 |
714 return (amount); 715} 716 717uint64_t 718rctl_get_available(struct proc *p, int resource) 719{ 720 struct rctl_rule *rule; 721 struct rctl_rule_link *link; 722 int64_t available, minavailable, allocated; 723 724 minavailable = INT64_MAX; 725 726 ASSERT_RACCT_ENABLED(); |
727 RACCT_LOCK_ASSERT(); |
728 |
729 /* 730 * There may be more than one matching rule; go through all of them. 731 * Denial should be done last, after logging and sending signals. 732 */ 733 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 734 rule = link->rrl_rule; 735 if (rule->rr_resource != resource) 736 continue; 737 if (rule->rr_action != RCTL_ACTION_DENY) 738 continue; 739 available = rctl_available_resource(p, rule); 740 if (available < minavailable) 741 minavailable = available; 742 } 743 |
744 /* 745 * XXX: Think about this _hard_. 746 */ 747 allocated = p->p_racct->r_resources[resource]; 748 if (minavailable < INT64_MAX - allocated) 749 minavailable += allocated; 750 if (minavailable < 0) 751 minavailable = 0; |
752 |
753 return (minavailable); 754} 755 756static int 757rctl_rule_matches(const struct rctl_rule *rule, const struct rctl_rule *filter) 758{ 759 760 ASSERT_RACCT_ENABLED(); --- 118 unchanged lines hidden (view full) --- 879 ASSERT_RACCT_ENABLED(); 880 KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); 881 882 rctl_rule_acquire(rule); 883 link = uma_zalloc(rctl_rule_link_zone, M_WAITOK); 884 link->rrl_rule = rule; 885 link->rrl_exceeded = 0; 886 |
887 RACCT_LOCK(); |
888 LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next); |
889 RACCT_UNLOCK(); |
890} 891 892static int 893rctl_racct_add_rule_locked(struct racct *racct, struct rctl_rule *rule) 894{ 895 struct rctl_rule_link *link; 896 897 ASSERT_RACCT_ENABLED(); 898 KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); |
899 RACCT_LOCK_ASSERT(); |
900 901 link = uma_zalloc(rctl_rule_link_zone, M_NOWAIT); 902 if (link == NULL) 903 return (ENOMEM); 904 rctl_rule_acquire(rule); 905 link->rrl_rule = rule; 906 link->rrl_exceeded = 0; 907 908 LIST_INSERT_HEAD(&racct->r_rule_links, link, rrl_next); |
909 |
910 return (0); 911} 912 913/* 914 * Remove limits for a rules matching the filter and release 915 * the refcounts for the rules, possibly freeing them. Returns 916 * the number of limit structures removed. 917 */ 918static int 919rctl_racct_remove_rules(struct racct *racct, 920 const struct rctl_rule *filter) 921{ 922 struct rctl_rule_link *link, *linktmp; 923 int removed = 0; 924 925 ASSERT_RACCT_ENABLED(); |
926 RACCT_LOCK_ASSERT(); |
927 928 LIST_FOREACH_SAFE(link, &racct->r_rule_links, rrl_next, linktmp) { 929 if (!rctl_rule_matches(link->rrl_rule, filter)) 930 continue; 931 932 LIST_REMOVE(link, rrl_next); 933 rctl_rule_release(link->rrl_rule); 934 uma_zfree(rctl_rule_link_zone, link); --- 454 unchanged lines hidden (view full) --- 1389 1390 return (0); 1391} 1392 1393static void 1394rctl_rule_pre_callback(void) 1395{ 1396 |
1397 RACCT_LOCK(); |
1398} 1399 1400static void 1401rctl_rule_post_callback(void) 1402{ 1403 |
1404 RACCT_UNLOCK(); |
1405} 1406 1407static void 1408rctl_rule_remove_callback(struct racct *racct, void *arg2, void *arg3) 1409{ 1410 struct rctl_rule *filter = (struct rctl_rule *)arg2; 1411 int found = 0; 1412 1413 ASSERT_RACCT_ENABLED(); |
1414 RACCT_LOCK_ASSERT(); |
1415 1416 found += rctl_racct_remove_rules(racct, filter); 1417 1418 *((int *)arg3) += found; 1419} 1420 1421/* 1422 * Remove all rules that match the filter. --- 4 unchanged lines hidden (view full) --- 1427 struct proc *p; 1428 int found = 0; 1429 1430 ASSERT_RACCT_ENABLED(); 1431 1432 if (filter->rr_subject_type == RCTL_SUBJECT_TYPE_PROCESS && 1433 filter->rr_subject.rs_proc != NULL) { 1434 p = filter->rr_subject.rs_proc; |
1435 RACCT_LOCK(); |
1436 found = rctl_racct_remove_rules(p->p_racct, filter); |
1437 RACCT_UNLOCK(); |
1438 if (found) 1439 return (0); 1440 return (ESRCH); 1441 } 1442 1443 loginclass_racct_foreach(rctl_rule_remove_callback, 1444 rctl_rule_pre_callback, rctl_rule_post_callback, 1445 filter, (void *)&found); 1446 ui_racct_foreach(rctl_rule_remove_callback, 1447 rctl_rule_pre_callback, rctl_rule_post_callback, 1448 filter, (void *)&found); 1449 prison_racct_foreach(rctl_rule_remove_callback, 1450 rctl_rule_pre_callback, rctl_rule_post_callback, 1451 filter, (void *)&found); 1452 1453 sx_assert(&allproc_lock, SA_LOCKED); |
1454 RACCT_LOCK(); |
1455 FOREACH_PROC_IN_SYSTEM(p) { 1456 found += rctl_racct_remove_rules(p->p_racct, filter); 1457 } |
1458 RACCT_UNLOCK(); |
1459 1460 if (found) 1461 return (0); 1462 return (ESRCH); 1463} 1464 1465/* 1466 * Appends a rule to the sbuf. --- 115 unchanged lines hidden (view full) --- 1582 int i; 1583 1584 ASSERT_RACCT_ENABLED(); 1585 1586 sb = sbuf_new_auto(); 1587 for (i = 0; i <= RACCT_MAX; i++) { 1588 if (sloppy == 0 && RACCT_IS_SLOPPY(i)) 1589 continue; |
1590 RACCT_LOCK(); |
1591 amount = racct->r_resources[i]; |
1592 RACCT_UNLOCK(); |
1593 if (RACCT_IS_IN_MILLIONS(i)) 1594 amount /= 1000000; 1595 sbuf_printf(sb, "%s=%jd,", rctl_resource_name(i), amount); 1596 } 1597 sbuf_setpos(sb, sbuf_len(sb) - 1); 1598 return (sb); 1599} 1600 --- 78 unchanged lines hidden (view full) --- 1679static void 1680rctl_get_rules_callback(struct racct *racct, void *arg2, void *arg3) 1681{ 1682 struct rctl_rule *filter = (struct rctl_rule *)arg2; 1683 struct rctl_rule_link *link; 1684 struct sbuf *sb = (struct sbuf *)arg3; 1685 1686 ASSERT_RACCT_ENABLED(); |
1687 RACCT_LOCK_ASSERT(); |
1688 1689 LIST_FOREACH(link, &racct->r_rule_links, rrl_next) { 1690 if (!rctl_rule_matches(link->rrl_rule, filter)) 1691 continue; 1692 rctl_rule_to_sbuf(sb, link->rrl_rule); 1693 sbuf_printf(sb, ","); 1694 } 1695} --- 34 unchanged lines hidden (view full) --- 1730 return (E2BIG); 1731 } 1732 1733 buf = malloc(bufsize, M_RCTL, M_WAITOK); 1734 sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN); 1735 KASSERT(sb != NULL, ("sbuf_new failed")); 1736 1737 FOREACH_PROC_IN_SYSTEM(p) { |
1738 RACCT_LOCK(); |
1739 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 1740 /* 1741 * Non-process rules will be added to the buffer later. 1742 * Adding them here would result in duplicated output. 1743 */ 1744 if (link->rrl_rule->rr_subject_type != 1745 RCTL_SUBJECT_TYPE_PROCESS) 1746 continue; 1747 if (!rctl_rule_matches(link->rrl_rule, filter)) 1748 continue; 1749 rctl_rule_to_sbuf(sb, link->rrl_rule); 1750 sbuf_printf(sb, ","); 1751 } |
1752 RACCT_UNLOCK(); |
1753 } 1754 1755 loginclass_racct_foreach(rctl_get_rules_callback, 1756 rctl_rule_pre_callback, rctl_rule_post_callback, 1757 filter, sb); 1758 ui_racct_foreach(rctl_get_rules_callback, 1759 rctl_rule_pre_callback, rctl_rule_post_callback, 1760 filter, sb); --- 70 unchanged lines hidden (view full) --- 1831 sx_sunlock(&allproc_lock); 1832 return (E2BIG); 1833 } 1834 1835 buf = malloc(bufsize, M_RCTL, M_WAITOK); 1836 sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN); 1837 KASSERT(sb != NULL, ("sbuf_new failed")); 1838 |
1839 RACCT_LOCK(); |
1840 LIST_FOREACH(link, &filter->rr_subject.rs_proc->p_racct->r_rule_links, 1841 rrl_next) { 1842 rctl_rule_to_sbuf(sb, link->rrl_rule); 1843 sbuf_printf(sb, ","); 1844 } |
1845 RACCT_UNLOCK(); |
1846 if (sbuf_error(sb) == ENOMEM) { 1847 error = ERANGE; 1848 sbuf_delete(sb); 1849 goto out; 1850 } 1851 1852 /* 1853 * Remove trailing ",". --- 109 unchanged lines hidden (view full) --- 1963 LIST_INIT(&newrules); 1964 1965again: 1966 /* 1967 * First, count the rules that apply to the process with new 1968 * credentials. 1969 */ 1970 rulecnt = 0; |
1971 RACCT_LOCK(); |
1972 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 1973 if (link->rrl_rule->rr_subject_type == 1974 RCTL_SUBJECT_TYPE_PROCESS) 1975 rulecnt++; 1976 } 1977 LIST_FOREACH(link, &newuip->ui_racct->r_rule_links, rrl_next) 1978 rulecnt++; 1979 LIST_FOREACH(link, &newlc->lc_racct->r_rule_links, rrl_next) 1980 rulecnt++; 1981 LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next) 1982 rulecnt++; |
1983 RACCT_UNLOCK(); |
1984 1985 /* 1986 * Create temporary list. We've dropped the rctl_lock in order 1987 * to use M_WAITOK. 1988 */ 1989 for (i = 0; i < rulecnt; i++) { 1990 newlink = uma_zalloc(rctl_rule_link_zone, M_WAITOK); 1991 newlink->rrl_rule = NULL; 1992 newlink->rrl_exceeded = 0; 1993 LIST_INSERT_HEAD(&newrules, newlink, rrl_next); 1994 } 1995 1996 newlink = LIST_FIRST(&newrules); 1997 1998 /* 1999 * Assign rules to the newly allocated list entries. 2000 */ |
2001 RACCT_LOCK(); |
2002 LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { 2003 if (link->rrl_rule->rr_subject_type == 2004 RCTL_SUBJECT_TYPE_PROCESS) { 2005 if (newlink == NULL) 2006 goto goaround; 2007 rctl_rule_acquire(link->rrl_rule); 2008 newlink->rrl_rule = link->rrl_rule; 2009 newlink->rrl_exceeded = link->rrl_exceeded; --- 51 unchanged lines hidden (view full) --- 2061 */ 2062 while (!LIST_EMPTY(&newrules)) { 2063 newlink = LIST_FIRST(&newrules); 2064 LIST_REMOVE(newlink, rrl_next); 2065 LIST_INSERT_HEAD(&p->p_racct->r_rule_links, 2066 newlink, rrl_next); 2067 } 2068 |
2069 RACCT_UNLOCK(); |
2070 2071 return; 2072 } 2073 2074goaround: |
2075 RACCT_UNLOCK(); |
2076 2077 /* 2078 * Rule list changed while we were not holding the rctl_lock. 2079 * Free the new list and try again. 2080 */ 2081 while (!LIST_EMPTY(&newrules)) { 2082 newlink = LIST_FIRST(&newrules); 2083 LIST_REMOVE(newlink, rrl_next); --- 10 unchanged lines hidden (view full) --- 2094 */ 2095int 2096rctl_proc_fork(struct proc *parent, struct proc *child) 2097{ 2098 struct rctl_rule *rule; 2099 struct rctl_rule_link *link; 2100 int error; 2101 |
2102 ASSERT_RACCT_ENABLED(); |
2103 RACCT_LOCK_ASSERT(); |
2104 KASSERT(parent->p_racct != NULL, ("process without racct; p = %p", parent)); 2105 |
2106 LIST_INIT(&child->p_racct->r_rule_links); |
2107 2108 /* 2109 * Go through limits applicable to the parent and assign them 2110 * to the child. Rules with 'process' subject have to be duplicated 2111 * in order to make their rr_subject point to the new process. 2112 */ 2113 LIST_FOREACH(link, &parent->p_racct->r_rule_links, rrl_next) { 2114 if (link->rrl_rule->rr_subject_type == --- 12 unchanged lines hidden (view full) --- 2127 } else { 2128 error = rctl_racct_add_rule_locked(child->p_racct, 2129 link->rrl_rule); 2130 if (error != 0) 2131 goto fail; 2132 } 2133 } 2134 |
2135 return (0); 2136 2137fail: 2138 while (!LIST_EMPTY(&child->p_racct->r_rule_links)) { 2139 link = LIST_FIRST(&child->p_racct->r_rule_links); 2140 LIST_REMOVE(link, rrl_next); 2141 rctl_rule_release(link->rrl_rule); 2142 uma_zfree(rctl_rule_link_zone, link); 2143 } |
2144 |
2145 return (EAGAIN); 2146} 2147 2148/* 2149 * Release rules attached to the racct. 2150 */ 2151void 2152rctl_racct_release(struct racct *racct) 2153{ 2154 struct rctl_rule_link *link; 2155 2156 ASSERT_RACCT_ENABLED(); |
2157 RACCT_LOCK_ASSERT(); |
2158 |
2159 while (!LIST_EMPTY(&racct->r_rule_links)) { 2160 link = LIST_FIRST(&racct->r_rule_links); 2161 LIST_REMOVE(link, rrl_next); 2162 rctl_rule_release(link->rrl_rule); 2163 uma_zfree(rctl_rule_link_zone, link); 2164 } |
2165} 2166 2167static void 2168rctl_init(void) 2169{ 2170 2171 if (!racct_enable) 2172 return; --- 61 unchanged lines hidden --- |