Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_rctl.c
Show First 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
#define HRF_DONT_ACCUMULATE 2 | #define HRF_DONT_ACCUMULATE 2 | ||||
#define RCTL_MAX_INBUFSIZE 4 * 1024 | #define RCTL_MAX_INBUFSIZE 4 * 1024 | ||||
#define RCTL_MAX_OUTBUFSIZE 16 * 1024 * 1024 | #define RCTL_MAX_OUTBUFSIZE 16 * 1024 * 1024 | ||||
#define RCTL_LOG_BUFSIZE 128 | #define RCTL_LOG_BUFSIZE 128 | ||||
#define RCTL_PCPU_SHIFT (10 * 1000000) | #define RCTL_PCPU_SHIFT (10 * 1000000) | ||||
unsigned int rctl_maxbufsize = RCTL_MAX_OUTBUFSIZE; | static unsigned int rctl_maxbufsize = RCTL_MAX_OUTBUFSIZE; | ||||
static int rctl_log_rate_limit = 10; | static int rctl_log_rate_limit = 10; | ||||
static int rctl_devctl_rate_limit = 10; | static int rctl_devctl_rate_limit = 10; | ||||
static unsigned int rctl_throttle_min = 0; | |||||
static unsigned int rctl_throttle_max = 0; | |||||
static unsigned int rctl_throttle_pct = 0; | |||||
static unsigned int rctl_throttle_pct2 = 0; | |||||
SYSCTL_NODE(_kern_racct, OID_AUTO, rctl, CTLFLAG_RW, 0, "Resource Limits"); | SYSCTL_NODE(_kern_racct, OID_AUTO, rctl, CTLFLAG_RW, 0, "Resource Limits"); | ||||
SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, maxbufsize, CTLFLAG_RWTUN, | SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, maxbufsize, CTLFLAG_RWTUN, | ||||
&rctl_maxbufsize, 0, "Maximum output buffer size"); | &rctl_maxbufsize, 0, "Maximum output buffer size"); | ||||
SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, log_rate_limit, CTLFLAG_RW, | SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, log_rate_limit, CTLFLAG_RW, | ||||
&rctl_log_rate_limit, 0, "Maximum number of log messages per second"); | &rctl_log_rate_limit, 0, "Maximum number of log messages per second"); | ||||
SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, devctl_rate_limit, CTLFLAG_RW, | SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, devctl_rate_limit, CTLFLAG_RW, | ||||
&rctl_devctl_rate_limit, 0, "Maximum number of devctl messages per second"); | &rctl_devctl_rate_limit, 0, "Maximum number of devctl messages per second"); | ||||
SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, throttle_min, CTLFLAG_RDTUN, | |||||
&rctl_throttle_min, 0, "Shortest throttling duration, in hz"); | |||||
SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, throttle_max, CTLFLAG_RDTUN, | |||||
&rctl_throttle_max, 0, "Longest throttling duration, in hz"); | |||||
SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, throttle_pct, CTLFLAG_RDTUN, | |||||
&rctl_throttle_pct, 0, | |||||
"Throttling penalty for process consumption, in percent"); | |||||
SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, throttle_pct2, CTLFLAG_RDTUN, | |||||
&rctl_throttle_pct2, 0, | |||||
"Throttling penalty for container consumption, in percent"); | |||||
/* | /* | ||||
* 'rctl_rule_link' connects a rule with every racct it's related to. | * 'rctl_rule_link' connects a rule with every racct it's related to. | ||||
* For example, rule 'user:X:openfiles:deny=N/process' is linked | * For example, rule 'user:X:openfiles:deny=N/process' is linked | ||||
* with uidinfo for user X, and to each process of that user. | * with uidinfo for user X, and to each process of that user. | ||||
*/ | */ | ||||
struct rctl_rule_link { | struct rctl_rule_link { | ||||
LIST_ENTRY(rctl_rule_link) rrl_next; | LIST_ENTRY(rctl_rule_link) rrl_next; | ||||
Show All 30 Lines | static struct dict resourcenames[] = { | ||||
{ "msgqsize", RACCT_MSGQSIZE }, | { "msgqsize", RACCT_MSGQSIZE }, | ||||
{ "nmsgq", RACCT_NMSGQ }, | { "nmsgq", RACCT_NMSGQ }, | ||||
{ "nsem", RACCT_NSEM }, | { "nsem", RACCT_NSEM }, | ||||
{ "nsemop", RACCT_NSEMOP }, | { "nsemop", RACCT_NSEMOP }, | ||||
{ "nshm", RACCT_NSHM }, | { "nshm", RACCT_NSHM }, | ||||
{ "shmsize", RACCT_SHMSIZE }, | { "shmsize", RACCT_SHMSIZE }, | ||||
{ "wallclock", RACCT_WALLCLOCK }, | { "wallclock", RACCT_WALLCLOCK }, | ||||
{ "pcpu", RACCT_PCTCPU }, | { "pcpu", RACCT_PCTCPU }, | ||||
{ "readbps", RACCT_READBPS }, | |||||
{ "writebps", RACCT_WRITEBPS }, | |||||
{ "readiops", RACCT_READIOPS }, | |||||
{ "writeiops", RACCT_WRITEIOPS }, | |||||
{ NULL, -1 }}; | { NULL, -1 }}; | ||||
static struct dict actionnames[] = { | static struct dict actionnames[] = { | ||||
{ "sighup", RCTL_ACTION_SIGHUP }, | { "sighup", RCTL_ACTION_SIGHUP }, | ||||
{ "sigint", RCTL_ACTION_SIGINT }, | { "sigint", RCTL_ACTION_SIGINT }, | ||||
{ "sigquit", RCTL_ACTION_SIGQUIT }, | { "sigquit", RCTL_ACTION_SIGQUIT }, | ||||
{ "sigill", RCTL_ACTION_SIGILL }, | { "sigill", RCTL_ACTION_SIGILL }, | ||||
{ "sigtrap", RCTL_ACTION_SIGTRAP }, | { "sigtrap", RCTL_ACTION_SIGTRAP }, | ||||
Show All 21 Lines | static struct dict actionnames[] = { | ||||
{ "sigwinch", RCTL_ACTION_SIGWINCH }, | { "sigwinch", RCTL_ACTION_SIGWINCH }, | ||||
{ "siginfo", RCTL_ACTION_SIGINFO }, | { "siginfo", RCTL_ACTION_SIGINFO }, | ||||
{ "sigusr1", RCTL_ACTION_SIGUSR1 }, | { "sigusr1", RCTL_ACTION_SIGUSR1 }, | ||||
{ "sigusr2", RCTL_ACTION_SIGUSR2 }, | { "sigusr2", RCTL_ACTION_SIGUSR2 }, | ||||
{ "sigthr", RCTL_ACTION_SIGTHR }, | { "sigthr", RCTL_ACTION_SIGTHR }, | ||||
{ "deny", RCTL_ACTION_DENY }, | { "deny", RCTL_ACTION_DENY }, | ||||
{ "log", RCTL_ACTION_LOG }, | { "log", RCTL_ACTION_LOG }, | ||||
{ "devctl", RCTL_ACTION_DEVCTL }, | { "devctl", RCTL_ACTION_DEVCTL }, | ||||
{ "throttle", RCTL_ACTION_THROTTLE }, | |||||
{ NULL, -1 }}; | { NULL, -1 }}; | ||||
static void rctl_init(void); | static void rctl_init(void); | ||||
SYSINIT(rctl, SI_SUB_RACCT, SI_ORDER_FIRST, rctl_init, NULL); | SYSINIT(rctl, SI_SUB_RACCT, SI_ORDER_FIRST, rctl_init, NULL); | ||||
static uma_zone_t rctl_rule_link_zone; | static uma_zone_t rctl_rule_link_zone; | ||||
static uma_zone_t rctl_rule_zone; | static uma_zone_t rctl_rule_zone; | ||||
static struct rwlock rctl_lock; | static struct rwlock rctl_lock; | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | rctl_available_resource(const struct proc *p, const struct rctl_rule *rule) | ||||
racct = rctl_proc_rule_to_racct(p, rule); | racct = rctl_proc_rule_to_racct(p, rule); | ||||
available = rule->rr_amount - racct->r_resources[rule->rr_resource]; | available = rule->rr_amount - racct->r_resources[rule->rr_resource]; | ||||
return (available); | return (available); | ||||
} | } | ||||
/* | /* | ||||
* Return non-zero if allocating 'amount' by proc 'p' would exceed | * Called every second for proc, uidinfo, loginclass, and jail containers. | ||||
* resource limit specified by 'rule'. | * If the limit isn't exceeded, it decreases the usage amount to zero. | ||||
* Otherwise, it decreases it by the value of the limit. This way | |||||
* resource consumption exceeding the limit "carries over" to the next | |||||
* period. | |||||
*/ | */ | ||||
static int | void | ||||
rctl_would_exceed(const struct proc *p, const struct rctl_rule *rule, | rctl_throttle_decay(struct racct *racct, int resource) | ||||
int64_t amount) | |||||
{ | { | ||||
int64_t available; | struct rctl_rule *rule; | ||||
struct rctl_rule_link *link; | |||||
int64_t minavailable; | |||||
ASSERT_RACCT_ENABLED(); | ASSERT_RACCT_ENABLED(); | ||||
RCTL_LOCK_ASSERT(); | |||||
available = rctl_available_resource(p, rule); | minavailable = INT64_MAX; | ||||
if (available >= amount) | |||||
return (0); | |||||
return (1); | RCTL_RLOCK(); | ||||
LIST_FOREACH(link, &racct->r_rule_links, rrl_next) { | |||||
rule = link->rrl_rule; | |||||
if (rule->rr_resource != resource) | |||||
continue; | |||||
if (rule->rr_action != RCTL_ACTION_THROTTLE) | |||||
continue; | |||||
if (rule->rr_amount < minavailable) | |||||
minavailable = rule->rr_amount; | |||||
} | } | ||||
RCTL_RUNLOCK(); | |||||
if (racct->r_resources[resource] < minavailable) { | |||||
racct->r_resources[resource] = 0; | |||||
} else { | |||||
/* | /* | ||||
* Cap utilization counter at ten times the limit. Otherwise, | |||||
* if we changed the rule lowering the allowed amount, it could | |||||
* take unreasonably long time for the accumulated resource | |||||
* usage to drop. | |||||
*/ | |||||
if (racct->r_resources[resource] > minavailable * 10) | |||||
racct->r_resources[resource] = minavailable * 10; | |||||
racct->r_resources[resource] -= minavailable; | |||||
} | |||||
} | |||||
/* | |||||
* Special version of rctl_get_available() for the %CPU resource. | * Special version of rctl_get_available() for the %CPU resource. | ||||
* We slightly cheat here and return less than we normally would. | * We slightly cheat here and return less than we normally would. | ||||
*/ | */ | ||||
int64_t | int64_t | ||||
rctl_pcpu_available(const struct proc *p) { | rctl_pcpu_available(const struct proc *p) { | ||||
struct rctl_rule *rule; | struct rctl_rule *rule; | ||||
struct rctl_rule_link *link; | struct rctl_rule_link *link; | ||||
int64_t available, minavailable, limit; | int64_t available, minavailable, limit; | ||||
Show All 30 Lines | if (limit > 2 * RCTL_PCPU_SHIFT) | ||||
minavailable -= RCTL_PCPU_SHIFT; | minavailable -= RCTL_PCPU_SHIFT; | ||||
else | else | ||||
minavailable -= (limit / 2); | minavailable -= (limit / 2); | ||||
} | } | ||||
return (minavailable); | return (minavailable); | ||||
} | } | ||||
static uint64_t | |||||
xadd(uint64_t a, uint64_t b) | |||||
{ | |||||
uint64_t c; | |||||
c = a + b; | |||||
/* | /* | ||||
* Detect overflow. | |||||
*/ | |||||
if (c < a || c < b) | |||||
return (UINT64_MAX); | |||||
return (c); | |||||
} | |||||
static uint64_t | |||||
xmul(uint64_t a, uint64_t b) | |||||
{ | |||||
uint64_t c; | |||||
if (a == 0 || b == 0) | |||||
return (0); | |||||
c = a * b; | |||||
if (c < a || c < b) | |||||
return (UINT64_MAX); | |||||
return (c); | |||||
} | |||||
/* | |||||
* Check whether the proc 'p' can allocate 'amount' of 'resource' in addition | * Check whether the proc 'p' can allocate 'amount' of 'resource' in addition | ||||
* to what it keeps allocated now. Returns non-zero if the allocation should | * to what it keeps allocated now. Returns non-zero if the allocation should | ||||
* be denied, 0 otherwise. | * be denied, 0 otherwise. | ||||
*/ | */ | ||||
int | int | ||||
rctl_enforce(struct proc *p, int resource, uint64_t amount) | rctl_enforce(struct proc *p, int resource, uint64_t amount) | ||||
{ | { | ||||
static struct timeval log_lasttime, devctl_lasttime; | static struct timeval log_lasttime, devctl_lasttime; | ||||
static int log_curtime = 0, devctl_curtime = 0; | static int log_curtime = 0, devctl_curtime = 0; | ||||
struct rctl_rule *rule; | struct rctl_rule *rule; | ||||
struct rctl_rule_link *link; | struct rctl_rule_link *link; | ||||
struct sbuf sb; | struct sbuf sb; | ||||
int64_t available; | |||||
uint64_t sleep_ms, sleep_ratio; | |||||
int should_deny = 0; | int should_deny = 0; | ||||
char *buf; | char *buf; | ||||
ASSERT_RACCT_ENABLED(); | ASSERT_RACCT_ENABLED(); | ||||
RCTL_RLOCK(); | RCTL_RLOCK(); | ||||
/* | /* | ||||
* There may be more than one matching rule; go through all of them. | * There may be more than one matching rule; go through all of them. | ||||
* Denial should be done last, after logging and sending signals. | * Denial should be done last, after logging and sending signals. | ||||
*/ | */ | ||||
LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { | LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { | ||||
rule = link->rrl_rule; | rule = link->rrl_rule; | ||||
if (rule->rr_resource != resource) | if (rule->rr_resource != resource) | ||||
continue; | continue; | ||||
if (!rctl_would_exceed(p, rule, amount)) { | |||||
available = rctl_available_resource(p, rule); | |||||
if (available >= (int64_t)amount) { | |||||
link->rrl_exceeded = 0; | link->rrl_exceeded = 0; | ||||
continue; | continue; | ||||
} | } | ||||
switch (rule->rr_action) { | switch (rule->rr_action) { | ||||
case RCTL_ACTION_DENY: | case RCTL_ACTION_DENY: | ||||
should_deny = 1; | should_deny = 1; | ||||
continue; | continue; | ||||
Show All 36 Lines | case RCTL_ACTION_LOG: | ||||
link->rrl_exceeded = 1; | link->rrl_exceeded = 1; | ||||
continue; | continue; | ||||
case RCTL_ACTION_DEVCTL: | case RCTL_ACTION_DEVCTL: | ||||
if (link->rrl_exceeded != 0) | if (link->rrl_exceeded != 0) | ||||
continue; | continue; | ||||
if (p->p_state != PRS_NORMAL) | if (p->p_state != PRS_NORMAL) | ||||
continue; | continue; | ||||
if (!ppsratecheck(&devctl_lasttime, &devctl_curtime, | if (!ppsratecheck(&devctl_lasttime, &devctl_curtime, | ||||
rctl_devctl_rate_limit)) | rctl_devctl_rate_limit)) | ||||
continue; | continue; | ||||
buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT); | buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT); | ||||
if (buf == NULL) { | if (buf == NULL) { | ||||
printf("rctl_enforce: out of memory\n"); | printf("rctl_enforce: out of memory\n"); | ||||
continue; | continue; | ||||
} | } | ||||
sbuf_new(&sb, buf, RCTL_LOG_BUFSIZE, SBUF_FIXEDLEN); | sbuf_new(&sb, buf, RCTL_LOG_BUFSIZE, SBUF_FIXEDLEN); | ||||
sbuf_printf(&sb, "rule="); | sbuf_printf(&sb, "rule="); | ||||
rctl_rule_to_sbuf(&sb, rule); | rctl_rule_to_sbuf(&sb, rule); | ||||
sbuf_printf(&sb, " pid=%d ruid=%d jail=%s", | sbuf_printf(&sb, " pid=%d ruid=%d jail=%s", | ||||
p->p_pid, p->p_ucred->cr_ruid, | p->p_pid, p->p_ucred->cr_ruid, | ||||
p->p_ucred->cr_prison->pr_prison_racct->prr_name); | p->p_ucred->cr_prison->pr_prison_racct->prr_name); | ||||
sbuf_finish(&sb); | sbuf_finish(&sb); | ||||
devctl_notify_f("RCTL", "rule", "matched", | devctl_notify_f("RCTL", "rule", "matched", | ||||
sbuf_data(&sb), M_NOWAIT); | sbuf_data(&sb), M_NOWAIT); | ||||
sbuf_delete(&sb); | sbuf_delete(&sb); | ||||
free(buf, M_RCTL); | free(buf, M_RCTL); | ||||
link->rrl_exceeded = 1; | link->rrl_exceeded = 1; | ||||
continue; | continue; | ||||
case RCTL_ACTION_THROTTLE: | |||||
if (p->p_state != PRS_NORMAL) | |||||
continue; | |||||
/* | |||||
* Make the process sleep for a fraction of second | |||||
* proportional to the ratio of process' resource | |||||
* utilization compared to the limit. The point is | |||||
* to penalize resource hogs: processes that consume | |||||
* more of the available resources sleep for longer. | |||||
* | |||||
* We're trying to defer division until the very end, | |||||
* to minimize the rounding effects. The following | |||||
* calculation could have been written in a clearer | |||||
* way like this: | |||||
* | |||||
* sleep_ms = hz * p->p_racct->r_resources[resource] / | |||||
* rule->rr_amount; | |||||
* sleep_ms *= rctl_throttle_pct / 100; | |||||
* if (sleep_ms < rctl_throttle_min) | |||||
* sleep_ms = rctl_throttle_min; | |||||
* | |||||
*/ | |||||
sleep_ms = xmul(hz, p->p_racct->r_resources[resource]); | |||||
sleep_ms = xmul(sleep_ms, rctl_throttle_pct) / 100; | |||||
if (sleep_ms < rctl_throttle_min * rule->rr_amount) | |||||
sleep_ms = rctl_throttle_min * rule->rr_amount; | |||||
/* | |||||
* Multiply that by the ratio of the resource | |||||
* consumption for the container compared to the limit, | |||||
* squared. In other words, a process in a container | |||||
* that is two times over the limit will be throttled | |||||
* four times as much for hitting the same rule. The | |||||
* point is to penalize processes more if the container | |||||
* itself (eg certain UID or jail) is above the limit. | |||||
*/ | |||||
if (available < 0) | |||||
sleep_ratio = -available / rule->rr_amount; | |||||
else | |||||
sleep_ratio = 0; | |||||
sleep_ratio = xmul(sleep_ratio, sleep_ratio); | |||||
sleep_ratio = xmul(sleep_ratio, rctl_throttle_pct2) / 100; | |||||
sleep_ms = xadd(sleep_ms, xmul(sleep_ms, sleep_ratio)); | |||||
/* | |||||
* Finally the division. | |||||
*/ | |||||
sleep_ms /= rule->rr_amount; | |||||
if (sleep_ms > rctl_throttle_max) | |||||
sleep_ms = rctl_throttle_max; | |||||
#if 0 | |||||
printf("%s: pid %d (%s), %jd of %jd, will sleep for %ld ms (ratio %ld, available %ld)\n", | |||||
__func__, p->p_pid, p->p_comm, | |||||
p->p_racct->r_resources[resource], | |||||
rule->rr_amount, sleep_ms, sleep_ratio, available); | |||||
#endif | |||||
KASSERT(sleep_ms >= rctl_throttle_min, ("%s: %ju < %d\n", | |||||
__func__, (uintmax_t)sleep_ms, rctl_throttle_min)); | |||||
racct_proc_throttle(p, sleep_ms); | |||||
continue; | |||||
default: | default: | ||||
if (link->rrl_exceeded != 0) | if (link->rrl_exceeded != 0) | ||||
continue; | continue; | ||||
if (p->p_state != PRS_NORMAL) | if (p->p_state != PRS_NORMAL) | ||||
continue; | continue; | ||||
KASSERT(rule->rr_action > 0 && | KASSERT(rule->rr_action > 0 && | ||||
▲ Show 20 Lines • Show All 613 Lines • ▼ Show 20 Lines | rctl_rule_add(struct rctl_rule *rule) | ||||
struct loginclass *lc; | struct loginclass *lc; | ||||
struct rctl_rule *rule2; | struct rctl_rule *rule2; | ||||
int match; | int match; | ||||
ASSERT_RACCT_ENABLED(); | ASSERT_RACCT_ENABLED(); | ||||
KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); | KASSERT(rctl_rule_fully_specified(rule), ("rule not fully specified")); | ||||
/* | /* | ||||
* Some rules just don't make sense. Note that the one below | * Some rules just don't make sense, like "deny" rule for an undeniable | ||||
* cannot be rewritten using RACCT_IS_DENIABLE(); the RACCT_PCTCPU, | * resource. The exception are the RSS and %CPU resources - they are | ||||
* for example, is not deniable in the racct sense, but the | * not deniable in the racct sense, but the limit is enforced in | ||||
* limit is enforced in a different way, so "deny" rules for %CPU | * a different way. | ||||
* do make sense. | |||||
*/ | */ | ||||
if (rule->rr_action == RCTL_ACTION_DENY && | if (rule->rr_action == RCTL_ACTION_DENY && | ||||
(rule->rr_resource == RACCT_CPU || | !RACCT_IS_DENIABLE(rule->rr_resource) && | ||||
rule->rr_resource == RACCT_WALLCLOCK)) | rule->rr_resource != RACCT_RSS && | ||||
rule->rr_resource != RACCT_PCTCPU) { | |||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
} | |||||
if (rule->rr_action == RCTL_ACTION_THROTTLE && | |||||
!RACCT_IS_DECAYING(rule->rr_resource)) { | |||||
return (EOPNOTSUPP); | |||||
} | |||||
if (rule->rr_action == RCTL_ACTION_THROTTLE && | |||||
rule->rr_resource == RACCT_PCTCPU) { | |||||
return (EOPNOTSUPP); | |||||
} | |||||
if (rule->rr_per == RCTL_SUBJECT_TYPE_PROCESS && | if (rule->rr_per == RCTL_SUBJECT_TYPE_PROCESS && | ||||
RACCT_IS_SLOPPY(rule->rr_resource)) | RACCT_IS_SLOPPY(rule->rr_resource)) { | ||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
} | |||||
/* | /* | ||||
* Make sure there are no duplicated rules. Also, for the "deny" | * Make sure there are no duplicated rules. Also, for the "deny" | ||||
* rules, remove ones differing only by "amount". | * rules, remove ones differing only by "amount". | ||||
*/ | */ | ||||
if (rule->rr_action == RCTL_ACTION_DENY) { | if (rule->rr_action == RCTL_ACTION_DENY) { | ||||
rule2 = rctl_rule_duplicate(rule, M_WAITOK); | rule2 = rctl_rule_duplicate(rule, M_WAITOK); | ||||
rule2->rr_amount = RCTL_AMOUNT_UNDEFINED; | rule2->rr_amount = RCTL_AMOUNT_UNDEFINED; | ||||
▲ Show 20 Lines • Show All 857 Lines • ▼ Show 20 Lines | rctl_init(void) | ||||
if (!racct_enable) | if (!racct_enable) | ||||
return; | return; | ||||
rctl_rule_link_zone = uma_zcreate("rctl_rule_link", | rctl_rule_link_zone = uma_zcreate("rctl_rule_link", | ||||
sizeof(struct rctl_rule_link), NULL, NULL, NULL, NULL, | sizeof(struct rctl_rule_link), NULL, NULL, NULL, NULL, | ||||
UMA_ALIGN_PTR, UMA_ZONE_NOFREE); | UMA_ALIGN_PTR, UMA_ZONE_NOFREE); | ||||
rctl_rule_zone = uma_zcreate("rctl_rule", sizeof(struct rctl_rule), | rctl_rule_zone = uma_zcreate("rctl_rule", sizeof(struct rctl_rule), | ||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); | NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); | ||||
if (rctl_throttle_min <= 0) | |||||
rctl_throttle_min = 1; | |||||
if (rctl_throttle_max <= 0) | |||||
rctl_throttle_max = 2 * hz; | |||||
if (rctl_throttle_pct <= 0) | |||||
rctl_throttle_pct = 100; | |||||
if (rctl_throttle_pct2 <= 0) | |||||
rctl_throttle_pct2 = 100; | |||||
} | } | ||||
#else /* !RCTL */ | #else /* !RCTL */ | ||||
int | int | ||||
sys_rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) | sys_rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) | ||||
{ | { | ||||
Show All 32 Lines |