PERFORCE change 167048 for review
Edward Tomasz Napierala
trasz at FreeBSD.org
Wed Aug 5 19:36:08 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=167048
Change 167048 by trasz at trasz_anger on 2009/08/05 19:35:23
Rewrite hrl_get_rules(2) and hrl_get_limits(2). Previous
approach was racy.
Affected files ...
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#46 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_loginclass.c#5 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#21 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#29 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/loginclass.h#3 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/resourcevar.h#11 edit
Differences ...
==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#46 (text+ko) ====
@@ -111,8 +111,8 @@
static void hrl_compute_available(struct proc *p, int64_t (*availablep)[],
struct hrl_rule *(*rulesp)[]);
-static struct sbuf *hrl_rules_to_sbuf(struct hrl_rule *usage, int nrules);
static int hrl_rule_fully_specified(const struct hrl_rule *rule);
+static void hrl_rule_to_sbuf(struct sbuf *sb, const struct hrl_rule *rule);
MALLOC_DEFINE(M_HRL, "hrl", "Hierarchical Resource Limits");
@@ -273,7 +273,8 @@
printf("hrl_enforce_proc: XXX, \"delay\" unimplemented.\n");
return (0);
case HRL_ACTION_LOG:
- sb = hrl_rules_to_sbuf(rules[resource], 1);
+ sb = sbuf_new_auto();
+ hrl_rule_to_sbuf(sb, rules[resource]);
sbuf_finish(sb);
printf("resource limit \"%s\" exceeded by process %d (%s), "
"uid %d\n", sbuf_data(sb), p->p_pid, p->p_comm,
@@ -1026,7 +1027,7 @@
}
static int
-hrl_rule_remove_callback(struct hrl_limits_head *limits, const struct hrl_rule *filter, void *arg3, void *arg4 __unused)
+hrl_rule_remove_callback(struct hrl_limits_head *limits, const struct hrl_rule *filter, void *arg3)
{
int *found = (int *)arg3;
@@ -1057,11 +1058,11 @@
return (ESRCH);
}
- error = loginclass_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found, NULL);
+ error = loginclass_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found);
KASSERT(error == 0, ("loginclass_limits_foreach failed"));
- error = ui_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found, NULL);
+ error = ui_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found);
KASSERT(error == 0, ("ui_limits_foreach failed"));
- error = gi_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found, NULL);
+ error = gi_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found);
KASSERT(error == 0, ("gi_limits_foreach failed"));
sx_slock(&proctree_lock);
@@ -1077,40 +1078,31 @@
return (ESRCH);
}
-static struct sbuf *
-hrl_rules_to_sbuf(struct hrl_rule *rules, int nrules)
+/*
+ * Appends a rule to the sbuf.
+ */
+static void
+hrl_rule_to_sbuf(struct sbuf *sb, const struct hrl_rule *rule)
{
- int i;
- struct sbuf *sb;
-
- sb = sbuf_new_auto();
- for (i = 0; i < nrules; i++) {
- if (rules[i].hr_subject == HRL_SUBJECT_LOGINCLASS) {
- KASSERT(rules[i].hr_subject_id != HRL_SUBJECT_ID_UNDEFINED,
- ("rules[i].hr_subject_id != HRL_SUBJECT_ID_UNDEFINED"));
- sbuf_printf(sb, "%s:%s:%s:%s=%jd",
- hrl_subject_name(rules[i].hr_subject),
- ((struct loginclass *)(long)rules[i].hr_subject_id)->lc_name,
- hrl_resource_name(rules[i].hr_resource),
- hrl_action_name(rules[i].hr_action),
- rules[i].hr_amount);
- } else {
- sbuf_printf(sb, "%s:%d:%s:%s=%jd",
- hrl_subject_name(rules[i].hr_subject),
- (int)rules[i].hr_subject_id,
- hrl_resource_name(rules[i].hr_resource),
- hrl_action_name(rules[i].hr_action),
- rules[i].hr_amount);
- }
- if (rules[i].hr_per != rules[i].hr_subject)
- sbuf_printf(sb, "/%s,",
- hrl_subject_name(rules[i].hr_per));
- else
- sbuf_printf(sb, ",");
+ if (rule->hr_subject == HRL_SUBJECT_LOGINCLASS) {
+ KASSERT(rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED,
+ ("rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED"));
+ sbuf_printf(sb, "%s:%s:%s:%s=%jd",
+ hrl_subject_name(rule->hr_subject),
+ ((struct loginclass *)(long)rule->hr_subject_id)->lc_name,
+ hrl_resource_name(rule->hr_resource),
+ hrl_action_name(rule->hr_action),
+ rule->hr_amount);
+ } else {
+ sbuf_printf(sb, "%s:%d:%s:%s=%jd",
+ hrl_subject_name(rule->hr_subject),
+ (int)rule->hr_subject_id,
+ hrl_resource_name(rule->hr_resource),
+ hrl_action_name(rule->hr_action),
+ rule->hr_amount);
}
- if (sbuf_len(sb) > 0)
- sbuf_setpos(sb, sbuf_len(sb) - 1);
- return (sb);
+ if (rule->hr_per != rule->hr_subject)
+ sbuf_printf(sb, "/%s", hrl_subject_name(rule->hr_per));
}
/*
@@ -1284,22 +1276,18 @@
}
static int
-hrl_get_rules_callback(struct hrl_limits_head *limits, const struct hrl_rule *filter, void *arg3, void *arg4)
+hrl_get_rules_callback(struct hrl_limits_head *limits, const struct hrl_rule *filter, void *arg3)
{
struct hrl_limit *limit;
- struct hrl_rule *buf = (struct hrl_rule *)arg3;
- int copied = 0, *available = (int *)arg4;
+ struct sbuf *sb = (struct sbuf *)arg3;
mtx_assert(&hrl_lock, MA_OWNED);
LIST_FOREACH(limit, limits, hl_next) {
- if (*available <= 0)
- return (ERANGE);
if (!hrl_rule_matches(limit->hl_rule, filter))
continue;
- *(buf + copied) = *limit->hl_rule;
- copied++;
- (*available)--;
+ hrl_rule_to_sbuf(sb, limit->hl_rule);
+ sbuf_printf(sb, ",");
}
return (0);
@@ -1308,10 +1296,11 @@
int
hrl_get_rules(struct thread *td, struct hrl_get_rules_args *uap)
{
- int error, copied, bufsize = HRL_MAX_RULES, available;
- char *inputstr;
- struct sbuf *outputsbuf;
- struct hrl_rule *filter, *buf;
+ int error;
+ size_t bufsize = HRL_MAX_RULES;
+ char *inputstr, *buf;
+ struct sbuf *sb;
+ struct hrl_rule *filter;
struct hrl_limit *limit;
struct proc *p;
@@ -1325,20 +1314,14 @@
return (EINVAL);
again:
- buf = malloc(bufsize * sizeof(*buf), M_HRL, M_WAITOK);
- available = bufsize;
- copied = 0;
+ buf = malloc(bufsize, M_HRL, M_WAITOK);
+ sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN);
+ KASSERT(sb != NULL, ("sbuf_new failed"));
+
sx_slock(&proctree_lock);
FOREACH_PROC_IN_SYSTEM(p) {
mtx_lock(&hrl_lock);
LIST_FOREACH(limit, &p->p_limits, hl_next) {
- if (available <= 0) {
- mtx_unlock(&hrl_lock);
- sx_sunlock(&proctree_lock);
- bufsize *= 4;
- free(buf, M_HRL);
- goto again;
- }
/*
* Non-process rules will be added to the buffer later.
* Adding them here would result in duplicated output.
@@ -1347,33 +1330,32 @@
continue;
if (!hrl_rule_matches(limit->hl_rule, filter))
continue;
- *(buf + copied) = *limit->hl_rule;
- copied++;
- available--;
+ hrl_rule_to_sbuf(sb, limit->hl_rule);
+ sbuf_printf(sb, ",");
}
mtx_unlock(&hrl_lock);
}
sx_sunlock(&proctree_lock);
mtx_lock(&hrl_lock);
- loginclass_limits_foreach(hrl_get_rules_callback, filter,
- buf + copied, &available);
- copied = bufsize - available;
- ui_limits_foreach(hrl_get_rules_callback, filter,
- buf + copied, &available);
- copied = bufsize - available;
- gi_limits_foreach(hrl_get_rules_callback, filter,
- buf + copied, &available);
+ loginclass_limits_foreach(hrl_get_rules_callback, filter, sb);
+ ui_limits_foreach(hrl_get_rules_callback, filter, sb);
+ gi_limits_foreach(hrl_get_rules_callback, filter, sb);
mtx_unlock(&hrl_lock);
- if (available <= 0) {
+ if (sbuf_overflowed(sb)) {
+ sbuf_delete(sb);
+ free(buf, M_HRL);
bufsize *= 4;
- free(buf, M_HRL);
goto again;
}
- outputsbuf = hrl_rules_to_sbuf(buf, copied);
+ /*
+ * Remove trailing ",".
+ */
+ if (sbuf_len(sb) > 0)
+ sbuf_setpos(sb, sbuf_len(sb) - 1);
- error = hrl_write_outbuf(outputsbuf, uap->outbufp, uap->outbuflen);
+ error = hrl_write_outbuf(sb, uap->outbufp, uap->outbuflen);
hrl_rule_release(filter);
free(buf, M_HRL);
@@ -1383,10 +1365,11 @@
int
hrl_get_limits(struct thread *td, struct hrl_get_limits_args *uap)
{
- int error, copied, maxcopied = HRL_MAX_RULES;
- char *inputstr;
- struct sbuf *outputsbuf;
- struct hrl_rule *filter, *buf;
+ int error;
+ size_t bufsize = HRL_MAX_RULES;
+ char *inputstr, *buf;
+ struct sbuf *sb;
+ struct hrl_rule *filter;
struct hrl_limit *limit;
struct proc *p;
@@ -1400,50 +1383,52 @@
return (EINVAL);
if (filter->hr_subject == HRL_SUBJECT_UNDEFINED) {
- error = EINVAL;
- goto out;
+ hrl_rule_release(filter);
+ return (EINVAL);
}
if (filter->hr_subject_id == HRL_SUBJECT_ID_UNDEFINED) {
- error = EINVAL;
- goto out;
+ hrl_rule_release(filter);
+ return (EINVAL);
}
if (filter->hr_subject != HRL_SUBJECT_PROCESS) {
- error = EOPNOTSUPP;
- goto out;
+ hrl_rule_release(filter);
+ return (EOPNOTSUPP);
}
-again:
- buf = malloc(maxcopied * sizeof(*buf), M_HRL, M_WAITOK);
- copied = 0;
-
p = pfind(filter->hr_subject_id);
if (p == NULL) {
- error = ESRCH;
- goto out;
+ hrl_rule_release(filter);
+ return (ESRCH);
}
+
+again:
+ buf = malloc(bufsize, M_HRL, M_WAITOK);
+ sb = sbuf_new(NULL, buf, bufsize, SBUF_FIXEDLEN);
+ KASSERT(sb != NULL, ("sbuf_new failed"));
+
mtx_lock(&hrl_lock);
LIST_FOREACH(limit, &p->p_limits, hl_next) {
- if (copied >= maxcopied) {
- mtx_unlock(&hrl_lock);
- PROC_UNLOCK(p);
- maxcopied *= 4;
- free(buf, M_HRL);
- goto again;
- }
- *(buf + copied) = *limit->hl_rule;
- copied++;
+ hrl_rule_to_sbuf(sb, limit->hl_rule);
+ sbuf_printf(sb, ",");
}
mtx_unlock(&hrl_lock);
PROC_UNLOCK(p);
- if (error)
- goto out;
+ if (sbuf_overflowed(sb)) {
+ sbuf_delete(sb);
+ free(buf, M_HRL);
+ bufsize *= 4;
+ goto again;
+ }
- outputsbuf = hrl_rules_to_sbuf(buf, copied);
+ /*
+ * Remove trailing ",".
+ */
+ if (sbuf_len(sb) > 0)
+ sbuf_setpos(sb, sbuf_len(sb) - 1);
- error = hrl_write_outbuf(outputsbuf, uap->outbufp, uap->outbuflen);
-out:
+ error = hrl_write_outbuf(sb, uap->outbufp, uap->outbuflen);
hrl_rule_release(filter);
free(buf, M_HRL);
return (error);
==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_loginclass.c#5 (text+ko) ====
@@ -204,14 +204,14 @@
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)
+ const struct hrl_rule *filter, void *arg3),
+ const struct hrl_rule *filter, void *arg3)
{
int error;
struct loginclass *lc;
LIST_FOREACH(lc, &loginclasses, lc_next) {
- error = (callback)(&lc->lc_limits, filter, arg3, arg4);
+ error = (callback)(&lc->lc_limits, filter, arg3);
if (error)
return (error);
}
==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#21 (text+ko) ====
@@ -1414,8 +1414,8 @@
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)
+ const struct hrl_rule *filter, void *arg3),
+ const struct hrl_rule *filter, void *arg3)
{
int error;
struct uidinfo *uip, *nextuip;
@@ -1425,7 +1425,7 @@
for (uih = &uihashtbl[uihash]; uih >= uihashtbl; uih--) {
for (uip = LIST_FIRST(uih); uip; uip = nextuip) {
nextuip = LIST_NEXT(uip, ui_hash);
- error = (callback)(&uip->ui_limits, filter, arg3, arg4);
+ error = (callback)(&uip->ui_limits, filter, arg3);
if (error) {
rw_runlock(&uihashtbl_lock);
return (error);
@@ -1584,8 +1584,8 @@
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)
+ const struct hrl_rule *filter, void *arg3),
+ const struct hrl_rule *filter, void *arg3)
{
int error;
struct gidinfo *gip, *nextgip;
@@ -1595,7 +1595,7 @@
for (gih = &gihashtbl[gihash]; gih >= gihashtbl; gih--) {
for (gip = LIST_FIRST(gih); gip; gip = nextgip) {
nextgip = LIST_NEXT(gip, gi_hash);
- error = (callback)(&gip->gi_limits, filter, arg3, arg4);
+ error = (callback)(&gip->gi_limits, filter, arg3);
if (error) {
rw_runlock(&gihashtbl_lock);
return (error);
==== //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#29 (text+ko) ====
@@ -138,7 +138,6 @@
void hrl_usage_subtract(struct hrl_usage *dest, const struct hrl_usage *src);
void hrl_proc_exiting(struct proc *p);
-
void hrl_proc_loginclass_changed(struct proc *p);
void hrl_proc_ucred_changed(struct proc *p);
==== //depot/projects/soc2009/trasz_limits/sys/sys/loginclass.h#3 (text+ko) ====
@@ -42,8 +42,8 @@
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);
+ const struct hrl_rule *filter, void *arg3),
+ const struct hrl_rule *filter, void *arg3);
#endif /* !_SYS_LOGINCLASS_H_ */
==== //depot/projects/soc2009/trasz_limits/sys/sys/resourcevar.h#11 (text+ko) ====
@@ -160,8 +160,8 @@
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);
+ const struct hrl_rule *filter, void *arg3),
+ const struct hrl_rule *filter, void *arg3);
struct gidinfo
*gifind(gid_t gid);
struct gidinfo
@@ -170,8 +170,8 @@
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);
+ const struct hrl_rule *filter, void *arg3),
+ const struct hrl_rule *filter, void *arg3);
#endif /* _KERNEL */
#endif /* !_SYS_RESOURCEVAR_H_ */
More information about the p4-projects
mailing list