Use pivot_root on kernels supporting two namespaces per context.
[util-vserver.git] / scripts / vserver.functions
index db64fec..63d1bad 100644 (file)
@@ -41,13 +41,14 @@ declare -a ENTER_SHELL=()
 declare -a OPTS_VCONTEXT_CREATE=()
 declare -a OPTS_VCONTEXT_MIGRATE=()
 declare -a OPTS_VCONTEXT_ENTER=()
+OPT_VCONTEXT_CHROOT=--chroot
 declare -a OPTS_VATTRIBUTE=( --flag fakeinit )
 declare -a OPTS_VSCHED=()
 declare -a OPTS_ENV=()
 declare -a OPTS_VTAG_CREATE=()
 declare -a OPTS_VTAG_ENTER=()
 declare -a OPTS_VMEMCTRL=()
-declare -a OPTS_VSPACE=()
+declare -a OPTS_VSPACE=( --default )
 
 declare -a STOPCMD_PREPARE=()
 
@@ -71,6 +72,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
@@ -342,6 +347,13 @@ function _generateInitOptions
            INITCMD_PREPARE=( $_FAKE_RUNLEVEL 3 /var/run/utmp )
            ;;
 
+       (xarch)
+           test -n "$RUNLEVEL_START" || RUNLEVEL_START=3
+           INITCMD_START=( /etc/rc.multi )
+           INITCMD_STOP=( /etc/rc.shutdown )
+           INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
+           ;;
+
        (x) ;;
        (*) panic "Unknown init-style '$INITSTYLE'; aborting";;
     esac
@@ -370,10 +382,12 @@ function _generateInitOptions
 function _generateFlagOptions
 {
     local vdir=$1
+    local file
 
     CHCONTEXT_FLAG_OPTS=()
 
-    test ! -e "$vdir"/flags || \
+    findFile file "$vdir"/cflags "$vdir"/flags ""
+    test -z "$file" || \
     while read flag; do
        case x"$flag" in
            (x|x\#*)            ;;
@@ -387,11 +401,13 @@ function _generateFlagOptions
                                      --flag "$flag" )
                ;;
        esac
-    done <"$vdir"/flags
+    done <"$file"
 
     isAvoidNamespace "$vdir" || {
        USE_VNAMESPACE=1
        CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
+       ! $_VSERVER_INFO - FEATURE PIVOT_ROOT || \
+           OPT_VCONTEXT_CHROOT=--pivot-root
     }
 }
 
@@ -769,8 +785,7 @@ function _generateSpaceOptions
     local vdir="$1"
     local d="$vdir"/spaces
 
-    ( test ! -e "$d"/pid &&
-      ! $_VSERVER_INFO PIDSPACE FEATURE ) || \
+    ( test ! -e "$d"/pid ) || \
        OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
 
     test ! -e "$d"/net || {
@@ -832,6 +847,7 @@ function generateOptions
     _generateTagOptions         "$1"
     _generateMemctrlOptions     "$1"
     _generateSpaceOptions       "$1"
+    _generateCgroupOptions
 
     if test -n "$_IS_FAKEINIT"; then
        CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
@@ -927,6 +943,8 @@ function mountVserver
     local ns_opt=$2
     local vdir=$1/vdir
     local mtab_src
+    local extra_opt=
+    local real_vdir
 
     test -e "$cfgdir"/fstab -o \
          -e "$cfgdir"/fstab.local -o \
@@ -947,8 +965,11 @@ function mountVserver
     isNamespaceCleanup "$cfgdir" && \
         _namespaceCleanup "$cfgdir"
 
+    real_vdir=$(getPhysicalDir "$vdir")
+    ! $_VSERVER_INFO - FEATURE PIVOT_ROOT || \
+       extra_opt=,shared
     isAvoidNamespace "$cfgdir" || \
-       $_SECURE_MOUNT --rbind -n "$vdir" "/"
+       $_SECURE_MOUNT --rbind -n -o dev$extra_opt "$vdir" "$real_vdir"
 }
 
 function _umountVserverInternal
@@ -1033,7 +1054,7 @@ function initWait
            rc=$?
 
            if test "$rc" -ne 0 -a "$rc" -ne 1; then
-               $_VPS axf | $_EGREP -e "^[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
+               $_VPS axf | $_EGREP -e "^[ \t]*[^ \t]+[ \t]+$S_CONTEXT[ \t]+" >&4
                killContext "$S_CONTEXT" 9
            fi
 
@@ -1396,3 +1417,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
+       name="$VSERVER_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 "$@"
+}