From owner-p4-projects@FreeBSD.ORG Wed Aug 5 19:36:07 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 975B51065672; Wed, 5 Aug 2009 19:36:07 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 572A5106564A for ; Wed, 5 Aug 2009 19:36:07 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 44BAD8FC08 for ; Wed, 5 Aug 2009 19:36:07 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n75Ja7Rg091679 for ; Wed, 5 Aug 2009 19:36:07 GMT (envelope-from trasz@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n75Ja7Jk091677 for perforce@freebsd.org; Wed, 5 Aug 2009 19:36:07 GMT (envelope-from trasz@freebsd.org) Date: Wed, 5 Aug 2009 19:36:07 GMT Message-Id: <200908051936.n75Ja7Jk091677@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to trasz@freebsd.org using -f From: Edward Tomasz Napierala To: Perforce Change Reviews Cc: Subject: PERFORCE change 167048 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Aug 2009 19:36:08 -0000 http://perforce.freebsd.org/chv.cgi?CH=167048 Change 167048 by trasz@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_ */