Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Jan 2011 18:22:49 GMT
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 187961 for review
Message-ID:  <201101191822.p0JIMnD6001904@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@187961?ac=10

Change 187961 by trasz@trasz_victim on 2011/01/19 18:22:01

	Improve RSS enforcement.

Affected files ...

.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_container.c#56 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_rctl.c#12 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/sysv_sem.c#10 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/container.h#22 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/rctl.h#6 edit
.. //depot/projects/soc2009/trasz_limits/sys/vm/vm_pageout.c#23 edit

Differences ...

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

@@ -477,6 +477,23 @@
 }
 
 /*
+ * Returns amount of 'resource' the process 'p' can keep allocated.
+ * Allocating more than that would be denied, unless the resource
+ * is marked undeniable.  Amount of already allocated resource does
+ * matter.
+ */
+uint64_t
+rusage_get_available(struct proc *p, int resource)
+{
+
+#ifdef RCTL
+	return (rctl_get_available(p, resource));
+#else
+	return (UINT64_MAX);
+#endif
+}
+
+/*
  * Decrease allocation of 'resource' by 'amount' for process 'p'.
  */
 void
@@ -616,6 +633,7 @@
 	rusage_set(p, RUSAGE_FSIZE, 0);
 	rusage_set(p, RUSAGE_NPTS, 0);
 	rusage_set(p, RUSAGE_NTHR, 0);
+	rusage_set(p, RUSAGE_RSS, 0);
 
 #ifdef RCTL
 	rctl_proc_exit(p);

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

@@ -389,6 +389,45 @@
 	return (amount);
 }
 
+uint64_t
+rctl_get_available(struct proc *p, int resource)
+{
+	struct rctl_rule *rule;
+	struct rctl_rule_link *link;
+	int64_t available, minavailable, allocated;
+
+	minavailable = INT64_MAX;
+
+	rw_rlock(&rctl_lock);
+
+	/*
+	 * There may be more than one matching rule; go through all of them.
+	 * Denial should be done last, after logging and sending signals.
+	 */
+	LIST_FOREACH(link, &p->p_container.c_rule_links, rrl_next) {
+		rule = link->rrl_rule;
+		if (rule->rr_resource != resource)
+			continue;
+		if (rule->rr_action != RCTL_ACTION_DENY)
+			continue;
+		available = rctl_available_resource(p, rule);
+		if (available < minavailable)
+			minavailable = available;
+	}
+
+	rw_runlock(&rctl_lock);
+
+	/*
+	 * XXX: Think about this _hard_.
+	 */
+	allocated = p->p_container.c_resources[resource];
+	if (minavailable < INT64_MAX - allocated)
+		minavailable += allocated;
+	if (minavailable < 0)
+		minavailable = 0;
+	return (minavailable);
+}
+
 static int
 rctl_rule_matches(const struct rctl_rule *rule, const struct rctl_rule *filter)
 {

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

@@ -1018,7 +1018,7 @@
 		DPRINTF(("too many sops (max=%d, nsops=%d)\n", seminfo.semopm,
 		    nsops));
 		return (E2BIG);
-	} else if (nsops > rusage_get_limit(td->td_proc, RUSAGE_NSEMOP)) {
+	} else if (nsops > rusage_get_available(td->td_proc, RUSAGE_NSEMOP)) {
 		return (E2BIG);
 	} else
 		sops = malloc(nsops * sizeof(*sops), M_TEMP, M_WAITOK);

==== //depot/projects/soc2009/trasz_limits/sys/sys/container.h#22 (text+ko) ====

@@ -102,6 +102,7 @@
 void	rusage_sub(struct proc *p, int resource, uint64_t amount);
 void	rusage_sub_cred(struct ucred *cred, int resource, uint64_t amount);
 uint64_t	rusage_get_limit(struct proc *p, int resource);
+uint64_t	rusage_get_available(struct proc *p, int resource);
 
 void	container_create(struct container *container);
 void	container_destroy(struct container *container);

==== //depot/projects/soc2009/trasz_limits/sys/sys/rctl.h#6 (text+ko) ====

@@ -121,6 +121,7 @@
 
 int	rctl_enforce(struct proc *p, int resource, uint64_t amount);
 uint64_t	rctl_get_limit(struct proc *p, int resource);
+uint64_t	rctl_get_available(struct proc *p, int resource);
 const char	*rctl_resource_name(int resource);
 int	rctl_proc_fork(struct proc *parent, struct proc *child);
 void	rctl_proc_exit(struct proc *p);

==== //depot/projects/soc2009/trasz_limits/sys/vm/vm_pageout.c#23 (text+ko) ====

@@ -1631,8 +1631,8 @@
 	struct proc *p;
 	struct thread *td;
 	struct vmspace *vm;
-	int breakout, swapout_flags;
-	uint64_t maxsize;
+	int breakout, swapout_flags, tryagain;
+	uint64_t rsize, ravailable;
 
 	while (TRUE) {
 		mtx_lock(&vm_daemon_mtx);
@@ -1651,6 +1651,8 @@
 		 * scan the processes for exceeding their rlimits or if
 		 * process is swapped out -- deactivate pages
 		 */
+again:
+		tryagain = 0;
 		sx_slock(&allproc_lock);
 		FOREACH_PROC_IN_SYSTEM(p) {
 			vm_pindex_t limit, size;
@@ -1708,29 +1710,39 @@
 				vm_pageout_map_deactivate_pages(
 				    &vm->vm_map, limit);
 			}
-			rusage_set(p, RUSAGE_RSS, IDX_TO_OFF(size));
-			maxsize = OFF_TO_IDX(rusage_get_limit(p, RUSAGE_RSS));
-			if (size > maxsize) {
+			rsize = IDX_TO_OFF(size);
+			rusage_set(p, RUSAGE_RSS, rsize);
+			ravailable = rusage_get_available(p, RUSAGE_RSS);
+			if (rsize > ravailable) {
 				/*
 				 * Don't be overly aggressive; this might be
 				 * an innocent process, and the limit could've
 				 * been exceeded by some memory hog.  Don't
-				 * try to deactivate more than half of process'
+				 * try to deactivate more than 1/4th of process'
 				 * resident set size.
 				 *
 				 * XXX: Reconsider.
 				 */
-				if (maxsize < size / 2)
-					maxsize = size / 2;
+				if (ravailable < rsize - (rsize / 4))
+					ravailable = rsize - (rsize / 4);
 				vm_pageout_map_deactivate_pages(
-				    &vm->vm_map, maxsize);
+				    &vm->vm_map, OFF_TO_IDX(ravailable));
 				/* Update RSS usage after paging out. */
 				size = vmspace_resident_count(vm);
-				rusage_set(p, RUSAGE_RSS, IDX_TO_OFF(size));
+				rsize = IDX_TO_OFF(size);
+				rusage_set(p, RUSAGE_RSS, rsize);
+				if (rsize > ravailable)
+					tryagain++;
+				if (tryagain > 20) {
+					printf("still too much: rsize = %ld, ravailable = %zd\n", rsize, ravailable);
+					tryagain = 0;
+				}
 			}
 			vmspace_free(vm);
 		}
 		sx_sunlock(&allproc_lock);
+		if (tryagain != 0)
+			goto again;
 	}
 }
 #endif			/* !defined(NO_SWAPPING) */



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