#! /bin/sh /usr/share/dpatch/dpatch-run
## cpuset.dpatch by Micah Anderson <Micah Anderson <micah@debian.org>>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.

@DPATCH@
diff -urNad trunk~/scripts/vserver-setup.functions trunk/scripts/vserver-setup.functions
--- trunk~/scripts/vserver-setup.functions	2006-03-20 08:16:45.000000000 -0500
+++ trunk/scripts/vserver-setup.functions	2006-04-16 00:06:57.000000000 -0400
@@ -24,11 +24,15 @@
 SETUP_CONFDIR=
 SETUP_CONTEXT=
 SETUP_INITSTYLE=
+SETUP_CPUSET=
+SETUP_CPUSETCPUS=
+SETUP_CPUSETMEMS=
+SETUP_CPUSETVIRT=
 
 declare -a SETUP_INTERFACES=()
 declare -a SETUP_FLAGS=()
 
-declare -r SETUP_OPTIONS="confdir:,lockfile:,hostname:,netdev:,netmask:,netprefix:,netbcast:,interface:,flags:,context:,initstyle:"
+declare -r SETUP_OPTIONS="confdir:,lockfile:,hostname:,netdev:,netmask:,netprefix:,netbcast:,interface:,flags:,context:,initstyle:,cpuset:,cpusetcpus:,cpusetmems:,cpusetvirt"
 declare -r SETUP_HELPMSG=$"
     --context   ...  the static context of the vserver [default: none; a dynamic
                      context will be assumed]
@@ -55,6 +59,19 @@
 			    this becomes a per vserver limit)
 		     private: No other process can join this security context.
 		            Even root
+     --cpuset <name>
+                ...  declares the CPUSET this vserver will run in [default: none]
+     --cpusetcpus <number[-number][:<exclusive>]>
+                ...  sets which cpus belong to the CPUSET,
+                     exclusive is a flag (0|1) prohibiting any other cpuset from
+                     using those cpus
+     --cpusetmems <number[-number][:<exclusive>]>
+                ...  sets which memory pools belong to the CPUSET,
+                     exclusive is a flag (0|1) prohibiting any other cpuset from
+                     using those memory pools
+     --cpusetvirt
+                ...  virtualize cpuset (guest will see only CPUs defined in cpuset)
+                     Requires kernel patch from http://www.bullopensource.org/cpuset/
     --initstyle <style>
                 ...  configures the initstyle (e.g. minit,sysv,plain)
 "
@@ -71,7 +88,23 @@
 	(--netprefix)	SETUP_NETPREFIX=$2;;
 	(--netbcast)	SETUP_NETBCAST=$2;;
 	(--interface)	SETUP_INTERFACES=( "${SETUP_INTERFACES[@]}" "$2" );;
-	(--initstyle)   SETUP_INITSTYLE=$2;;
+	(--initstyle)	SETUP_INITSTYLE=$2;;
+	(--cpuset)	SETUP_CPUSET=$2;;
+	(--cpusetcpus)	old_IFS=$IFS
+			IFS=:
+			set -- $2
+			SETUP_CPUSETCPUS=$1
+			SETUP_CPUSETCPUSEXCL=$2
+			IFS=$old_IFS
+			;;
+	(--cpusetmems)	old_IFS=$IFS
+			IFS=:
+			set -- $2
+			SETUP_CPUSETMEMS=$1
+			SETUP_CPUSETMEMSEXCL=$2
+			IFS=$old_IFS
+			;;
+	(--cpusetvirt)  SETUP_CPUSETVIRT=1;;
 	(--flags)	old_IFS=$IFS
 			IFS=,
 			set -- $2
@@ -140,7 +173,7 @@
     local cfgdir=${SETUP_CONFDIR:?}
     local i
 
-    mkdir -p "$cfgdir"/interfaces "$cfgdir"/apps/init "$cfgdir"/uts
+    mkdir -p "$cfgdir"/interfaces "$cfgdir"/apps/init "$cfgdir"/uts "$cfgdir"/cpuset
 
     _setup_writeSingleOption "$name"            "$cfgdir"/name
     _setup_writeSingleOption "$SETUP_CONTEXT"   "$cfgdir"/context
@@ -150,6 +183,12 @@
     _setup_writeSingleOption "$SETUP_NETPREFIX" "$cfgdir"/interfaces/prefix
     _setup_writeSingleOption "$SETUP_NETBCAST"  "$cfgdir"/interfaces/bcast
     _setup_writeSingleOption "$SETUP_INITSTYLE" "$cfgdir"/apps/init/style
+    _setup_writeSingleOption "$SETUP_CPUSET"    "$cfgdir"/cpuset/name
+    _setup_writeSingleOption "$SETUP_CPUSETCPUS"     "$cfgdir"/cpuset/cpus
+    _setup_writeSingleOption "$SETUP_CPUSETCPUSEXCL" "$cfgdir"/cpuset/cpus_exclusive
+    _setup_writeSingleOption "$SETUP_CPUSETMEMS"     "$cfgdir"/cpuset/mems
+    _setup_writeSingleOption "$SETUP_CPUSETMEMSEXCL" "$cfgdir"/cpuset/mem_exclusive
+    _setup_writeSingleOption "$SETUP_CPUSETVIRT"     "$cfgdir"/cpuset/virtualize
 
     local idx=0
     for i in "${SETUP_INTERFACES[@]}"; do
diff -urNad trunk~/scripts/vserver.functions trunk/scripts/vserver.functions
--- trunk~/scripts/vserver.functions	2006-03-20 08:16:45.000000000 -0500
+++ trunk/scripts/vserver.functions	2006-04-16 00:06:57.000000000 -0400
@@ -690,6 +690,54 @@
     fi
 }
 
+function addtoCPUSET
+{
+    local vdir=$1
+    local cpuset
+    local f="$vdir"/cpuset
+    local i
+    local configured=0
+
+    test -d "$f" || return 0
+    test -e "$f"/name || return 0
+
+    read cpuset < "$f"/name
+    test -e "$f"/nocreate || {
+       test -d /dev/cpuset/"$cpuset" || mkdir /dev/cpuset/"$cpuset" || configured=1
+       for i in cpus mems cpu_exclusive mem_exclusive virtualize; do
+           if test -e "$f"/"$i"; then
+               cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" 2>/dev/null || {
+                   configured=1
+                   break
+               }
+           fi
+       done
+    }
+
+    echo $$ >/dev/cpuset/"$cpuset"/tasks || configured=1
+    if [ "$configured" -ne 0 ]; then
+       warning $"\
+WARNING: Failed to create or CPUSET \"$cpuset\" does not exist! Not using it!" >&2
+       rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
+       return 0
+    fi
+}
+
+function removeCPUSET
+{
+    local vdir=$1
+    local cpuset
+    local f="$vdir"/cpuset
+
+    test -d "$f" || return 0
+    test -e "$f"/name || return 0
+
+    read cpuset < "$f"/name
+    test -e "$f"/nocreate || {
+       rmdir /dev/cpuset/"$cpuset" 2>/dev/null || :
+    }
+}
+
 function _mountVserverInternal
 {
     local fstab="$1"
diff -urNad trunk~/scripts/vserver.start trunk/scripts/vserver.start
--- trunk~/scripts/vserver.start	2006-03-20 08:16:45.000000000 -0500
+++ trunk/scripts/vserver.start	2006-04-16 00:06:57.000000000 -0400
@@ -113,6 +113,7 @@
 
 mountVserver "$VSERVER_DIR"     && is_mounted=1
 prepareInit  "$VSERVER_DIR"
+addtoCPUSET  "$VSERVER_DIR"
 
 pushd "$VSERVER_DIR"/vdir/ >/dev/null
 execScriptlets   "$VSERVER_DIR" "$VSERVER_NAME" pre-start
diff -urNad trunk~/scripts/vserver.stop trunk/scripts/vserver.stop
--- trunk~/scripts/vserver.stop	2006-03-20 08:16:45.000000000 -0500
+++ trunk/scripts/vserver.stop	2006-04-16 00:06:57.000000000 -0400
@@ -112,3 +112,4 @@
 saveDiskLimits    "$VSERVER_DIR"
 
 execScriptlets    "$VSERVER_DIR" "$VSERVER_NAME" postpost-stop
+removeCPUSET      "$VSERVER_DIR"
diff -urNad trunk~/scripts/vserver.stop.orig trunk/scripts/vserver.stop.orig
--- trunk~/scripts/vserver.stop.orig	1969-12-31 19:00:00.000000000 -0500
+++ trunk/scripts/vserver.stop.orig	2006-03-20 08:16:45.000000000 -0500
@@ -0,0 +1,114 @@
+# $Id: vserver.stop,v 1.31 2006/01/21 13:22:23 ensc Exp $  --*- sh -*--
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+lock "$__LOCKDIR"/vserver."$($_VSERVER_INFO "$VSERVER_DIR" CANONIFY)".startup
+
+if ! isVserverRunning "$VSERVER_DIR" S_CONTEXT; then
+    warning $"vserver '$VSERVER_NAME' is not running" >&2
+    test -n "$OPTION_DEBUG" || exec 2>/dev/null >/dev/null
+    umountVserver     "$VSERVER_DIR" || :
+    disableInterfaces "$VSERVER_DIR" || :
+    unlock
+    exit 0
+fi
+
+function cleanup
+{
+    set +e
+    unlock
+    
+    test ! -p "$sync_fifo" || {
+	$_RM -f "$sync_fifo"
+	$_RMDIR $($_DIRNAME "$sync_fifo")
+    }
+
+    test ! -d "$vwait_statdir" ||
+	$_RM -rf "$vwait_statdir"
+}
+
+vwait_statdir=
+vwait_pid=
+sync_fifo=
+trap "cleanup" EXIT
+
+OPTION_FORCE_SYNC=1
+
+set -e
+generateOptions   "$VSERVER_DIR"
+set +e
+
+vshelper.doDestroy "$VSERVER_DIR" "$S_CONTEXT"
+initSync           "$VSERVER_DIR" "$S_CONTEXT" sync_fifo
+prepareStop        "$VSERVER_DIR"
+
+cd "$VSERVER_DIR"/vdir/
+execScriptlets     "$VSERVER_DIR" "$VSERVER_NAME" pre-stop
+cd "$VSERVER_DIR"/vdir/
+
+test -z "$OPTION_DEFAULTTTY" || setDefaultTTY "$VSERVER_DIR"
+
+fail=
+initWait	   "$VSERVER_DIR" "$S_CONTEXT" vwait_statdir
+if test -n "$_IS_FAKEINIT" && \
+   $_VSERVER_INFO - FEATURE vkill; then
+    $_VKILL -s INT --xid "$S_CONTEXT" -- 1 || fail=1
+    ## HACK: remove the 'initpid' stuff above when PID virtualization
+    ## is implemented
+elif $_VSERVER_INFO - FEATURE migrate; then
+    "${NICE_CMD[@]}" \
+    ${USE_VNAMESPACE:+$_VNAMESPACE --enter "$S_CONTEXT" -- } \
+    $_VCONTEXT $SILENT_OPT --migrate --chroot --xid "$S_CONTEXT" -- \
+    "${INITCMD_STOP[@]}" || fail=1
+else
+    "${NICE_CMD[@]}" \
+    "$_CHBIND"       "${CHBIND_OPTS[@]}" \
+    "$_EXEC_ULIMIT"  "$VSERVER_DIR/ulimits" \
+    ${USE_VNAMESPACE:+$_VNAMESPACE --enter "$S_CONTEXT"} \
+    $_CHCONTEXT_COMPAT    "${CHCONTEXT_OPTS[@]}" \
+    "$_CAPCHROOT"    "${CAPCHROOT_OPTS[@]}" "." \
+    "${INITCMD_STOP[@]}" || fail=1
+fi
+
+waitForSync "$VSERVER_DIR" "$sync_fifo" "$vwait_statdir"
+
+vshelper.doDestroy "$VSERVER_DIR" "$S_CONTEXT"
+sendKillSequence   "$S_CONTEXT" "${INITKILL_SEQ[@]}"
+
+## Small hack... isVserverRunning removes stale runfiles as a sideeffect
+! isVserverRunning  "$VSERVER_DIR" || \
+    echo $"Vserver '$VSERVER_DIR' still running unexpectedly; please investigate it manually..." >&2
+
+execScriptlets    "$VSERVER_DIR" "$VSERVER_NAME" post-stop
+    
+umountVserver     "$VSERVER_DIR" || :
+disableInterfaces "$VSERVER_DIR"
+#
+# <Bertl> it's a 'feature' introduced by recent kernels ...
+# <Bertl> proc inodes stay around as long as they want to
+# <Bertl> and processes too, even if they are dead
+# <Bertl> as long as the process won't go away, the context will not either
+# <Bertl> and the process won't go away, as long as the proc entry exists ...
+# <Bertl> and the proc entry (in /proc/<pid>...) will remain until the proc inodes are purged
+# <Bertl> maybe I just add a hack to do exactly that on vserver stop
+# <Bertl> but you can also add the proc remount hack in userspace
+#
+mount -o remount,rw /proc
+
+saveDiskLimits    "$VSERVER_DIR"
+
+execScriptlets    "$VSERVER_DIR" "$VSERVER_NAME" postpost-stop
diff -urNad trunk~/scripts/vserver.suexec trunk/scripts/vserver.suexec
--- trunk~/scripts/vserver.suexec	2006-03-20 08:16:45.000000000 -0500
+++ trunk/scripts/vserver.suexec	2006-04-16 00:06:57.000000000 -0400
@@ -22,6 +22,7 @@
     exit 1
 }
 generateOptions  "$VSERVER_DIR"
+addtoCPUSET  "$VSERVER_DIR"
 
 user=$1
 shift
