From owner-p4-projects@FreeBSD.ORG Sun Jun 27 18:25:09 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 5A7131065673; Sun, 27 Jun 2010 18:25:09 +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 06662106566B for ; Sun, 27 Jun 2010 18:25:09 +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 E2F6F8FC08 for ; Sun, 27 Jun 2010 18:25:08 +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 o5RIP8vS065469 for ; Sun, 27 Jun 2010 18:25:08 GMT (envelope-from trasz@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o5RIP80k065467 for perforce@freebsd.org; Sun, 27 Jun 2010 18:25:08 GMT (envelope-from trasz@freebsd.org) Date: Sun, 27 Jun 2010 18:25:08 GMT Message-Id: <201006271825.o5RIP80k065467@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 Precedence: bulk Cc: Subject: PERFORCE change 180274 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Jun 2010 18:25:09 -0000 http://p4web.freebsd.org/@@180274?ac=10 Change 180274 by trasz@trasz_victim on 2010/06/27 18:24:29 Divorce containers from hrl some more. Affected files ... .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_container.c#3 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_exit.c#18 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_fork.c#14 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#76 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/container.h#3 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#45 edit Differences ... ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_container.c#3 (text+ko) ==== @@ -62,12 +62,12 @@ mtx_assert(&hrl_lock, MA_OWNED); for (i = 0; i <= HRL_RESOURCE_MAX; i++) { - KASSERT(dest->hc_resources[i] >= 0, + KASSERT(dest->c_resources[i] >= 0, ("resource usage propagation meltdown: dest < 0")); - KASSERT(src->hc_resources[i] >= 0, + KASSERT(src->c_resources[i] >= 0, ("resource usage propagation meltdown: src < 0")); - dest->hc_resources[i] += src->hc_resources[i]; - KASSERT(dest->hc_resources[i] >= 0, + dest->c_resources[i] += src->c_resources[i]; + KASSERT(dest->c_resources[i] >= 0, ("resource usage propagation meltdown: dest < 0 after addition")); } } @@ -80,14 +80,14 @@ mtx_assert(&hrl_lock, MA_OWNED); for (i = 0; i <= HRL_RESOURCE_MAX; i++) { - KASSERT(dest->hc_resources[i] >= 0, + KASSERT(dest->c_resources[i] >= 0, ("resource usage propagation meltdown: dest < 0")); - KASSERT(src->hc_resources[i] >= 0, + KASSERT(src->c_resources[i] >= 0, ("resource usage propagation meltdown: src < 0")); - KASSERT(src->hc_resources[i] <= dest->hc_resources[i], + KASSERT(src->c_resources[i] <= dest->c_resources[i], ("resource usage propagation meltdown: src > dest")); - dest->hc_resources[i] -= src->hc_resources[i]; - KASSERT(dest->hc_resources[i] >= 0, + dest->c_resources[i] -= src->c_resources[i]; + KASSERT(dest->c_resources[i] >= 0, ("resource usage propagation meltdown: dest < 0 after subtraction")); } } @@ -101,11 +101,11 @@ KASSERT(child != NULL, ("child != NULL")); KASSERT(parent != NULL, ("parent != NULL")); - for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) { - KASSERT(child->hc_parents[i] != parent, + for (i = 0; i <= CONTAINER_PARENTS_MAX; i++) { + KASSERT(child->c_parents[i] != parent, ("container already joined")); - if (child->hc_parents[i] == NULL) { - child->hc_parents[i] = parent; + if (child->c_parents[i] == NULL) { + child->c_parents[i] = parent; container_add(parent, child); return; } @@ -122,10 +122,10 @@ KASSERT(child != NULL, ("child != NULL")); KASSERT(parent != NULL, ("parent != NULL")); - for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) { - if (child->hc_parents[i] == parent) { + for (i = 0; i <= CONTAINER_PARENTS_MAX; i++) { + if (child->c_parents[i] == parent) { container_subtract(parent, child); - child->hc_parents[i] = NULL; + child->c_parents[i] = NULL; return; } } @@ -140,11 +140,11 @@ mtx_assert(&hrl_lock, MA_OWNED); KASSERT(child != NULL, ("child != NULL")); - for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) { - if (child->hc_parents[i] == NULL) + for (i = 0; i <= CONTAINER_PARENTS_MAX; i++) { + if (child->c_parents[i] == NULL) continue; - container_subtract(child->hc_parents[i], child); - child->hc_parents[i] = NULL; + container_subtract(child->c_parents[i], child); + child->c_parents[i] = NULL; } } @@ -154,11 +154,11 @@ int i; for (i = 0; i <= HRL_RESOURCE_MAX; i++) - KASSERT(container->hc_resources[i] == 0, - ("container->hc_resources[%d] != NULL", i)); - for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) - KASSERT(container->hc_parents[i] == NULL, - ("container->hc_parents[%d] != NULL", i)); + KASSERT(container->c_resources[i] == 0, + ("container->c_resources[%d] != NULL", i)); + for (i = 0; i <= CONTAINER_PARENTS_MAX; i++) + KASSERT(container->c_parents[i] == NULL, + ("container->c_parents[%d] != NULL", i)); } void @@ -168,12 +168,12 @@ mtx_lock(&hrl_lock); for (i = 0; i <= HRL_RESOURCE_MAX; i++) { - if (container->hc_resources[i] != 0) + if (container->c_resources[i] != 0) printf("destroying non-empty container: " "%ju allocated for resource %s", - container->hc_resources[i], + container->c_resources[i], hrl_resource_name(i)); - container->hc_resources[i] = 0; + container->c_resources[i] = 0; } container_leave_parents(container); @@ -194,18 +194,18 @@ KASSERT(container != NULL, ("NULL container")); for (resource = 0; resource <= HRL_RESOURCE_MAX; resource++) { - KASSERT(container->hc_resources[resource] >= 0, + KASSERT(container->c_resources[resource] >= 0, ("resource usage propagation meltdown: resource < 0")); } - for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) { - parent = container->hc_parents[i]; + for (i = 0; i <= CONTAINER_PARENTS_MAX; i++) { + parent = container->c_parents[i]; if (parent == NULL); continue; container_assert(parent); for (resource = 0; resource <= HRL_RESOURCE_MAX; resource++) { - KASSERT(parent->hc_resources[resource] >= - container->hc_resources[resource], + KASSERT(parent->c_resources[resource] >= + container->c_resources[resource], ("resource usage propagation meltdown: child > parent")); } } @@ -226,11 +226,11 @@ mtx_assert(&hrl_lock, MA_OWNED); KASSERT(container != NULL, ("NULL container")); - container->hc_resources[resource] += amount; - for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) { - if (container->hc_parents[i] == NULL) + container->c_resources[resource] += amount; + for (i = 0; i <= CONTAINER_PARENTS_MAX; i++) { + if (container->c_parents[i] == NULL) continue; - container_alloc_resource(container->hc_parents[i], resource, amount); + container_alloc_resource(container->c_parents[i], resource, amount); } #ifdef DIAGNOSTIC container_assert(container); @@ -286,7 +286,7 @@ hrl_resource_name(resource), amount)); mtx_lock(&hrl_lock); - diff = amount - p->p_container.hc_resources[resource]; + diff = amount - p->p_container.c_resources[resource]; if (diff > 0) { error = hrl_enforce_proc(p, resource, diff); if (error) { @@ -315,11 +315,76 @@ hrl_resource_name(resource), amount)); mtx_lock(&hrl_lock); - KASSERT(amount <= p->p_container.hc_resources[resource], + KASSERT(amount <= p->p_container.c_resources[resource], ("hrl_free: freeing %ju of %s, which is more than allocated " "%ld for %s (pid %d)", amount, hrl_resource_name(resource), - p->p_container.hc_resources[resource], p->p_comm, p->p_pid)); + p->p_container.c_resources[resource], p->p_comm, p->p_pid)); container_alloc_resource(&p->p_container, resource, -amount); mtx_unlock(&hrl_lock); } + +static int +container_resource_inheritable(int resource) +{ + + switch (resource) { + case HRL_RESOURCE_MAXPROCESSES: + return (0); + default: + return (1); + } +} + +void +container_proc_exit(struct proc *p) +{ + /* + * XXX: Free these three some other way. + */ + hrl_allocated(p, HRL_RESOURCE_FILESIZE, 0); + hrl_allocated(p, HRL_RESOURCE_COREDUMPSIZE, 0); + hrl_allocated(p, HRL_RESOURCE_PTY, 0); + + mtx_lock(&hrl_lock); + container_destroy(&p->p_container); + mtx_unlock(&hrl_lock); +} + +/* + * Inherit resource usage information and copy limits from the parent + * process to the child. + */ +void +container_proc_fork(struct proc *parent, struct proc *child) +{ + int i; + struct container *container; + + PROC_LOCK(parent); + PROC_LOCK(child); + mtx_lock(&hrl_lock); + + /* + * Create container for the child process and inherit containing + * containers from the parent. + */ + container_create(&child->p_container); + for (i = 0; i <= CONTAINER_PARENTS_MAX; i++) { + container = parent->p_container.c_parents[i]; + if (container == NULL) + continue; + container_join(&child->p_container, container); + } + + for (i = 0; i <= HRL_RESOURCE_MAX; i++) { + if (parent->p_container.c_resources[i] != 0 && + container_resource_inheritable(i)) + hrl_allocated(child, i, + parent->p_container.c_resources[i]); + } + + mtx_unlock(&hrl_lock); + PROC_UNLOCK(child); + PROC_UNLOCK(parent); +} ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_exit.c#18 (text+ko) ==== @@ -768,7 +768,11 @@ */ (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); hrl_free(p->p_pptr, HRL_RESOURCE_MAXPROCESSES, 1); - hrl_proc_exiting(p); + + /* + * Destroy resource container associated with the process. + */ + container_proc_exit(p); /* * Free credentials, arguments, and sigacts. ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_fork.c#14 (text+ko) ==== @@ -739,6 +739,11 @@ } /* + * Initialize resource container for the child process. + */ + container_proc_fork(p1, p2); + + /* * Both processes are set up, now check if any loadable modules want * to adjust anything. * What if they have an error? XXX ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#76 (text+ko) ==== @@ -124,18 +124,6 @@ MALLOC_DEFINE(M_HRL, "hrl", "Hierarchical Resource Limits"); -static int -hrl_resource_inheritable(int resource) -{ - - switch (resource) { - case HRL_RESOURCE_MAXPROCESSES: - return (0); - default: - return (1); - } -} - static const char * hrl_subject_type_name(int subject) { @@ -210,20 +198,20 @@ switch (rule->hr_per) { case HRL_SUBJECT_TYPE_PROCESS: available = rule->hr_amount - - p->p_container.hc_resources[resource]; + p->p_container.c_resources[resource]; break; case HRL_SUBJECT_TYPE_USER: available = rule->hr_amount - - cred->cr_ruidinfo->ui_container.hc_resources[resource]; + cred->cr_ruidinfo->ui_container.c_resources[resource]; break; case HRL_SUBJECT_TYPE_LOGINCLASS: available = rule->hr_amount - - cred->cr_loginclass->lc_container.hc_resources[resource]; + cred->cr_loginclass->lc_container.c_resources[resource]; available = INT64_MAX; /* XXX */ break; case HRL_SUBJECT_TYPE_JAIL: available = rule->hr_amount - - cred->cr_prison->pr_container.hc_resources[resource]; + cred->cr_prison->pr_container.c_resources[resource]; break; default: panic("hrl_compute_available: unknown per %d", @@ -300,9 +288,9 @@ /* * XXX: We should sort the rules somewhat, so that 'log' and 'sig' * rules come before before 'deny', to spare iterations over - * the p_container.hc_rule_links. + * the p_container.c_rule_links. */ - LIST_FOREACH(link, &p->p_container.hc_rule_links, hrl_next) { + LIST_FOREACH(link, &p->p_container.c_rule_links, hrl_next) { rule = link->hrl_rule; if (rule->hr_resource != resource) continue; @@ -380,7 +368,7 @@ for (i = 0; i <= HRL_RESOURCE_MAX; i++) (*availablep)[i] = INT64_MAX; - LIST_FOREACH(link, &p->p_container.hc_rule_links, hrl_next) { + LIST_FOREACH(link, &p->p_container.c_rule_links, hrl_next) { rule = link->hrl_rule; resource = rule->hr_resource; available = hrl_available_resource(p, rule); @@ -522,7 +510,7 @@ link->hrl_rule = rule; mtx_lock(&hrl_lock); - LIST_INSERT_HEAD(&container->hc_rule_links, link, hrl_next); + LIST_INSERT_HEAD(&container->c_rule_links, link, hrl_next); mtx_unlock(&hrl_lock); } @@ -540,7 +528,7 @@ hrl_rule_acquire(rule); link->hrl_rule = rule; - LIST_INSERT_HEAD(&container->hc_rule_links, link, hrl_next); + LIST_INSERT_HEAD(&container->c_rule_links, link, hrl_next); return (0); } @@ -557,7 +545,7 @@ struct hrl_rule_link *link, *linktmp; mtx_lock(&hrl_lock); - LIST_FOREACH_SAFE(link, &container->hc_rule_links, hrl_next, linktmp) { + LIST_FOREACH_SAFE(link, &container->c_rule_links, hrl_next, linktmp) { if (!hrl_rule_matches(link->hrl_rule, filter)) continue; @@ -1129,7 +1117,7 @@ sb = sbuf_new_auto(); for (i = 0; i <= HRL_RESOURCE_MAX; i++) { sbuf_printf(sb, "%s=%jd,", hrl_resource_name(i), - container->hc_resources[i]); + container->c_resources[i]); } sbuf_setpos(sb, sbuf_len(sb) - 1); return (sb); @@ -1224,7 +1212,7 @@ mtx_assert(&hrl_lock, MA_OWNED); - LIST_FOREACH(link, &container->hc_rule_links, hrl_next) { + LIST_FOREACH(link, &container->c_rule_links, hrl_next) { if (!hrl_rule_matches(link->hrl_rule, filter)) continue; hrl_rule_to_sbuf(sb, link->hrl_rule); @@ -1265,7 +1253,7 @@ sx_assert(&allproc_lock, SA_LOCKED); FOREACH_PROC_IN_SYSTEM(p) { mtx_lock(&hrl_lock); - LIST_FOREACH(link, &p->p_container.hc_rule_links, hrl_next) { + LIST_FOREACH(link, &p->p_container.c_rule_links, hrl_next) { /* * Non-process rules will be added to the buffer later. * Adding them here would result in duplicated output. @@ -1350,7 +1338,7 @@ KASSERT(sb != NULL, ("sbuf_new failed")); mtx_lock(&hrl_lock); - LIST_FOREACH(link, &filter->hr_subject.hs_proc->p_container.hc_rule_links, hrl_next) { + LIST_FOREACH(link, &filter->hr_subject.hs_proc->p_container.c_rule_links, hrl_next) { hrl_rule_to_sbuf(sb, link->hrl_rule); sbuf_printf(sb, ","); } @@ -1492,7 +1480,7 @@ /* * Remove rules that are no longer applicable with the new ucred. */ - LIST_FOREACH(link, &p->p_container.hc_rule_links, hrl_next) { + LIST_FOREACH(link, &p->p_container.c_rule_links, hrl_next) { switch (link->hrl_rule->hr_subject_type) { case HRL_SUBJECT_TYPE_PROCESS: continue; @@ -1522,7 +1510,7 @@ * Add rules for the new ucred and move between containers where applicable. */ if (newuip != olduip) { - LIST_FOREACH(link, &newuip->ui_container.hc_rule_links, hrl_next) { + LIST_FOREACH(link, &newuip->ui_container.c_rule_links, hrl_next) { error = hrl_container_add_rule_locked(&p->p_container, link->hrl_rule); KASSERT(error == 0, ("XXX: better error handling needed")); } @@ -1531,7 +1519,7 @@ container_join(&p->p_container, &newuip->ui_container); } if (newlc != oldlc) { - LIST_FOREACH(link, &newlc->lc_container.hc_rule_links, hrl_next) { + LIST_FOREACH(link, &newlc->lc_container.c_rule_links, hrl_next) { error = hrl_container_add_rule_locked(&p->p_container, link->hrl_rule); KASSERT(error == 0, ("XXX: better error handling needed")); } @@ -1540,7 +1528,7 @@ container_join(&p->p_container, &newlc->lc_container); } if (newpr != oldpr) { - LIST_FOREACH(link, &newpr->pr_container.hc_rule_links, hrl_next) { + LIST_FOREACH(link, &newpr->pr_container.c_rule_links, hrl_next) { error = hrl_container_add_rule_locked(&p->p_container, link->hrl_rule); KASSERT(error == 0, ("XXX: better error handling needed")); } @@ -1553,47 +1541,26 @@ } /* - * Inherit resource usage information and copy limits from the parent - * process to the child. + * Assign HRL rules to the newly created process. */ static void hrl_proc_fork(void *arg __unused, struct proc *parent, struct proc *child, int flags __unused) { - int error, i; + int error; struct hrl_rule_link *link; struct hrl_rule *rule; - struct container *container; PROC_LOCK(parent); PROC_LOCK(child); mtx_lock(&hrl_lock); /* - * Create container for the child process and inherit containing - * containers from the parent. - */ - container_create(&child->p_container); - for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) { - container = parent->p_container.hc_parents[i]; - if (container == NULL) - continue; - container_join(&child->p_container, container); - } - - for (i = 0; i <= HRL_RESOURCE_MAX; i++) { - if (parent->p_container.hc_resources[i] != 0 && - hrl_resource_inheritable(i)) - hrl_allocated(child, i, - parent->p_container.hc_resources[i]); - } - - /* * Go through limits applicable to the parent and assign them to the child. * Rules with 'process' subject have to be duplicated in order to make their * hr_subject point to the new process. */ - LIST_FOREACH(link, &parent->p_container.hc_rule_links, hrl_next) { + LIST_FOREACH(link, &parent->p_container.c_rule_links, hrl_next) { if (link->hrl_rule->hr_subject_type == HRL_SUBJECT_TYPE_PROCESS) { rule = hrl_rule_duplicate(link->hrl_rule, M_NOWAIT); KASSERT(rule != NULL, ("XXX: better error handling needed")); @@ -1614,21 +1581,6 @@ PROC_UNLOCK(parent); } -void -hrl_proc_exiting(struct proc *p) -{ - /* - * XXX: Free these three some other way. - */ - hrl_allocated(p, HRL_RESOURCE_FILESIZE, 0); - hrl_allocated(p, HRL_RESOURCE_COREDUMPSIZE, 0); - hrl_allocated(p, HRL_RESOURCE_PTY, 0); - - mtx_lock(&hrl_lock); - container_destroy(&p->p_container); - mtx_unlock(&hrl_lock); -} - /* * Go through the process' limits, freeing them. */ @@ -1638,8 +1590,8 @@ struct hrl_rule_link *link; mtx_lock(&hrl_lock); - while (!LIST_EMPTY(&p->p_container.hc_rule_links)) { - link = LIST_FIRST(&p->p_container.hc_rule_links); + while (!LIST_EMPTY(&p->p_container.c_rule_links)) { + link = LIST_FIRST(&p->p_container.c_rule_links); LIST_REMOVE(link, hrl_next); hrl_rule_release(link->hrl_rule); uma_zfree(hrl_rule_link_zone, link); ==== //depot/projects/soc2009/trasz_limits/sys/sys/container.h#3 (text+ko) ==== @@ -46,7 +46,7 @@ * one parent container, loginclass and uidinfo structures have none. * This may change when - and if - we add per-group resource limits. */ -#define HRL_HC_PARENTS_MAX 3 +#define CONTAINER_PARENTS_MAX 3 #define HRL_RESOURCE_UNDEFINED -1 #define HRL_RESOURCE_CPUTIME 0x0000 @@ -64,7 +64,6 @@ #define HRL_RESOURCE_SWAP 0x000c #define HRL_RESOURCE_MAX HRL_RESOURCE_SWAP - /* * 'container' defines resource consumption for a particular * subject, such as process or jail. Containers form a graph - each @@ -85,13 +84,11 @@ * This structure must be filled with zeroes initially. */ struct container { - int64_t hc_resources[HRL_RESOURCE_MAX + 1]; - struct container *hc_parents[HRL_HC_PARENTS_MAX + 1]; - LIST_HEAD(, hrl_rule_link) hc_rule_links; + int64_t c_resources[HRL_RESOURCE_MAX + 1]; + struct container *c_parents[CONTAINER_PARENTS_MAX + 1]; + LIST_HEAD(, hrl_rule_link) c_rule_links; }; -#ifdef _KERNEL - int hrl_alloc(struct proc *p, int object, uint64_t amount); int hrl_allocated(struct proc *p, int object, uint64_t amount); void hrl_free(struct proc *p, int object, uint64_t amount); @@ -102,6 +99,7 @@ void container_join(struct container *child, struct container *parent); void container_leave(struct container *child, struct container *parent); -#endif /* _KERNEL */ +void container_proc_exit(struct proc *p); +void container_proc_fork(struct proc *parent, struct proc *child); #endif /* !_CONTAINER_H_ */ ==== //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#45 (text+ko) ==== @@ -110,8 +110,6 @@ #ifdef _KERNEL -void hrl_proc_exiting(struct proc *p); - void hrl_proc_init(struct proc *p); void hrl_proc_ucred_changing(struct proc *p, struct ucred *newcred);