PERFORCE change 164289 for review
Edward Tomasz Napierala
trasz at FreeBSD.org
Sat Jun 13 19:53:10 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=164289
Change 164289 by trasz at 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 <vm/uma.h>
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 <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <grp.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
-#include <pwd.h>
-#include <grp.h>
+#include <string.h>
#include <sys/hrl.h>
+#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);
}
More information about the p4-projects
mailing list