Date: Sun, 2 Aug 2009 18:47:01 GMT From: Edward Tomasz Napierala <trasz@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 166939 for review Message-ID: <200908021847.n72Il1ch042802@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=166939 Change 166939 by trasz@trasz_anger on 2009/08/02 18:46:44 Add support for 'loginclass:' rules. Affected files ... .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#39 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_loginclass.c#3 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#18 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/loginclass.h#2 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/resourcevar.h#9 edit .. //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#20 edit Differences ... ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#39 (text+ko) ==== @@ -724,9 +724,6 @@ LIST_REMOVE(limit, hl_next); mtx_unlock(&hrl_lock); hrl_rule_release(limit->hl_rule); - if (limit->hl_rule->hr_subject == HRL_SUBJECT_LOGINCLASS && - limit->hl_rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED) - loginclass_release((struct loginclass *)(long)limit->hl_rule->hr_subject_id); uma_zfree(hrl_limit_zone, limit); removed++; goto again; @@ -784,8 +781,13 @@ KASSERT(rule->hr_refcount > 0, ("rule->hr_refcount > 0")); - if (refcount_release(&rule->hr_refcount)) + if (refcount_release(&rule->hr_refcount)) { + if (rule->hr_subject == HRL_SUBJECT_LOGINCLASS && + rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED) + loginclass_release((struct loginclass *)(long) + rule->hr_subject_id); uma_zfree(hrl_rule_zone, rule); + } } static int @@ -839,11 +841,12 @@ * to the 'struct loginclass' into the hr_subject_id field. */ if (rule->hr_subject == HRL_SUBJECT_LOGINCLASS) { - if (subject_idstr == NULL || subject_idstr[0] == '\0') - goto out; - - lc = loginclass_find(subject_idstr); - rule->hr_subject_id = (long)lc; + if (subject_idstr == NULL || subject_idstr[0] == '\0') { + rule->hr_subject_id = HRL_SUBJECT_ID_UNDEFINED; + } else { + lc = loginclass_find(subject_idstr); + rule->hr_subject_id = (long)lc; + } } else { if (subject_idstr == NULL || subject_idstr[0] == '\0') rule->hr_subject_id = HRL_SUBJECT_ID_UNDEFINED; @@ -961,7 +964,6 @@ break; case HRL_SUBJECT_LOGINCLASS: - KASSERT(rule->hr_subject_id > 0, ("rule->hr_subject_id > 0")); lc = (struct loginclass *)(long)rule->hr_subject_id; hrl_limit_add(&lc->lc_limits, rule); break; @@ -1021,6 +1023,15 @@ return (0); } +static int +hrl_rule_remove_callback(struct hrl_limits_head *limits, const struct hrl_rule *filter, void *arg3, void *arg4 __unused) +{ + int *found = (int *)arg3; + + *found += hrl_limit_remove_matching(limits, filter); + return (0); +} + /* * Remove all rules that match the filter. */ @@ -1037,18 +1048,27 @@ if (p == NULL) return (ESRCH); PROC_UNLOCK(p); - error = hrl_limit_remove_matching(&p->p_limits, filter); + found = hrl_limit_remove_matching(&p->p_limits, filter); sx_sunlock(&proctree_lock); - return (error); + if (found) + return (0); + return (ESRCH); } + error = loginclass_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found, NULL); + KASSERT(error == 0, ("loginclass_limits_foreach failed")); + error = ui_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found, NULL); + KASSERT(error == 0, ("ui_limits_foreach failed")); + error = gi_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found, NULL); + KASSERT(error == 0, ("gi_limits_foreach failed")); + /* * XXX: per-process, per-group, per-jail and per-class limits. */ sx_slock(&proctree_lock); FOREACH_PROC_IN_SYSTEM(p) { - error = hrl_limit_remove_matching(&p->p_limits, filter); + found += hrl_limit_remove_matching(&p->p_limits, filter); if (error == 0) found = 1; } @@ -1056,8 +1076,7 @@ if (found) return (0); - else - return (ESRCH); + return (ESRCH); } static struct sbuf * @@ -1266,10 +1285,30 @@ return (error); } +static int +hrl_get_rules_callback(struct hrl_limits_head *limits, const struct hrl_rule *filter, void *arg3, void *arg4) +{ + struct hrl_limit *limit; + struct hrl_rule *buf = (struct hrl_rule *)arg3; + int copied = 0, *available = (int *)arg4; + + LIST_FOREACH(limit, limits, hl_next) { + if (copied >= *available) + return (ERANGE); + if (!hrl_rule_matches(limit->hl_rule, filter)) + continue; + *(buf + copied) = *limit->hl_rule; + copied++; + (*available)--; + } + + return (0); +} + int hrl_get_rules(struct thread *td, struct hrl_get_rules_args *uap) { - int error, copied, maxcopied = HRL_MAX_RULES; + int error, copied, maxcopied = HRL_MAX_RULES, available; char *inputstr; struct sbuf *outputsbuf; struct hrl_rule *filter, *buf; @@ -1285,8 +1324,6 @@ if (filter == NULL) return (EINVAL); - buf = malloc(HRL_MAX_RULES * sizeof(struct hrl_rule), M_HRL, M_WAITOK); - again: buf = malloc(maxcopied * sizeof(*buf), M_HRL, M_WAITOK); copied = 0; @@ -1294,7 +1331,7 @@ FOREACH_PROC_IN_SYSTEM(p) { mtx_lock(&hrl_lock); LIST_FOREACH(limit, &p->p_limits, hl_next) { - if (copied >= HRL_MAX_RULES) { + if (copied >= maxcopied) { mtx_unlock(&hrl_lock); sx_sunlock(&proctree_lock); maxcopied *= 4; @@ -1312,6 +1349,24 @@ if (error) goto out; + available = maxcopied - copied; + loginclass_limits_foreach(hrl_get_rules_callback, filter, + buf + copied, &available); + copied = maxcopied - available; + available = maxcopied - copied; + ui_limits_foreach(hrl_get_rules_callback, filter, + buf + copied, &available); + copied = maxcopied - available; + available = maxcopied - copied; + gi_limits_foreach(hrl_get_rules_callback, filter, + buf + copied, &available); + copied = maxcopied - available; + if (copied >= maxcopied) { + maxcopied *= 4; + free(buf, M_HRL); + goto again; + } + /* * XXX: Iterate over the rest (other than per-process) of the rules. */ @@ -1370,15 +1425,13 @@ } mtx_lock(&hrl_lock); LIST_FOREACH(limit, &p->p_limits, hl_next) { - if (copied >= HRL_MAX_RULES) { + if (copied >= maxcopied) { mtx_unlock(&hrl_lock); PROC_UNLOCK(p); maxcopied *= 4; free(buf, M_HRL); goto again; } - if (!hrl_rule_matches(limit->hl_rule, filter)) - continue; *(buf + copied) = *limit->hl_rule; copied++; } @@ -1413,10 +1466,8 @@ rule = hrl_rule_from_string(inputstr); free(inputstr, M_HRL); - if (rule == NULL) { - error = EINVAL; - goto out; - } + if (rule == NULL) + return (EINVAL); if (!hrl_rule_fully_specified(rule)) { error = EINVAL; ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_loginclass.c#3 (text+ko) ==== @@ -201,6 +201,23 @@ return (0); } +int +loginclass_limits_foreach(int (*callback)(struct hrl_limits_head *limits, + const struct hrl_rule *filter, void *arg3, void *arg4), + const struct hrl_rule *filter, void *arg3, void *arg4) +{ + int error; + struct loginclass *lc; + + LIST_FOREACH(lc, &loginclasses, lc_next) { + error = (callback)(&lc->lc_limits, filter, arg3, arg4); + if (error) + return (error); + } + + return (0); +} + static void lc_proc_fork(void *arg __unused, struct proc *parent, struct proc *child, int flags __unused) ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#18 (text+ko) ==== @@ -1412,6 +1412,19 @@ rw_wunlock(&uihashtbl_lock); } +int +ui_limits_foreach(int (*callback)(struct hrl_limits_head *limits, + const struct hrl_rule *filter, void *arg3, void *arg4), + const struct hrl_rule *filter, void *arg3, void *arg4) +{ + + callback = callback; + filter = filter; + arg3 = arg3; + arg4 = arg4; + return (0); +} + /* * Find the gidinfo structure for a gid. This structure is used to * track the total resource consumption (process count, socket buffer @@ -1557,6 +1570,20 @@ rw_wunlock(&gihashtbl_lock); } +int +gi_limits_foreach(int (*callback)(struct hrl_limits_head *limits, + const struct hrl_rule *filter, void *arg3, void *arg4), + const struct hrl_rule *filter, void *arg3, void *arg4) +{ + + callback = callback; + filter = filter; + arg3 = arg3; + arg4 = arg4; + + return (0); +} + /* * Change the count associated with number of processes * a given user is using. When 'max' is 0, don't enforce a limit ==== //depot/projects/soc2009/trasz_limits/sys/sys/loginclass.h#2 (text+ko) ==== @@ -41,6 +41,9 @@ void loginclass_acquire(struct loginclass *lc); void loginclass_release(struct loginclass *lc); struct loginclass *loginclass_find(const char *name); +int loginclass_limits_foreach(int (*callback)(struct hrl_limits_head *limits, + const struct hrl_rule *filter, void *arg3, void *arg4), + const struct hrl_rule *filter, void *arg3, void *arg4); #endif /* !_SYS_LOGINCLASS_H_ */ ==== //depot/projects/soc2009/trasz_limits/sys/sys/resourcevar.h#9 (text+ko) ==== @@ -159,6 +159,9 @@ void uifree(struct uidinfo *uip); void uihashinit(void); void uihold(struct uidinfo *uip); +int ui_limits_foreach(int (*callback)(struct hrl_limits_head *limits, + const struct hrl_rule *filter, void *arg3, void *arg4), + const struct hrl_rule *filter, void *arg3, void *arg4); struct gidinfo *gifind(gid_t gid); struct gidinfo @@ -166,6 +169,9 @@ void gifree(struct gidinfo *gip); void gihashinit(void); void gihold(struct gidinfo *gip); +int gi_limits_foreach(int (*callback)(struct hrl_limits_head *limits, + const struct hrl_rule *filter, void *arg3, void *arg4), + const struct hrl_rule *filter, void *arg3, void *arg4); #endif /* _KERNEL */ #endif /* !_SYS_RESOURCEVAR_H_ */ ==== //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#20 (text+ko) ==== @@ -107,7 +107,9 @@ subject = "group"; else if (strcasecmp(subject, "p") == 0) subject = "process"; - else if (strcasecmp(subject, "l") == 0 || strcasecmp(subject, "c") == 0) + else if (strcasecmp(subject, "l") == 0 || + strcasecmp(subject, "c") == 0 || + strcasecmp(subject, "class") == 0) subject = "loginclass"; if (strcasecmp(subject, "user") == 0 && strlen(textid) > 0) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908021847.n72Il1ch042802>