PERFORCE change 119762 for review

Chris Jones cdjones at FreeBSD.org
Sun May 13 08:27:53 UTC 2007


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

Change 119762 by cdjones at cdjones_iconoclast on 2007/05/13 08:27:07

	Well, it compiles and links --- and runs (without jails) okay.  Now, to test....

Affected files ...

.. //depot/projects/soc2006/cdjones_jail_current/src/sys/compat/freebsd32/syscalls.master#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/sys/kern/kern_jail.c#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/sys/kern/kern_mib.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail_current/src/sys/kern/sched_4bsd.c#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/sys/kern/syscalls.master#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/sys/sys/jail.h#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/sys/vm/vm_pageout.c#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/sys/vm/vm_pageout.h#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/usr.sbin/jail/jail.8#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/usr.sbin/jail/jail.c#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/usr.sbin/jls/jls.8#2 edit
.. //depot/projects/soc2006/cdjones_jail_current/src/usr.sbin/jtune/Makefile#1 add
.. //depot/projects/soc2006/cdjones_jail_current/src/usr.sbin/jtune/jtune.8#1 add
.. //depot/projects/soc2006/cdjones_jail_current/src/usr.sbin/jtune/jtune.c#1 add

Differences ...

==== //depot/projects/soc2006/cdjones_jail_current/src/sys/compat/freebsd32/syscalls.master#2 (text+ko) ====

@@ -781,3 +781,5 @@
 474	AUE_NULL	NOPROTO	{ int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
 				    struct sockaddr * from, __socklen_t *fromlenaddr, \
 				    struct sctp_sndrcvinfo *sinfo, int *msg_flags); }
+475     AUE_NULL        STD     { int jail_set_resource_limits(unsigned int jid, \
+                                    int cpushares, int memlimit); }

==== //depot/projects/soc2006/cdjones_jail_current/src/sys/kern/kern_jail.c#2 (text+ko) ====

@@ -5,6 +5,35 @@
  * can do whatever you want with this stuff. If we meet some day, and you think
  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
  * ----------------------------------------------------------------------------
+ *
+ *  Portions copyright (c) 2006 Chris Jones
+ *  All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Chris Jones
+ * thanks to the support of Google's Summer of Code program and
+ * mentoring by Kip Macy.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. 
+ *
  */
 
 #include <sys/cdefs.h>
@@ -15,6 +44,7 @@
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/kernel.h>
+#include <sys/kthread.h>
 #include <sys/systm.h>
 #include <sys/errno.h>
 #include <sys/sysproto.h>
@@ -33,6 +63,10 @@
 #include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
 #include <sys/vnode.h>
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_pageout.h>
 #include <net/if.h>
 #include <netinet/in.h>
 
@@ -78,6 +112,17 @@
     &jail_mount_allowed, 0,
     "Processes in jail can mount/unmount jail-friendly file systems");
 
+int     jail_limit_memory = 0;
+SYSCTL_INT(_security_jail, OID_AUTO, limit_jail_memory, CTLFLAG_RW,
+	   &jail_limit_memory, 0,
+	   "Limit jails' memory usage");
+
+int     jail_memory_pager_interval = 5;
+SYSCTL_INT(_security_jail, OID_AUTO, jail_pager_interval,
+	   CTLTYPE_INT | CTLFLAG_RW,
+	   &jail_memory_pager_interval, 0,
+	   "Interval between jail memory limit checks");
+
 /* allprison, lastprid, and prisoncount are protected by allprison_lock. */
 struct	prisonlist allprison;
 struct	sx allprison_lock;
@@ -114,6 +159,99 @@
 
 SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL);
 
+static void
+jpager_td(void *arg)
+{
+	struct proc *p;
+	struct prison *pr = arg;
+	struct thread *td;
+	long limit, cursize, newsize, usage;
+	int breakout;
+	int flags = J_PAGER_TD_ACTIVE;
+	pr->pr_pager_flags_ptr = &flags;
+	
+	for (;;) {
+		if (flags & J_PAGER_TD_DIE)
+			break;
+	       
+		if (jail_limit_memory && pr->pr_mem_limit) {
+			/* 
+			 * TODO: consider whether it might be better to start
+			 * pushing back when we approach the limit, rather than
+			 * when we hit it.
+			 * 
+			 */
+			limit = prison_memory_limit(pr);
+			usage = prison_memory(pr);
+			
+			/*
+			 * The logic from vm_daemon() really needs to go here.
+			 * Problem: we want to push things below their rlimits,
+			 * and vm_daemon doesn't do that.  It'd be better to 
+			 * refactor vm_daemon to fit, but this'll do for now.
+			 *
+			 */
+			
+			if ((usage - limit) > 0) {
+				sx_slock(&allproc_lock);
+				LIST_FOREACH(p, &allproc, p_list) {
+					
+					if (pr != p->p_ucred->cr_prison)
+						continue;
+					
+					PROC_LOCK(p);
+					if (p->p_flag & (P_SYSTEM | P_WEXIT)) {
+						PROC_UNLOCK(p);
+						continue;
+					}
+					
+					mtx_lock_spin(&sched_lock);
+					breakout = 0;
+					FOREACH_THREAD_IN_PROC(p, td) {
+						if (!TD_ON_RUNQ(td) &&
+						    !TD_IS_RUNNING(td) &&
+						    !TD_IS_SLEEPING(td)) {
+							breakout = 1;
+							break;
+						}
+					}
+					mtx_unlock_spin(&sched_lock);
+					if (breakout) {
+						PROC_UNLOCK(p);
+						continue;
+					}
+					
+					/* NOTE: we differ here from vm_daemon b/c we don't 
+					 * care about the rlimit; things that are exceeding that will
+					 * get caught in due course.  We need, however, to decrease
+					 * the pressure on our permitted memory allocation.  Fortunately, 
+					 * we only care about eventually hitting the limit, so if we
+					 * don't get there right away, it's okay.
+					 */      
+					
+					/* TODO: this arbitrarily reduces each process's space by
+					 * 6.25% (until it's completely swapped out) while
+					 * we're under memory pressure.  A better way would be 
+					 * to either hit large processes first, or to hit the
+					 * least-active processes first, or go proportionally,
+					 * or .... 
+					 */
+					newsize = cursize = vmspace_resident_count(p->p_vmspace);
+					newsize -= newsize / 16;
+					if (cursize < 0)
+						newsize = 0;
+					PROC_UNLOCK(p);
+					vm_pageout_map_deactivate_pages(&p->p_vmspace->vm_map, newsize);
+				} /* end LIST_FOREACH procs */
+				sx_sunlock(&allproc_lock);
+			}
+		}
+		tsleep(pr, 0, "-", jail_memory_pager_interval * hz); 
+	}
+	
+	kthread_exit(0);
+}
+
 /*
  * struct jail_args {
  *	struct jail *jail;
@@ -126,6 +264,7 @@
 	struct prison *pr, *tpr;
 	struct prison_service *psrv;
 	struct jail j;
+	struct proc *j_pager_proc = NULL;
 	struct jail_attach_args jaa;
 	int vfslocked, error, tryprid;
 
@@ -156,6 +295,8 @@
 		goto e_dropvnref;
 	pr->pr_ip = j.ip_number;
 	pr->pr_linux = NULL;
+	pr->pr_mem_limit = j.mem_limit;
+	pr->pr_sched_shares = j.sched_shares;
 	pr->pr_securelevel = securelevel;
 	if (prison_service_slots == 0)
 		pr->pr_slots = NULL;
@@ -190,6 +331,11 @@
 	}
 	sx_sunlock(&allprison_lock);
 
+	if (kthread_create(jpager_td, pr, (void *) j_pager_proc, 0, 0, "jpager %d", pr->pr_id))
+		goto e_dropprref;
+	KASSERT(j_pager_proc != NULL, ("NULL j_pager_proc"));
+	pr->pr_pager = j_pager_proc;
+
 	error = jail_attach(td, &jaa);
 	if (error)
 		goto e_dropprref;
@@ -199,6 +345,10 @@
 	td->td_retval[0] = jaa.jid;
 	return (0);
 e_dropprref:
+	if (j_pager_proc != NULL) {
+		*pr->pr_pager_flags_ptr = J_PAGER_TD_DIE;
+		wakeup(pr);
+	}
 	sx_xlock(&allprison_lock);
 	LIST_REMOVE(pr, pr_list);
 	prisoncount--;
@@ -314,6 +464,9 @@
 	pr->pr_ref--;
 	if (pr->pr_ref == 0) {
 		mtx_unlock(&pr->pr_mtx);
+		/* Kill pager; no need to wait. */
+		*pr->pr_pager_flags_ptr = J_PAGER_TD_DIE;
+		wakeup(pr);
 		TASK_INIT(&pr->pr_task, 0, prison_complete, pr);
 		taskqueue_enqueue(taskqueue_thread, &pr->pr_task);
 		return;
@@ -435,6 +588,40 @@
 		ok = 0;
 	return (ok);
 }
+/* Given credential, return memory usage in bytes. */
+long
+prison_memory(struct prison *pr)
+{
+	struct proc *p;
+	long mem_used = 0;
+	
+	/* 
+	 * TODO: this is a really bad way of doing the
+	 * search, as we end up going across all processes
+	 * for each jail.  It'd be more efficient to just do 
+	 * this once in a period and update the relevant jail.
+	 *
+	 */
+	FOREACH_PROC_IN_SYSTEM(p) {
+		if (!jailed(p->p_ucred) ||
+		    (pr != p->p_ucred->cr_prison))
+			continue;
+		mem_used += vmspace_resident_count(p->p_vmspace);
+	}
+       	mem_used *= PAGE_SIZE;
+	return mem_used;
+}
+
+/* Given credential, return permitted memory usage in bytes. */
+long
+prison_memory_limit(struct prison *pr)
+{
+	vm_pindex_t memlimit;
+	mtx_lock(&pr->pr_mtx);
+	memlimit = (vm_pindex_t) pr->pr_mem_limit;
+	mtx_unlock(&pr->pr_mtx);
+	return memlimit;
+}
 
 /*
  * Return 0 if jails permit p1 to frob p2, otherwise ESRCH.
@@ -566,6 +753,52 @@
 	}
 }
 
+/* 
+ * Change resource limit for a prison.
+ * 
+ * unsigned int jid: id of jail to mess with
+ *
+ * int cpushares:  0 -> remove prison from cpu limits
+ *                -1 -> don't change existing shares
+ *                >0 -> set cpu shares
+ *
+ * int memlimit:   0 -> remove prison from mem limits
+ *                -1 -> don't change existing limit
+ *                >1 -> set memory limit (bytes)
+ *
+ * TODO: might this be better handled via a writable 
+ * sysctl than with a new syscall?
+ */
+int
+jail_set_resource_limits(struct thread *td, struct jail_set_resource_limits_args *uap)
+{
+	struct prison *pr;
+	int error;
+
+	error = suser(td);
+	if (error)
+		return (error);
+
+	sx_slock(&allprison_lock);
+	LIST_FOREACH(pr, &allprison, pr_list) {
+		if (pr->pr_id == uap->jid)
+			break;
+	}
+	if (NULL == pr) {
+		sx_sunlock(&allprison_lock);
+		return 1;
+	}
+
+	mtx_lock(&pr->pr_mtx);
+	if (-1 != uap->cpushares)
+		pr->pr_sched_shares = uap->cpushares;
+	if (-1 != uap->memlimit)
+		pr->pr_mem_limit = uap->memlimit;
+	mtx_unlock(&pr->pr_mtx);
+	sx_sunlock(&allprison_lock);
+	return 0;
+}
+
 /*
  * Check with permission for a specific privilege is granted within jail.  We
  * have a specific list of accepted privileges; the rest are denied.
@@ -954,6 +1187,10 @@
 		xp->pr_version = XPRISON_VERSION;
 		xp->pr_id = pr->pr_id;
 		xp->pr_ip = pr->pr_ip;
+		xp->pr_sched_shares = pr->pr_sched_shares;
+		xp->pr_estcpu = pr->pr_estcpu;
+		xp->pr_mem_limit = pr->pr_mem_limit;
+		xp->pr_mem_usage = pr->pr_mem_usage;
 		strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path));
 		mtx_lock(&pr->pr_mtx);
 		strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host));

==== //depot/projects/soc2006/cdjones_jail_current/src/sys/kern/kern_mib.c#2 (text+ko) ====

@@ -36,12 +36,13 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_mib.c,v 1.77 2007/04/09 19:18:09 pjd Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_mib.c,v 1.78 2007/05/12 19:38:18 wkoszek Exp $");
 
 #include "opt_posix.h"
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/sbuf.h>
 #include <sys/systm.h>
 #include <sys/sysctl.h>
 #include <sys/proc.h>
@@ -295,6 +296,38 @@
     CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_kern_securelvl,
     "I", "Current secure level");
 
+/* Actual kernel configuration options. */
+extern char kernconfstring[];
+
+static int
+sysctl_kern_config(SYSCTL_HANDLER_ARGS)
+{
+	struct sbuf *sb;
+	int error;
+	char *p;
+
+	sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND);
+	if (sb == NULL)
+		return (ENOMEM);
+	sbuf_clear(sb);
+	p = kernconfstring;
+	if (p == NULL || *p == '\0') {
+		sbuf_printf(sb, "No kernel configuration\n");
+	} else {
+		sbuf_printf(sb, "%s", p);
+	}
+	sbuf_trim(sb);
+	sbuf_putc(sb, '\n');
+	sbuf_finish(sb);
+	error = sysctl_handle_string(oidp, sbuf_data(sb), sbuf_len(sb), req);
+	if (error)
+		return (error);
+	sbuf_delete(sb);
+	return (error);
+}
+SYSCTL_PROC(_kern, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RW, 
+    0, 0, sysctl_kern_config, "", "Kernel configuration file");
+
 char domainname[MAXHOSTNAMELEN];
 SYSCTL_STRING(_kern, KERN_NISDOMAINNAME, domainname, CTLFLAG_RW,
     &domainname, sizeof(domainname), "Name of the current YP/NIS domain");

==== //depot/projects/soc2006/cdjones_jail_current/src/sys/kern/sched_4bsd.c#2 (text+ko) ====

@@ -39,6 +39,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/ktr.h>
 #include <sys/lock.h>
@@ -122,6 +123,10 @@
 static int	forward_wakeup(int  cpunum);
 #endif
 
+static uint32_t total_cpu_sched_shares;
+static u_int total_est_cpu;
+extern int prisoncount;
+
 static struct kproc_desc sched_kp = {
         "schedcpu",
         schedcpu_thread,
@@ -227,6 +232,18 @@
 	   "allow threads to share a quantum");
 #endif
 
+static int sched_limitjailcpu = 0;
+SYSCTL_INT(_kern_sched, OID_AUTO, limit_jail_cpu, 
+	   CTLFLAG_RW, 
+	   &sched_limitjailcpu, 0,
+	   "limit jailed process cpu usage");
+
+static int sched_unjailedProcessShares = 0;
+SYSCTL_INT(_kern_sched, OID_AUTO, system_cpu_shares, 
+	   CTLTYPE_INT | CTLFLAG_RW,
+	   &sched_unjailedProcessShares, 0,
+	   "number of shares to allocate to unjailed processes");
+
 static __inline void
 sched_load_add(void)
 {
@@ -372,10 +389,23 @@
 	struct thread *td;
 	struct proc *p;
 	struct td_sched *ts;
+	struct prison *pr;
 	int awake, realstathz;
 
 	realstathz = stathz ? stathz : hz;
+	/* 
+	 * Need to acquire each jail's mutex and hold throughout to keep 
+	 * everything out while we recalculate per-jail CPU usage.
+	 * TODO: this is excessively icky.
+	 */
 	sx_slock(&allproc_lock);
+	sx_slock(&allprison_lock);
+	if (prisoncount) {
+		LIST_FOREACH(pr, &allprison, pr_list) {
+			pr->pr_estcpu = 0;
+		}
+	}
+	total_est_cpu = 0;
 	FOREACH_PROC_IN_SYSTEM(p) {
 		/*
 		 * Prevent state changes and protect run queue.
@@ -459,11 +489,18 @@
 			if (td->td_slptime > 1)
 				continue;
 			td->td_estcpu = decay_cpu(loadfac, td->td_estcpu);
+			total_est_cpu += td->td_estcpu;
+			if (sched_limitjailcpu &&
+				NULL != td->td_proc->p_ucred &&
+				NULL != td->td_proc->p_ucred->cr_prison)
+				td->td_proc->p_ucred->cr_prison->pr_estcpu +=
+					td->td_estcpu;
 		      	resetpriority(td);
 			resetpriority_thread(td);
 		} /* end of thread loop */
 		mtx_unlock_spin(&sched_lock);
 	} /* end of process loop */
+	sx_sunlock(&allprison_lock);
 	sx_sunlock(&allproc_lock);
 }
 
@@ -473,8 +510,29 @@
 static void
 schedcpu_thread(void)
 {
+struct prison *pr;
+u_int32_t shares = 0;
 
 	for (;;) {
+		if (sched_limitjailcpu) {
+			/* 
+			 * Update total jail CPU shares in case they've changed.
+			 * Safe to read pr_sched_shares without mutex because
+			 * in worst case, we get a bogus value which will be 
+			 * corrected on the next pass.
+			 *
+			 * TODO: this should be done by forcing a recalculation
+			 * when jail CPU shares are added / changed, rather than
+			 * doing it every second.
+			 */
+			
+			shares = sched_unjailedProcessShares;
+			LIST_FOREACH(pr, &allprison, pr_list) {
+				shares += pr->pr_sched_shares;
+			}
+			total_cpu_sched_shares = shares;
+		}
+
 		schedcpu();
 		pause("-", hz);
 	}
@@ -512,12 +570,37 @@
 resetpriority(struct thread *td)
 {
 	register unsigned int newpriority;
+	struct prison *pr = NULL;
+	if (NULL != td->td_proc->p_ucred)
+		pr = td->td_proc->p_ucred->cr_prison;
 
 	if (td->td_pri_class == PRI_TIMESHARE) {
 		newpriority = PUSER + td->td_estcpu / INVERSE_ESTCPU_WEIGHT +
 		    NICE_WEIGHT * (td->td_proc->p_nice - PRIO_MIN);
-		newpriority = min(max(newpriority, PRI_MIN_TIMESHARE),
-		    PRI_MAX_TIMESHARE);
+		if (sched_limitjailcpu && NULL != pr) {
+			/* 
+			 * Skew the priority by the jail's share of CPU resources.
+			 * The unjailed processes get half the CPU time.
+			 *
+			 * TODO: this is a hard limit.  We should really also have
+			 * soft limits available.  Also, the amount of CPU time 
+			 * reserved to unjailed processes really should be sysctl'd.
+			 */ 
+			register unsigned int skew;
+			skew = pr->pr_estcpu * total_cpu_sched_shares;
+			skew /= max(total_est_cpu, 1) * max(pr->pr_sched_shares, 1);
+			if (skew > 0) {
+				/* wait your turn until your cpu usage's proportionate */
+				newpriority = PRI_MAX_IDLE - 1;
+			} else {
+				newpriority = min(max(newpriority, PRI_MIN_TIMESHARE),
+						  PRI_MAX_TIMESHARE);
+			}
+		} else {
+			newpriority = min(max(newpriority, PRI_MIN_TIMESHARE),
+					  PRI_MAX_TIMESHARE);
+		}
+		
 		sched_user_prio(td, newpriority);
 	}
 }

==== //depot/projects/soc2006/cdjones_jail_current/src/sys/kern/syscalls.master#2 (text+ko) ====

@@ -835,5 +835,8 @@
 474     AUE_NULL        STD    { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
 				    struct sockaddr * from, __socklen_t *fromlenaddr, \
 				    struct sctp_sndrcvinfo *sinfo, int *msg_flags); }
+475	AUE_NULL	STD	{ int jail_set_resource_limits(unsigned int jid, \
+				    int cpushares, int memlimit); }
+
 ; Please copy any additions and changes to the following compatability tables:
 ; sys/compat/freebsd32/syscalls.master

==== //depot/projects/soc2006/cdjones_jail_current/src/sys/sys/jail.h#2 (text+ko) ====

@@ -18,6 +18,8 @@
 	char		*path;
 	char		*hostname;
 	u_int32_t	ip_number;
+	unsigned int    sched_shares;
+	unsigned int    mem_limit;
 };
 
 struct xprison {
@@ -26,13 +28,24 @@
 	char		 pr_path[MAXPATHLEN];
 	char 		 pr_host[MAXHOSTNAMELEN];
 	u_int32_t	 pr_ip;
+        unsigned int     pr_sched_shares;
+        unsigned int     pr_estcpu;
+        unsigned int     pr_mem_limit;
+        unsigned int     pr_mem_usage;
 };
-#define	XPRISON_VERSION	1
+#define	XPRISON_VERSION	2
+
+#define JAIL_MINIMUM_SHARES 1
+
+#define J_PAGER_TD_ACTIVE	0x01
+#define J_PAGER_TD_DIE		0x02
+#define J_PAGER_TD_DEAD		0x04
 
 #ifndef _KERNEL
 
 int jail(struct jail *);
 int jail_attach(int);
+int jail_set_resource_limits(unsigned int, int, int);
 
 #else /* _KERNEL */
 
@@ -74,6 +87,12 @@
 	struct task	 pr_task;			/* (d) destroy task */
 	struct mtx	 pr_mtx;
 	void		**pr_slots;			/* (p) additional data */
+	u_int32_t        pr_sched_shares;		/* (p) jail priority */
+	u_int		 pr_estcpu;			/* (p) est. cpu of jail */
+	struct proc     *pr_pager;                      /* (c) pager pid */
+	int             *pr_pager_flags_ptr;            /* (p) communication to pager */
+	size_t           pr_mem_limit;                  /* (p) memory allocation limit */
+	size_t           pr_mem_usage;                  /* (p) memory in use */
 };
 #endif /* _KERNEL || _WANT_PRISON */
 
@@ -114,6 +133,8 @@
 int prison_if(struct ucred *cred, struct sockaddr *sa);
 int prison_ip(struct ucred *cred, int flag, u_int32_t *ip);
 int prison_priv_check(struct ucred *cred, int priv);
+long prison_memory(struct prison *pr);
+long prison_memory_limit(struct prison *pr);
 void prison_remote_ip(struct ucred *cred, int flags, u_int32_t *ip);
 
 /*

==== //depot/projects/soc2006/cdjones_jail_current/src/sys/vm/vm_pageout.c#2 (text+ko) ====

@@ -204,7 +204,6 @@
 int vm_page_max_wired;		/* XXX max # of wired pages system-wide */
 
 #if !defined(NO_SWAPPING)
-static void vm_pageout_map_deactivate_pages(vm_map_t, long);
 static void vm_pageout_object_deactivate_pages(pmap_t, vm_object_t, long);
 static void vm_req_vmdaemon(void);
 #endif
@@ -596,7 +595,7 @@
  * deactivate some number of pages in a map, try to do it fairly, but
  * that is really hard to do.
  */
-static void
+void
 vm_pageout_map_deactivate_pages(map, desired)
 	vm_map_t map;
 	long desired;

==== //depot/projects/soc2006/cdjones_jail_current/src/sys/vm/vm_pageout.h#2 (text+ko) ====

@@ -87,6 +87,8 @@
  *	Exported routines.
  */
 
+void vm_pageout_map_deactivate_pages(vm_map_t map, long desired);
+
 /*
  *	Signal pageout-daemon and wait for it.
  */

==== //depot/projects/soc2006/cdjones_jail_current/src/usr.sbin/jail/jail.8#2 (text+ko) ====

@@ -45,6 +45,8 @@
 .Op Fl J Ar jid_file
 .Op Fl s Ar securelevel
 .Op Fl l u Ar username | Fl U Ar username
+.Op Fl S Ar cpu_shares
+.Op Fl M Ar mem_limit
 .Ar path hostname ip-number command ...
 .Sh DESCRIPTION
 The
@@ -88,6 +90,10 @@
 The user name from jailed environment as whom the
 .Ar command
 should run.
+.It Fl S Ar cpu_shares
+CPU shares to assign to the prison.
+.It Fl M Ar mem_limit
+Amount of memory (in MB) to allow the prison to use.
 .It Ar path
 Directory which is to be the root of the prison.
 .It Ar hostname
@@ -546,6 +552,17 @@
 privileged, and may manipulate system file flags subject to the usual
 constraints on
 .Va kern.securelevel .
+.It Va security.jail.limit_jail_memory, Va security.jail.jail_pager_interval
+These MIB entries determine whether and how often (in seconds) a
+jail's memory-limit monitoring daemon will run, and consequently the 
+period during which a jail can be overcommitted for resident memory.
+.It Va kern.sched.limit_jail_cpu
+This MIB entry sets whether CPU usage limits will be enforced 
+against processes in jails with CPU limits.
+.It Va kern.sched.system_cpu_shares
+Number of CPU usage shares to allocate to unjailed processes for the 
+purposes of determining CPU usage permitted for jailed processes.  
+Unjailed processes are not subject to CPU usage limits.
 .It Va security.jail.mount_allowed
 This MIB entry determines if a privileged user inside a jail will be
 able to mount and unmount file system types marked as jail-friendly.

==== //depot/projects/soc2006/cdjones_jail_current/src/usr.sbin/jail/jail.c#2 (text+ko) ====

@@ -56,6 +56,8 @@
 	struct in_addr in;
 	gid_t groups[NGROUPS];
 	int ch, i, iflag, Jflag, lflag, ngroups, securelevel, uflag, Uflag;
+	unsigned int mem_limit = 0;
+	unsigned int sched_shares = 0;
 	char path[PATH_MAX], *ep, *username, *JidFile;
 	static char *cleanenv;
 	const char *shell, *p = NULL;
@@ -67,7 +69,7 @@
 	username = JidFile = cleanenv = NULL;
 	fp = NULL;
 
-	while ((ch = getopt(argc, argv, "ils:u:U:J:")) != -1) {
+	while ((ch = getopt(argc, argv, "ilS:M:s:u:U:J:")) != -1) {
 		switch (ch) {
 		case 'i':
 			iflag = 1;
@@ -76,6 +78,13 @@
 			JidFile = optarg;
 			Jflag = 1;
 			break;
+		case 'M':
+			mem_limit = atoi(optarg);
+			mem_limit *= 1024 * 1024;
+			break;
+		case 'S':
+			sched_shares = atoi(optarg);
+			break;
 		case 's':
 			ltmp = strtol(optarg, &ep, 0);
 			if (*ep || ep == optarg || ltmp > INT_MAX || !ltmp)
@@ -118,6 +127,8 @@
 	if (inet_aton(argv[2], &in) == 0)
 		errx(1, "Could not make sense of ip-number: %s", argv[2]);
 	j.ip_number = ntohl(in.s_addr);
+	j.mem_limit = mem_limit;
+	j.sched_shares = sched_shares;
 	if (Jflag) {
 		fp = fopen(JidFile, "w");
 		if (fp == NULL)
@@ -183,7 +194,8 @@
 {
 
 	(void)fprintf(stderr, "%s%s%s\n",
-	     "usage: jail [-i] [-J jid_file] [-s securelevel] [-l -u ",
+	     "usage: jail [-i] [-J jid_file] [-M mem_limit] ",
+	     "[-S cpu_shares] [-s securelevel] [-l -u ",
 	     "username | -U username]",
 	     " path hostname ip-number command ...");
 	exit(1);

==== //depot/projects/soc2006/cdjones_jail_current/src/usr.sbin/jls/jls.8#2 (text+ko) ====

@@ -42,7 +42,8 @@
 .Sh SEE ALSO
 .Xr jail 2 ,
 .Xr jail 8 ,
-.Xr jexec 8
+.Xr jexec 8 ,
+.Xr jtune 8
 .Sh HISTORY
 The
 .Nm


More information about the p4-projects mailing list