PERFORCE change 166939 for review

Edward Tomasz Napierala trasz at FreeBSD.org
Sun Aug 2 18:47:03 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=166939

Change 166939 by trasz at trasz_anger on 2009/08/02 18:46:44

	Add support for 'loginclass:' rules.

Affected files ...

.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#39 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_loginclass.c#3 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#18 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/loginclass.h#2 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/resourcevar.h#9 edit
.. //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#20 edit

Differences ...

==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#39 (text+ko) ====

@@ -724,9 +724,6 @@
 		LIST_REMOVE(limit, hl_next);
 		mtx_unlock(&hrl_lock);
 		hrl_rule_release(limit->hl_rule);
-		if (limit->hl_rule->hr_subject == HRL_SUBJECT_LOGINCLASS &&
-		    limit->hl_rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED)
-			loginclass_release((struct loginclass *)(long)limit->hl_rule->hr_subject_id);
 		uma_zfree(hrl_limit_zone, limit);
 		removed++;
 		goto again;
@@ -784,8 +781,13 @@
 
 	KASSERT(rule->hr_refcount > 0, ("rule->hr_refcount > 0"));
 
-	if (refcount_release(&rule->hr_refcount))
+	if (refcount_release(&rule->hr_refcount)) {
+		if (rule->hr_subject == HRL_SUBJECT_LOGINCLASS &&
+		    rule->hr_subject_id != HRL_SUBJECT_ID_UNDEFINED)
+			loginclass_release((struct loginclass *)(long)
+			    rule->hr_subject_id);
 		uma_zfree(hrl_rule_zone, rule);
+	}
 }
 
 static int
@@ -839,11 +841,12 @@
 	 * to the 'struct loginclass' into the hr_subject_id field.
 	 */
 	if (rule->hr_subject == HRL_SUBJECT_LOGINCLASS) {
-		if (subject_idstr == NULL || subject_idstr[0] == '\0')
-			goto out;
-
-		lc = loginclass_find(subject_idstr);
-		rule->hr_subject_id = (long)lc;
+		if (subject_idstr == NULL || subject_idstr[0] == '\0') {
+			rule->hr_subject_id = HRL_SUBJECT_ID_UNDEFINED;
+		} else {
+			lc = loginclass_find(subject_idstr);
+			rule->hr_subject_id = (long)lc;
+		}
 	} else {
 		if (subject_idstr == NULL || subject_idstr[0] == '\0')
 			rule->hr_subject_id = HRL_SUBJECT_ID_UNDEFINED;
@@ -961,7 +964,6 @@
 		break;
 
 	case HRL_SUBJECT_LOGINCLASS:
-		KASSERT(rule->hr_subject_id > 0, ("rule->hr_subject_id > 0"));
 		lc = (struct loginclass *)(long)rule->hr_subject_id;
 		hrl_limit_add(&lc->lc_limits, rule);
 		break;
@@ -1021,6 +1023,15 @@
 	return (0);
 }
 
+static int
+hrl_rule_remove_callback(struct hrl_limits_head *limits, const struct hrl_rule *filter, void *arg3, void *arg4 __unused)
+{
+	int *found = (int *)arg3;
+
+	*found += hrl_limit_remove_matching(limits, filter);
+	return (0);
+}
+
 /*
  * Remove all rules that match the filter.
  */
@@ -1037,18 +1048,27 @@
 		if (p == NULL)
 			return (ESRCH);
 		PROC_UNLOCK(p);
-		error = hrl_limit_remove_matching(&p->p_limits, filter);
+		found = hrl_limit_remove_matching(&p->p_limits, filter);
 		sx_sunlock(&proctree_lock);
-		return (error);
+		if (found)
+			return (0);
+		return (ESRCH);
 	}
 
+	error = loginclass_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found, NULL);
+	KASSERT(error == 0, ("loginclass_limits_foreach failed"));
+	error = ui_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found, NULL);
+	KASSERT(error == 0, ("ui_limits_foreach failed"));
+	error = gi_limits_foreach(hrl_rule_remove_callback, filter, (void *)&found, NULL);
+	KASSERT(error == 0, ("gi_limits_foreach failed"));
+
 	/*
 	 * XXX: per-process, per-group, per-jail and per-class limits.
 	 */
 
 	sx_slock(&proctree_lock);
 	FOREACH_PROC_IN_SYSTEM(p) {
-		error = hrl_limit_remove_matching(&p->p_limits, filter);
+		found += hrl_limit_remove_matching(&p->p_limits, filter);
 		if (error == 0)
 			found = 1;
 	}
@@ -1056,8 +1076,7 @@
 
 	if (found)
 		return (0);
-	else
-		return (ESRCH);
+	return (ESRCH);
 }
 
 static struct sbuf *
@@ -1266,10 +1285,30 @@
 	return (error);
 }
 
+static int
+hrl_get_rules_callback(struct hrl_limits_head *limits, const struct hrl_rule *filter, void *arg3, void *arg4)
+{
+	struct hrl_limit *limit;
+	struct hrl_rule *buf = (struct hrl_rule *)arg3;
+	int copied = 0, *available = (int *)arg4;
+
+	LIST_FOREACH(limit, limits, hl_next) {
+		if (copied >= *available)
+			return (ERANGE);
+		if (!hrl_rule_matches(limit->hl_rule, filter))
+			continue;
+		*(buf + copied) = *limit->hl_rule;
+		copied++;
+		(*available)--;
+	}
+
+	return (0);
+}
+
 int
 hrl_get_rules(struct thread *td, struct hrl_get_rules_args *uap)
 {
-	int error, copied, maxcopied = HRL_MAX_RULES;
+	int error, copied, maxcopied = HRL_MAX_RULES, available;
 	char *inputstr;
 	struct sbuf *outputsbuf;
 	struct hrl_rule *filter, *buf;
@@ -1285,8 +1324,6 @@
 	if (filter == NULL)
 		return (EINVAL);
 
-	buf = malloc(HRL_MAX_RULES * sizeof(struct hrl_rule), M_HRL, M_WAITOK);
-
 again:
 	buf = malloc(maxcopied * sizeof(*buf), M_HRL, M_WAITOK);
 	copied = 0;
@@ -1294,7 +1331,7 @@
 	FOREACH_PROC_IN_SYSTEM(p) {
 		mtx_lock(&hrl_lock);
 		LIST_FOREACH(limit, &p->p_limits, hl_next) {
-			if (copied >= HRL_MAX_RULES) {
+			if (copied >= maxcopied) {
 				mtx_unlock(&hrl_lock);
 				sx_sunlock(&proctree_lock);
 				maxcopied *= 4;
@@ -1312,6 +1349,24 @@
 	if (error)
 		goto out;
 
+	available = maxcopied - copied;
+	loginclass_limits_foreach(hrl_get_rules_callback, filter,
+	    buf + copied, &available);
+	copied = maxcopied - available;
+	available = maxcopied - copied;
+	ui_limits_foreach(hrl_get_rules_callback, filter,
+	    buf + copied, &available);
+	copied = maxcopied - available;
+	available = maxcopied - copied;
+	gi_limits_foreach(hrl_get_rules_callback, filter,
+	    buf + copied, &available);
+	copied = maxcopied - available;
+	if (copied >= maxcopied) {
+		maxcopied *= 4;
+		free(buf, M_HRL);
+		goto again;
+	}
+
 	/*
 	 * XXX: Iterate over the rest (other than per-process) of the rules.
 	 */
@@ -1370,15 +1425,13 @@
 	}
 	mtx_lock(&hrl_lock);
 	LIST_FOREACH(limit, &p->p_limits, hl_next) {
-		if (copied >= HRL_MAX_RULES) {
+		if (copied >= maxcopied) {
 			mtx_unlock(&hrl_lock);
 			PROC_UNLOCK(p);
 			maxcopied *= 4;
 			free(buf, M_HRL);
 			goto again;
 		}
-		if (!hrl_rule_matches(limit->hl_rule, filter))
-			continue;
 		*(buf + copied) = *limit->hl_rule;
 		copied++;
 	}
@@ -1413,10 +1466,8 @@
 
 	rule = hrl_rule_from_string(inputstr);
 	free(inputstr, M_HRL);
-	if (rule == NULL) {
-		error = EINVAL;
-		goto out;
-	}
+	if (rule == NULL)
+		return (EINVAL);
 
 	if (!hrl_rule_fully_specified(rule)) {
 		error = EINVAL;

==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_loginclass.c#3 (text+ko) ====

@@ -201,6 +201,23 @@
 	return (0);
 }
 
+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)
+{
+	int error;
+	struct loginclass *lc;
+
+	LIST_FOREACH(lc, &loginclasses, lc_next) {
+		error = (callback)(&lc->lc_limits, filter, arg3, arg4);
+		if (error)
+			return (error);
+	}
+
+	return (0);
+}
+
 static void
 lc_proc_fork(void *arg __unused, struct proc *parent, struct proc *child,
     int flags __unused)

==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#18 (text+ko) ====

@@ -1412,6 +1412,19 @@
 	rw_wunlock(&uihashtbl_lock);
 }
 
+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)
+{
+
+	callback = callback;
+	filter = filter;
+	arg3 = arg3;
+	arg4 = arg4;
+	return (0);
+}
+
 /*
  * Find the gidinfo structure for a gid.  This structure is used to
  * track the total resource consumption (process count, socket buffer
@@ -1557,6 +1570,20 @@
 	rw_wunlock(&gihashtbl_lock);
 }
 
+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)
+{
+
+	callback = callback;
+	filter = filter;
+	arg3 = arg3;
+	arg4 = arg4;
+
+	return (0);
+}
+
 /*
  * Change the count associated with number of processes
  * a given user is using.  When 'max' is 0, don't enforce a limit

==== //depot/projects/soc2009/trasz_limits/sys/sys/loginclass.h#2 (text+ko) ====

@@ -41,6 +41,9 @@
 void	loginclass_acquire(struct loginclass *lc);
 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);
 
 #endif /* !_SYS_LOGINCLASS_H_ */
 

==== //depot/projects/soc2009/trasz_limits/sys/sys/resourcevar.h#9 (text+ko) ====

@@ -159,6 +159,9 @@
 void	 uifree(struct uidinfo *uip);
 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);
 struct gidinfo
 	*gifind(gid_t gid);
 struct gidinfo
@@ -166,6 +169,9 @@
 void	 gifree(struct gidinfo *gip);
 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);
 
 #endif /* _KERNEL */
 #endif /* !_SYS_RESOURCEVAR_H_ */

==== //depot/projects/soc2009/trasz_limits/usr.sbin/hrl/hrl.c#20 (text+ko) ====

@@ -107,7 +107,9 @@
 		subject = "group";
 	else if (strcasecmp(subject, "p") == 0)
 		subject = "process";
-	else if (strcasecmp(subject, "l") == 0 || strcasecmp(subject, "c") == 0)
+	else if (strcasecmp(subject, "l") == 0 ||
+	    strcasecmp(subject, "c") == 0 ||
+	    strcasecmp(subject, "class") == 0)
 		subject = "loginclass";
 
 	if (strcasecmp(subject, "user") == 0 && strlen(textid) > 0) {


More information about the p4-projects mailing list