PERFORCE change 166939 for review
Edward Tomasz Napierala
trasz at FreeBSD.org
Sun Aug 2 18:47:03 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=166939
Change 166939 by trasz at 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) {
More information about the p4-projects
mailing list