cgroup support.
authorDaniel Hokka Zakrisson <daniel@hozac.com>
Sun, 24 Aug 2008 20:12:08 +0000 (20:12 +0000)
committerDaniel Hokka Zakrisson <daniel@hozac.com>
Sun, 24 Aug 2008 20:12:08 +0000 (20:12 +0000)
git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@2771 94cd875c-1c1d-0410-91d2-eb244daf1a30

doc/configuration.xml
scripts/vserver.functions
scripts/vserver.start
scripts/vserver.stop
sysv/util-vserver

index 729a197..fe9bfe6 100644 (file)
@@ -305,6 +305,41 @@ interface will be executed.
         <description>The default /etc/resolv.conf file.</description>
       </data>
     </collection>
+
+    <collection name="cgroup" use="optional" since="0.30.216" id="global-cgroup">
+      <description>
+This directory contains cgroup settings which should be applied to all guests.
+See your kernel documentation for what settings are valid with your
+configuration.
+      </description>
+      <scalar name="mnt">
+        <description>
+The directory to mount the cgroup hierarchy at. The default is /dev/cgroup.
+        </description>
+      </scalar>
+      <scalar name="subsys">
+        <description>
+Comma-separated list of subsystems to enable on the cgroup mount point.
+The default is "all".
+        </description>
+      </scalar>
+      <list name="inherit">
+        <description>
+Some subsystems start out with clean slates, making it impossible to use the
+cgroup before certain things have been set. This is true for e.g. the cpuset
+subsystem. This file contains a list of filenames which should be explicitly
+inherited from the parent (root) cgroup, if not overridden elsewhere.
+The default is cpuset.cpus and cpuset.mems.
+        </description>
+      </list>
+      <scalar name="name" id="global-cgroup-name">
+        <description>
+If this file exists, all guests will be put in one cgroup named after the
+contents of this file. The default is to put each guest in a cgroup named the
+same thing as the guest.
+        </description>
+      </scalar>
+    </collection>
   </collection>
     
   <collection name=".distributions" use="optional">
@@ -1619,5 +1654,29 @@ Puts the guest in a cpuset. Required entries are name, cpus and mems.
         <description>The IO scheduling priority to use for this guest (see ionice(1)).</description>
       </scalar>
     </collection>
+
+    <collection name="cgroup" use="optional" since="0.30.216" id="guest-cgroup">
+      <description>
+This directory contains cgroup settings to be applied to this guest.
+See your kernel documentation for what settings are valid with your
+configuration.
+      </description>
+      <scalar name="name">
+        <description>
+If this file exists, the guest will be put in a cgroup named after the
+contents of this file. The default is to name the cgroup the same thing as the
+guest, unless
+<optionref ref="global-cgroup-name">.defaults/cgroup/name</optionref> says
+otherwise.
+        </description>
+      </scalar>
+    </collection>
+    <scalar name="nocgroup" since="0.30.216">
+      <description>
+If this file exists,
+<optionref ref="global-cgroup">.defaults/cgroup</optionref> will be ignored
+for this guest.
+      </description>
+    </scalar>
   </collection>
   </database>
index 238c4b8..d5eeda5 100644 (file)
@@ -71,6 +71,10 @@ N_CONTEXT=
 
 SILENT_OPT=
 
+CGROUP_MNT=/dev/cgroup
+CGROUP_SUBSYS=all
+declare -a CGROUP_INHERIT=( cpuset.cpus cpuset.mems )
+
 : ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
 
 if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
@@ -831,6 +835,7 @@ function generateOptions
     _generateTagOptions         "$1"
     _generateMemctrlOptions     "$1"
     _generateSpaceOptions       "$1"
+    _generateCgroupOptions
 
     if test -n "$_IS_FAKEINIT"; then
        CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
@@ -1395,3 +1400,91 @@ function handleDeviceMap
        $_VDEVMAP --xid "$xid" "$op" "${vdevmap_opts[@]}" || return $?
     done
 }
+
+function hasCgroup
+{
+    $_GREP -q "cgroup" /proc/filesystems
+}
+
+function _generateCgroupOptions
+{
+    local file
+
+    hasCgroup || return 0
+
+    findFile file "$__CONFDIR/.defaults/cgroup/mnt" ""
+    if test -n "$file"; then
+       read CGROUP_MNT < "$file"
+    fi
+    findFile file "$__CONFDIR/.defaults/cgroup/subsys" ""
+    if test -n "$file"; then
+       read CGROUP_SUBSYS < "$file"
+    fi
+    findFile file "$__CONFDIR/.defaults/cgroup/inherit" ""
+    if test -n "$file"; then
+       _readFileToArray CGROUP_INHERIT "$file" ""
+    fi
+
+    return 0
+}
+
+function useCgroup
+{
+    hasCgroup || return 1
+    test -d "$CGROUP_MNT" || return 1
+    test -d "$1/cgroup" -o \
+       \( -d "$__CONFDIR/.defaults/cgroup" -a \
+          ! -e "$1/nocgroup" \)
+}
+
+function _handleCgroup
+{
+    local action="$1"
+    local vdir="$2"
+    local dir
+    local name
+    local i
+    local parent
+
+    useCgroup "$vdir" || return 0
+
+    findDir dir "$vdir/cgroup" "$__CONFDIR/.defaults/cgroup" ""
+    test -d "$dir" || return 0
+
+    if test -r "$dir"/name; then
+       read name < "$dir"/name
+    else
+       read name < "$vdir"/name
+    fi
+
+    if test "$action" = "attach"; then
+       if mkdir "$CGROUP_MNT/$name" 2>/dev/null; then
+           parent="$CGROUP_MNT/$name"
+           parent="${parent%/*}"
+            for i in "${CGROUP_INHERIT[@]}"; do
+               test -f "$parent/$i" || continue
+               cat "$parent/$i" > "$CGROUP_MNT/$name/$i"
+           done
+
+           shopt -s nullglob
+           for i in "$dir"/*; do
+               cat "$i" > "$CGROUP_MNT/$name/${i##*/}"
+           done
+       fi
+       echo "$$" > "$CGROUP_MNT/$name/tasks"
+    elif test "$action" = "destroy"; then
+       rmdir "$CGROUP_MNT/$name" 2>/dev/null || :
+    fi
+
+    return 0
+}
+
+function attachToCgroup
+{
+    _handleCgroup attach "$@"
+}
+
+function destroyCgroup
+{
+    _handleCgroup destroy "$@"
+}
index 569c87e..cd3df9f 100644 (file)
@@ -121,6 +121,7 @@ enableInterfaces "$VSERVER_DIR" && have_interfaces=1
 mountVserver     "$VSERVER_DIR" && is_mounted=1
 prepareInit      "$VSERVER_DIR"
 addtoCPUSET      "$VSERVER_DIR"
+attachToCgroup   "$VSERVER_DIR"
 
 handleDeviceMap --set "$S_CONTEXT" "$VSERVER_DIR/apps/vdevmap"
 
index 6c20260..033d0c3 100644 (file)
@@ -126,3 +126,4 @@ saveDiskLimits    "$VSERVER_DIR"
 
 execScriptlets    "$VSERVER_DIR" "$VSERVER_NAME" postpost-stop
 removeCPUSET      "$VSERVER_DIR"
+destroyCgroup     "$VSERVER_DIR"
index 4374143..4f7f035 100755 (executable)
@@ -52,6 +52,14 @@ function create_dirs()
     $_MKDIR -p "$__RUNDIR" && $_MKDIR -p "$__VSHELPERSTATEDIR" && $_MKDIR -p `$_READLINK "$__PKGSTATEREVDIR"`
 }
 
+function mount_cgroup()
+{
+    _generateCgroupOptions
+    test -n "$CGROUP_MNT" || return 0
+    $_MKDIR -p "$CGROUP_MNT"
+    $_MOUNT -t cgroup -o "$CGROUP_SUBSYS" vserver "$CGROUP_MNT"
+}
+
 function start()
 {
     _beginResult $"Creating required directories"
@@ -64,6 +72,11 @@ function start()
     _beginResult $"Loading default device map"
     handleDeviceMap --set 0 "$__CONFDIR/.defaults/apps/vdevmap"
     _endResult $?
+    if hasCgroup; then
+       _beginResult $"Mounting cgroup-hierarchy"
+       mount_cgroup
+       _endResult $?
+    fi
     test "$retval" -ne 0 || touch "$lockfile"
     return $retval
 }