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