From owner-p4-projects@FreeBSD.ORG Sat Jun 13 19:53:09 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 46FB31065670; Sat, 13 Jun 2009 19:53: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 06CEA106566B for ; Sat, 13 Jun 2009 19:53: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 E7F5A8FC17 for ; Sat, 13 Jun 2009 19:53:08 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n5DJr8MN057940 for ; Sat, 13 Jun 2009 19:53:08 GMT (envelope-from trasz@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n5DJr8s2057938 for perforce@freebsd.org; Sat, 13 Jun 2009 19:53:08 GMT (envelope-from trasz@freebsd.org) Date: Sat, 13 Jun 2009 19:53:08 GMT Message-Id: <200906131953.n5DJr8s2057938@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 164289 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: Sat, 13 Jun 2009 19:53:10 -0000 http://perforce.freebsd.org/chv.cgi?CH=164289 Change 164289 by trasz@trasz_victim on 2009/06/13 19:52:47 WIP on exporting the accounting data to the userland. Affected files ... .. //depot/projects/soc2009/trasz_limits/sys/compat/freebsd32/syscalls.master#3 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/init_sysent.c#4 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#7 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/syscalls.c#3 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/syscalls.master#3 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/systrace_args.c#3 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#6 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/syscall.h#3 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/syscall.mk#3 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/sysproto.h#3 edit .. //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#6 edit Differences ... ==== //depot/projects/soc2009/trasz_limits/sys/compat/freebsd32/syscalls.master#3 (text+ko) ==== @@ -875,5 +875,4 @@ 507 AUE_NULL STD { int freebsd32_jail_set(struct iovec32 *iovp, \ unsigned int iovcnt, int flags); } 508 AUE_NULL NOPROTO { int jail_remove(int jid); } -509 AUE_NULL STD { int hrl_get(struct hrl_limit **bufp, int nentries, int *required); } -510 AUE_NULL STD { int hrl_set(struct hrl_limit **bufp, int nentries); } +509 AUE_NULL STD { int hrl(int op, const void inbufp, size_t *inbuflen, void *outbufp, size_t outbuflen); } ==== //depot/projects/soc2009/trasz_limits/sys/kern/init_sysent.c#4 (text+ko) ==== @@ -2,8 +2,8 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/kern/init_sysent.c,v 1.248 2009/06/01 16:14:38 rwatson Exp $ - * created from FreeBSD: head/sys/kern/syscalls.master 191673 2009-04-29 21:14:15Z jamie + * $FreeBSD$ + * created from FreeBSD: src/sys/kern/syscalls.master,v 1.250 2009/04/29 21:14:15 jamie Exp */ #include "opt_compat.h" @@ -537,6 +537,5 @@ { AS(jail_get_args), (sy_call_t *)jail_get, AUE_NULL, NULL, 0, 0, 0 }, /* 506 = jail_get */ { AS(jail_set_args), (sy_call_t *)jail_set, AUE_NULL, NULL, 0, 0, 0 }, /* 507 = jail_set */ { AS(jail_remove_args), (sy_call_t *)jail_remove, AUE_NULL, NULL, 0, 0, 0 }, /* 508 = jail_remove */ - { AS(hrl_get_args), (sy_call_t *)hrl_get, AUE_NULL, NULL, 0, 0, 0 }, /* 509 = hrl_get */ - { AS(hrl_set_args), (sy_call_t *)hrl_set, AUE_NULL, NULL, 0, 0, 0 }, /* 510 = hrl_set */ + { AS(hrl_args), (sy_call_t *)hrl, AUE_NULL, NULL, 0, 0, 0 }, /* 509 = hrl */ }; ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#7 (text+ko) ==== @@ -45,7 +45,7 @@ #include struct hrl_node { - struct hrl_rule hn_rule; + struct hrl_rule hn_rule; RB_ENTRY(hrl_node) hn_next; }; @@ -93,7 +93,6 @@ static void hrl_init(void); SYSINIT(hrl, SI_SUB_RUN_SCHEDULER, SI_ORDER_SECOND, hrl_init, NULL); -static int nhrls = 0; static uma_zone_t hrl_zone; static struct mtx hrl_lock; @@ -169,7 +168,6 @@ if (node != NULL) { node = RB_REMOVE(hrl_tree, &hrls, node); KASSERT(node != NULL, ("node removal failed")); - nhrls--; } mtx_unlock(&hrl_lock); if (node != NULL) @@ -184,12 +182,10 @@ *node = searched; mtx_lock(&hrl_lock); existing = RB_INSERT(hrl_tree, &hrls, node); - if (existing != NULL) { + if (existing != NULL) existing->hn_rule.hr_amount = amount; - } else { + else node->hn_rule.hr_amount = amount; - nhrls++; - } mtx_unlock(&hrl_lock); if (existing != NULL) uma_zfree(hrl_zone, node); @@ -222,89 +218,16 @@ } #endif -int -hrl_set(struct thread *td, struct hrl_set_args *uap) +static int +hrl_get_rules(struct thread *td, void *bufp, size_t buflen) { -#if 0 - int error; - size_t buflen; - struct hrl_rule *newlimits; - - error = priv_check(td, PRIV_HRL_GET); - if (error) - return (error); - - /* - * XXX: Check for being in jail? - */ - - if (uap->nentries < 0 || uap->nentries > HRL_MAX_LIMITS) - return (EINVAL); - - /* - * Removing all the limits? - */ - if (uap->nentries == 0) { - mtx_lock(&hrl_lock); - free(limits, M_HRL); - limits = NULL; - nhrls = 0; - mtx_unlock(&hrl_lock); - - return (0); - } - - buflen = sizeof(struct hrl_rule) * uap->nentries; - - newlimits = malloc(buflen, M_HRL, M_WAITOK); - error = copyin(uap->bufp, newlimits, buflen); - if (error) - goto out; - - error = hrl_check(newlimits, uap->nentries); - if (error) - goto out; - - mtx_lock(&hrl_lock); - - if (limits != NULL) - free(limits, M_HRL); - - limits = newlimits; - nhrls = uap->nentries; - - mtx_unlock(&hrl_lock); - - return (0); - -out: - free(newlimits, M_HRL); - return (error); -#else - return (ENOSYS); -#endif -} - -int -hrl_get(struct thread *td, struct hrl_get_args *uap) -{ - int error = 0, copied = 0; - size_t buflen; + int error, copied = 0; + struct hrl_rule *buf; struct hrl_node *node; - struct hrl_rule *buf; - if (uap->nentries == 0 && uap->bufp == NULL) { - mtx_lock(&hrl_lock); - error = suword(uap->required, nhrls); - mtx_unlock(&hrl_lock); - - return (error); - } - - if (uap->nentries < 0 || uap->nentries >= HRL_MAX_LIMITS) + if (buflen > HRL_MAX_LIMITS * sizeof(struct hrl_rule)) return (EINVAL); - buflen = sizeof(struct hrl_rule) * uap->nentries; buf = malloc(buflen, M_HRL, M_WAITOK); /* @@ -317,7 +240,8 @@ * XXX: Do not show everything to the client; just the * nodes that affect him. */ - if (copied >= uap->nentries) { + /* +1 to make room for the terminating NULL entry. */ + if ((copied + 1) * sizeof(*buf) >= buflen) { error = EFBIG; break; } @@ -328,21 +252,33 @@ if (error) goto out; - error = copyout(buf, uap->bufp, sizeof(struct hrl_rule) * copied); + /* Add terminating NULL entry. */ + bzero(buf + copied, sizeof(*buf)); + copied++; + + error = copyout(buf, bufp, sizeof(struct hrl_rule) * copied); if (error) goto out; - if (suword(uap->required, copied) != 0) { - error = EINVAL; - goto out; - } - out: free(buf, M_HRL); return (error); } +int +hrl(struct thread *td, struct hrl_args *uap) +{ + switch (uap->op) { + case HRL_OP_GET_RULES: + return (hrl_get_rules(td, uap->outbufp, uap->outbuflen)); + case HRL_OP_GET_ACC_PID: + return (hrl_get_acc_pid(td, uap->outbufp, uap->outbuflen)); + default: + return (EINVAL); + } +} + static void hrl_proc_exit(void *arg __unused, struct proc *p) { @@ -368,7 +304,6 @@ node = RB_REMOVE(hrl_tree, &hrls, node); KASSERT(node != NULL, ("node removal failed")); - nhrls--; mtx_unlock(&hrl_lock); uma_zfree(hrl_zone, node); ==== //depot/projects/soc2009/trasz_limits/sys/kern/syscalls.c#3 (text+ko) ==== @@ -516,6 +516,5 @@ "jail_get", /* 506 = jail_get */ "jail_set", /* 507 = jail_set */ "jail_remove", /* 508 = jail_remove */ - "hrl_get", /* 509 = hrl_get */ - "hrl_set", /* 510 = hrl_set */ + "hrl", /* 509 = hrl */ }; ==== //depot/projects/soc2009/trasz_limits/sys/kern/syscalls.master#3 (text+ko) ==== @@ -902,7 +902,6 @@ 507 AUE_NULL STD { int jail_set(struct iovec *iovp, \ unsigned int iovcnt, int flags); } 508 AUE_NULL STD { int jail_remove(int jid); } -509 AUE_NULL STD { int hrl_get(struct hrl_limit **bufp, int nentries, int *required); } -510 AUE_NULL STD { int hrl_set(struct hrl_limit **bufp, int nentries); } +509 AUE_NULL STD { int hrl(int op, const void *inbufp, size_t inbuflen, void *outbufp, size_t outbuflen); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master ==== //depot/projects/soc2009/trasz_limits/sys/kern/systrace_args.c#3 (text+ko) ==== @@ -3065,23 +3065,17 @@ *n_args = 1; break; } - /* hrl_get */ + /* hrl */ case 509: { - struct hrl_get_args *p = params; - uarg[0] = (intptr_t) p->bufp; /* struct hrl_limit ** */ - iarg[1] = p->nentries; /* int */ - uarg[2] = (intptr_t) p->required; /* int * */ - *n_args = 3; + struct hrl_args *p = params; + iarg[0] = p->op; /* int */ + uarg[1] = (intptr_t) p->inbufp; /* const void * */ + uarg[2] = p->inbuflen; /* size_t */ + uarg[3] = (intptr_t) p->outbufp; /* void * */ + uarg[4] = p->outbuflen; /* size_t */ + *n_args = 5; break; } - /* hrl_set */ - case 510: { - struct hrl_set_args *p = params; - uarg[0] = (intptr_t) p->bufp; /* struct hrl_limit ** */ - iarg[1] = p->nentries; /* int */ - *n_args = 2; - break; - } default: *n_args = 0; break; @@ -8154,30 +8148,23 @@ break; }; break; - /* hrl_get */ + /* hrl */ case 509: switch(ndx) { case 0: - p = "struct hrl_limit **"; + p = "int"; break; case 1: - p = "int"; + p = "const void *"; break; case 2: - p = "int *"; + p = "size_t"; break; - default: + case 3: + p = "void *"; break; - }; - break; - /* hrl_set */ - case 510: - switch(ndx) { - case 0: - p = "struct hrl_limit **"; - break; - case 1: - p = "int"; + case 4: + p = "size_t"; break; default: break; ==== //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#6 (text+ko) ==== @@ -92,6 +92,11 @@ #define HRL_MAX_LIMITS 128 +#define HRL_OP_GET_RULES 1 +#define HRL_OP_GET_ACC_PID 2 +#define HRL_OP_GET_ACC_UID 3 +#define HRL_OP_GET_ACC_GID 4 + #ifdef _KERNEL struct proc; @@ -108,8 +113,7 @@ #else /* !_KERNEL */ __BEGIN_DECLS -int hrl_get(struct hrl_rule *bufp, int nentries, int *count); -int hrl_set(struct hrl_rule *bufp, int nentries); +int hrl(int op, const void *inbufp, size_t inbuflen, void *outbufp, size_t outbuflen); __END_DECLS #endif /* !_KERNEL */ ==== //depot/projects/soc2009/trasz_limits/sys/sys/syscall.h#3 (text+ko) ==== @@ -424,6 +424,5 @@ #define SYS_jail_get 506 #define SYS_jail_set 507 #define SYS_jail_remove 508 -#define SYS_hrl_get 509 -#define SYS_hrl_set 510 -#define SYS_MAXSYSCALL 511 +#define SYS_hrl 509 +#define SYS_MAXSYSCALL 510 ==== //depot/projects/soc2009/trasz_limits/sys/sys/syscall.mk#3 (text+ko) ==== @@ -373,5 +373,4 @@ jail_get.o \ jail_set.o \ jail_remove.o \ - hrl_get.o \ - hrl_set.o + hrl.o ==== //depot/projects/soc2009/trasz_limits/sys/sys/sysproto.h#3 (text+ko) ==== @@ -1638,15 +1638,13 @@ struct jail_remove_args { char jid_l_[PADL_(int)]; int jid; char jid_r_[PADR_(int)]; }; -struct hrl_get_args { - char bufp_l_[PADL_(struct hrl_limit **)]; struct hrl_limit ** bufp; char bufp_r_[PADR_(struct hrl_limit **)]; - char nentries_l_[PADL_(int)]; int nentries; char nentries_r_[PADR_(int)]; - char required_l_[PADL_(int *)]; int * required; char required_r_[PADR_(int *)]; +struct hrl_args { + char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)]; + char inbufp_l_[PADL_(const void *)]; const void * inbufp; char inbufp_r_[PADR_(const void *)]; + char inbuflen_l_[PADL_(size_t)]; size_t inbuflen; char inbuflen_r_[PADR_(size_t)]; + char outbufp_l_[PADL_(void *)]; void * outbufp; char outbufp_r_[PADR_(void *)]; + char outbuflen_l_[PADL_(size_t)]; size_t outbuflen; char outbuflen_r_[PADR_(size_t)]; }; -struct hrl_set_args { - char bufp_l_[PADL_(struct hrl_limit **)]; struct hrl_limit ** bufp; char bufp_r_[PADR_(struct hrl_limit **)]; - char nentries_l_[PADL_(int)]; int nentries; char nentries_r_[PADR_(int)]; -}; int nosys(struct thread *, struct nosys_args *); void sys_exit(struct thread *, struct sys_exit_args *); int fork(struct thread *, struct fork_args *); @@ -2004,8 +2002,7 @@ int jail_get(struct thread *, struct jail_get_args *); int jail_set(struct thread *, struct jail_set_args *); int jail_remove(struct thread *, struct jail_remove_args *); -int hrl_get(struct thread *, struct hrl_get_args *); -int hrl_set(struct thread *, struct hrl_set_args *); +int hrl(struct thread *, struct hrl_args *); #ifdef COMPAT_43 @@ -2602,8 +2599,7 @@ #define SYS_AUE_jail_get AUE_NULL #define SYS_AUE_jail_set AUE_NULL #define SYS_AUE_jail_remove AUE_NULL -#define SYS_AUE_hrl_get AUE_NULL -#define SYS_AUE_hrl_set AUE_NULL +#define SYS_AUE_hrl AUE_NULL #undef PAD_ #undef PADL_ ==== //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#6 (text+ko) ==== @@ -28,12 +28,17 @@ __FBSDID("$FreeBSD$"); #include +#include +#include +#include +#include #include #include -#include -#include +#include #include +#define BUFLEN_DEFAULT 1024 + static void print_subject(int subject, id_t id) { @@ -179,45 +184,200 @@ } } -int -main(int argc __unused, char **argv __unused) +static id_t +parse_pid(const char *s) +{ + id_t id; + char *end; + + id = strtod(s, &end); + if ((size_t)(end - s) != strlen(s)) + errx(1, "trailing characters after numerical id"); + + return (id); +} + +static id_t +parse_user(const char *s) +{ + id_t id; + char *end; + struct passwd *pwd; + + pwd = getpwnam(s); + if (pwd != NULL) + return (pwd->pw_uid); + + id = strtod(s, &end); + if ((size_t)(end - s) != strlen(s)) + errx(1, "trailing characters after numerical id"); + + return (id); +} + +static id_t +parse_group(const char *s) +{ + id_t id; + char *end; + struct group *grp; + + grp = getgrnam(s); + if (grp != NULL) + return (grp->gr_gid); + + id = strtod(s, &end); + if ((size_t)(end - s) != strlen(s)) + errx(1, "trailing characters after numerical id"); + + return (id); +} + +static void +print_rules(void) { - int error, nentries, i; - struct hrl_rule *limits; + int error; + size_t ruleslen, i; + struct hrl_rule *rules = NULL; + + ruleslen = BUFLEN_DEFAULT / 4; + do { + ruleslen *= 4; + rules = realloc(rules, ruleslen); + if (rules == NULL) + err(1, "realloc"); + + error = hrl(HRL_OP_GET_RULES, NULL, 0, rules, ruleslen); + if (error != 0 && error != EFBIG) + err(1, "hrl_get"); + } while (error == EFBIG); - error = hrl_get(NULL, 0, &nentries); - if (error) - err(1, "hrl_get"); + printf("Defined resource limits:\n"); - if (nentries == 0) { + if (rules[0].hr_subject == 0) { printf("No resource limits defined.\n"); - return (0); + + return; + } + + for (i = 0; i < ruleslen / sizeof(*rules); i++) { + /* NULL entry terminating the table? */ + if (rules[i].hr_subject == 0) + break; + print_subject(rules[i].hr_subject, rules[i].hr_subject_id); + printf(":"); + print_resource(rules[i].hr_resource); + printf(":"); + print_action(rules[i].hr_action); + printf("="); + printf("%jd", rules[i].hr_amount); + if (rules[i].hr_subject != rules[i].hr_per) { + printf("/"); + print_per(rules[i].hr_per); + } + printf("\n"); } +} + +static void +print_accounting(int op, id_t id) +{ + int error; + size_t ruleslen, i; + struct hrl_rule *rules = NULL; - limits = malloc(sizeof(struct hrl_rule) * nentries); - if (limits == NULL) - err(1, "malloc"); + ruleslen = BUFLEN_DEFAULT / 4; + do { + ruleslen *= 4; + rules = realloc(rules, ruleslen); + if (rules == NULL) + err(1, "realloc"); + + error = hrl(op, &id, sizeof(id), rules, ruleslen); + if (error != 0 && error != EFBIG) + err(1, "hrl_get"); + } while (error == EFBIG); + + printf("Resource utilisation:\n"); - error = hrl_get(limits, nentries, &nentries); - if (error) - err(1, "hrl_get"); + if (rules[0].hr_subject == 0) { + printf("No resource utilisation recorded.\n"); - printf("Defined resource limits:\n"); + return; + } - for (i = 0; i < nentries; i++) { - print_subject(limits[i].hr_subject, limits[i].hr_subject_id); + for (i = 0; i < ruleslen / sizeof(*rules); i++) { + /* NULL entry terminating the table? */ + if (rules[i].hr_subject == 0) + break; + print_subject(rules[i].hr_subject, rules[i].hr_subject_id); printf(":"); - print_resource(limits[i].hr_resource); + print_resource(rules[i].hr_resource); printf(":"); - print_action(limits[i].hr_action); + print_action(rules[i].hr_action); printf("="); - printf("%jd", limits[i].hr_amount); - if (limits[i].hr_subject != limits[i].hr_per) { + printf("%jd", rules[i].hr_amount); + if (rules[i].hr_subject != rules[i].hr_per) { printf("/"); - print_per(limits[i].hr_per); + print_per(rules[i].hr_per); } printf("\n"); } +} + +static void +usage(void) +{ + + fprintf(stderr, "usage: hrl [-u user | -g group | -p pid]\n"); +} + +int +main(int argc __unused, char **argv __unused) +{ + int ch, op, pflag = 0, uflag = 0, gflag = 0; + id_t id = 0; + + op = HRL_OP_GET_RULES; + + while ((ch = getopt(argc, argv, "p:u:g:")) != -1) { + switch (ch) { + case 'p': + pflag = 1; + op = HRL_OP_GET_ACC_PID; + id = parse_pid(optarg); + break; + case 'u': + uflag = 1; + op = HRL_OP_GET_ACC_UID; + id = parse_user(optarg); + break; + case 'g': + gflag = 1; + op = HRL_OP_GET_ACC_GID; + id = parse_group(optarg); + break; + case '?': + default: + usage(); + } + } + + if (pflag + uflag + gflag > 1) + errx(1, "only one of the -p, -u and -g may be specified " + "at the same time"); + + switch (op) { + case HRL_OP_GET_RULES: + print_rules(); + break; + + case HRL_OP_GET_ACC_PID: + case HRL_OP_GET_ACC_UID: + case HRL_OP_GET_ACC_GID: + print_accounting(op, id); + break; + } return (0); }