Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Aug 2009 16:12:23 GMT
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 167035 for review
Message-ID:  <200908051612.n75GCNxk059495@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=167035

Change 167035 by trasz@trasz_anger on 2009/08/05 16:11:26

	Improve locking.

Affected files ...

.. //depot/projects/soc2009/trasz_limits/TODO#9 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#43 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_resource.c#20 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#27 edit

Differences ...

==== //depot/projects/soc2009/trasz_limits/TODO#9 (text+ko) ====

@@ -4,6 +4,9 @@
 
  - Why did I put the loginclass pointer into the proc and not into the cred?
 
+ - Make the limits lists protected by the subjects lock (e.g. process lock)
+   instead of hrl_lock.
+
  - Make sure we have all the gidinfos we need in the 'struct ucred'.
 
  - Fix up (add/remove resource counters) when:

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

@@ -682,26 +682,23 @@
 	mtx_unlock(&hrl_lock);
 }
 
-#if 0
 static int
-hrl_limit_remove(struct hrl_limits_head *limits_head, struct hrl_rule *rule)
+hrl_limit_add_locked(struct hrl_limits_head *limits_head, struct hrl_rule *rule)
 {
-	struct hrl_limit *limit, *limittmp;
+	struct hrl_limit *limit;
+
+	KASSERT(hrl_rule_fully_specified(rule), ("rule not fully specified"));
+	mtx_assert(&hrl_lock, MA_OWNED);
+
+	limit = uma_zalloc(hrl_limit_zone, M_NOWAIT);
+	if (limit == NULL)
+		return (ENOMEM);
+	hrl_rule_acquire(rule);
+	limit->hl_rule = rule;
 
-	mtx_lock(&hrl_lock);
-	LIST_FOREACH_SAFE(limit, limits_head, hl_next, limittmp) {
-		if (limit->hl_rule == rule) {
-			LIST_REMOVE(limit, hl_next);
-			mtx_unlock(&hrl_lock);
-			uma_zfree(hrl_limit_zone, limit);
-			hrl_rule_release(rule);
-			return (1);
-		}
-	}
-	mtx_unlock(&hrl_lock);
+	LIST_INSERT_HEAD(limits_head, limit, hl_next);
 	return (0);
 }
-#endif
 
 /*
  * Remove limits for a rules matching the filter and release
@@ -715,29 +712,28 @@
 	int removed = 0;
 	struct hrl_limit *limit, *limittmp;
 
-again:
 	mtx_lock(&hrl_lock);
 	LIST_FOREACH_SAFE(limit, limits_head, hl_next, limittmp) {
 		if (!hrl_rule_matches(limit->hl_rule, filter))
 			continue;
 
 		LIST_REMOVE(limit, hl_next);
-		mtx_unlock(&hrl_lock);
 		hrl_rule_release(limit->hl_rule);
 		uma_zfree(hrl_limit_zone, limit);
 		removed++;
-		goto again;
 	}
 	mtx_unlock(&hrl_lock);
 	return (removed);
 }
 
 struct hrl_rule *
-hrl_rule_alloc(void)
+hrl_rule_alloc(int flags)
 {
 	struct hrl_rule *rule;
 
-	rule = uma_zalloc(hrl_rule_zone, M_WAITOK);
+	rule = uma_zalloc(hrl_rule_zone, flags);
+	if (rule == NULL)
+		return (NULL);
 	rule->hr_subject = HRL_SUBJECT_UNDEFINED;
 	rule->hr_subject_id = HRL_SUBJECT_ID_UNDEFINED;
 	rule->hr_per = HRL_SUBJECT_UNDEFINED;
@@ -750,11 +746,13 @@
 }
 
 struct hrl_rule *
-hrl_rule_duplicate(const struct hrl_rule *rule)
+hrl_rule_duplicate(const struct hrl_rule *rule, int flags)
 {
 	struct hrl_rule *copy;
 
-	copy = uma_zalloc(hrl_rule_zone, M_WAITOK);
+	copy = uma_zalloc(hrl_rule_zone, flags);
+	if (copy == NULL)
+		return (NULL);
 	copy->hr_subject = rule->hr_subject;
 	copy->hr_subject_id = rule->hr_subject_id;
 	copy->hr_per = rule->hr_per;
@@ -819,7 +817,7 @@
 	struct loginclass *lc;
 	struct hrl_rule *rule;
 
-	rule = hrl_rule_alloc();
+	rule = hrl_rule_alloc(M_WAITOK);
 
 	subjectstr = strsep(&rulestr, ":");
 	subject_idstr = strsep(&rulestr, ":");
@@ -1066,10 +1064,6 @@
 	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) {
 		found += hrl_limit_remove_matching(&p->p_limits, filter);
@@ -1527,35 +1521,40 @@
 hrl_proc_fork(void *arg __unused, struct proc *parent, struct proc *child,
     int flags __unused)
 {
-	int i;
+	int error, i;
 	struct hrl_limit *limit;
 	struct hrl_rule *rule;
 
 	PROC_LOCK(parent);
 	PROC_LOCK(child);
+	mtx_lock(&hrl_lock);
+
 	for (i = 0; i < HRL_RESOURCE_MAX; i++) {
 		if (parent->p_usage.hu_resources[i] != 0 &&
 		    hrl_resource_inheritable(i))
 			hrl_allocated_proc(child, i,
 			    parent->p_usage.hu_resources[i]);
 	}
-	PROC_UNLOCK(child);
-	PROC_UNLOCK(parent);
 
-	/*
-	 * XXX: What about locking the parent?
-	 */
 	LIST_FOREACH(limit, &parent->p_limits, hl_next) {
 		if (limit->hl_rule->hr_subject == HRL_SUBJECT_PROCESS) {
-			rule = hrl_rule_duplicate(limit->hl_rule);
+			rule = hrl_rule_duplicate(limit->hl_rule, M_NOWAIT);
+			KASSERT(rule != NULL, ("XXX: better error handling needed"));
 			KASSERT(rule->hr_subject_id == parent->p_pid,
 			    ("rule->hr_subject_id == parent->p_pid"));
 			rule->hr_subject_id = child->p_pid;
-			hrl_limit_add(&child->p_limits, rule);
+			error = hrl_limit_add_locked(&child->p_limits, rule);
+			KASSERT(error == 0, ("XXX: better error handling needed"));
 			hrl_rule_release(rule);
-		} else
-			hrl_limit_add(&child->p_limits, limit->hl_rule);
+		} else {
+			error = hrl_limit_add_locked(&child->p_limits, limit->hl_rule);
+			KASSERT(error == 0, ("XXX: better error handling needed"));
+		}
 	}
+
+	mtx_unlock(&hrl_lock);
+	PROC_UNLOCK(child);
+	PROC_UNLOCK(parent);
 }
 
 /*

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

@@ -655,7 +655,7 @@
 	int error;
 	struct hrl_rule *rule, *rule2;
 
-	rule = hrl_rule_alloc();
+	rule = hrl_rule_alloc(M_WAITOK);
 	rule->hr_subject = HRL_SUBJECT_PROCESS;
 	rule->hr_subject_id = td->td_proc->p_pid;
 	rule->hr_per = HRL_SUBJECT_PROCESS;
@@ -724,7 +724,7 @@
 	 * rule, "deny".
 	 */
 	if (rule->hr_action != HRL_ACTION_DENY) {
-		rule2 = hrl_rule_duplicate(rule);
+		rule2 = hrl_rule_duplicate(rule, M_WAITOK);
 		rule2->hr_action = HRL_ACTION_DENY;
 		hrl_rule_remove(rule2);
 

==== //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#27 (text+ko) ====

@@ -138,8 +138,8 @@
 void	hrl_usage_subtract(struct hrl_usage *dest, const struct hrl_usage *src);
 void	hrl_proc_exiting(struct proc *p);
 
-struct hrl_rule	*hrl_rule_alloc(void);
-struct hrl_rule	*hrl_rule_duplicate(const struct hrl_rule *rule);
+struct hrl_rule	*hrl_rule_alloc(int flags);
+struct hrl_rule	*hrl_rule_duplicate(const struct hrl_rule *rule, int flags);
 void	hrl_rule_acquire(struct hrl_rule *rule);
 void	hrl_rule_release(struct hrl_rule *rule);
 int	hrl_rule_add(struct hrl_rule *rule);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908051612.n75GCNxk059495>