# $VSERVER_NAME ... name of vserver
declare -a NICE_CMD=()
-declare -a CHBIND_OPTS=()
+declare -a IONICE_CMD=()
+declare -a CHBIND_CMD=()
declare -a CAP_OPTS=()
declare -a CHCONTEXT_INIT_OPTS=()
declare -a CHCONTEXT_FLAG_OPTS=()
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=( --default )
+declare -a OPTS_VSPACE_SHARED=()
+declare -a VSPACE_SHARED_CMD=()
declare -a STOPCMD_PREPARE=()
INITSTYLE=sysv
S_CONTEXT=
+N_CONTEXT=
SILENT_OPT=
+CGROUP_MNT=/dev/cgroup
+declare -a CGROUP_SUBSYS=()
+declare -a CGROUP_INHERIT=( cpuset.cpus cpuset.mems )
+CGROUP_BASE=""
+CGROUP_MNT_PER_SS=""
+
: ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
if test -e "$VSERVER_DIR"/noisy -o -n "$OPTION_VERBOSE"; then
SILENT_OPT='--silent'
fi
+function _readFileToArray
+{
+ local _rfta_f="$1"
+ local _rfta_a="$2"
+ local _rfta_p="$3"
+ local _rfta_v
+
+ test -e "$_rfta_f" || return 0
+ while read _rfta_v; do
+ case x"$_rfta_v" in
+ (x|x\#*) ;;
+ (*) eval "$_rfta_a=( \"\${$_rfta_a[@]}\" $_rfta_p \"$_rfta_v\" )";;
+ esac
+ done <"$_rfta_f"
+}
+
function _generateChbindOptions
{
local vdir="$1"
local i
local bcast=
+ local lback=
local nid=
test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
- local f=$vdir/interfaces/bcast
+ if test -e "$vdir"/noncontext -o \
+ \( -e "$vdir"/spaces/net -a ! -e "$vdir"/ncontext \); then
+ _HAVE_CHBIND_OPTIONS=1
+ return 0
+ fi
+
+ local f="$vdir"/interfaces/bcast
getFileValue bcast "$f"
+ f="$vdir"/interfaces/lback
+ getFileValue lback "$f"
- getFileValue nid "$vdir/ncontext" "$vdir/context"
-
- CHBIND_OPTS=( $SILENT_OPT ${nid:+--nid "$nid"} ${bcast:+--bcast "$bcast"} )
+ CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${N_CONTEXT:+--nid "$N_CONTEXT"}
+ ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
+ )
for i in "${INTERFACES[@]}"; do
- CHBIND_OPTS=( "${CHBIND_OPTS[@]}" --ip "$i" )
+ CHBIND_CMD=( "${CHBIND_CMD[@]}" --ip "$i" )
done
+ _readFileToArray "$vdir"/nflags CHBIND_CMD --flag
+ _readFileToArray "$vdir"/ncapabilities CHBIND_CMD --ncap
+
_HAVE_CHBIND_OPTIONS=1
}
NICE_CMD=( $_NICE -n $nice )
}
+function _generateIONiceCommand
+{
+ local vdir=$1
+ local ionice_class=
+ local ionice_priority=
+
+ test -n "$_IONICE" || return 0
+
+ test -r "$vdir/ionice/class" && read ionice_class <"$vdir"/ionice/class
+ test -r "$vdir/ionice/priority" && read ionice_priority <"$vdir"/ionice/priority
+
+ test -n "$ionice_class$ionice_priority" || return 0
+
+ if test -z "$ionice_class" -a -n "$ionice_priority"; then
+ IONICE_CMD=( $_IONICE -c2 -n"$ionice_priority" )
+ else
+ IONICE_CMD=( $_IONICE ${ionice_class:+-c$ionice_class} ${ionice_priority:+-n$ionice_priority} )
+ fi
+}
function _generatePersonalityOptions
{
function _generateCCapabilityOptions
{
local vdir=$1
- local cap
- local f="$vdir"/ccapabilities
-
- test -e "$f" || return 0
- while read cap; do
- case x"$cap" in
- (x|x\#*) ;;
- (*) OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --ccap "$cap" );;
- esac
- done <"$f"
+
+ _readFileToArray "$vdir"/ccapabilities OPTS_VATTRIBUTE --ccap
}
function _generateBCapabilityOptions
{
local vdir=$1
- local cap
- local f="$vdir"/bcapabilities
-
- test -e "$f" || return 0
- while read cap; do
- case x"$cap" in
- (x|x\#*) ;;
- (*) OPTS_VATTRIBUTE=( "${OPTS_VATTRIBUTE[@]}" --bcap "$cap" );;
- esac
- done <"$f"
+
+ _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
+}
+
+function _generateUMaskOptions
+{
+ local vdir=$1
+
+ _readFileToArray "$vdir"/umask OPTS_VATTRIBUTE --umask
}
function _generateCapabilityOptions
CHCONTEXT_INIT_OPTS=()
- getFileValue INITSTYLE "$cfgdir"/style
+ test x"$INITSTYLE" = xrescue || \
+ getFileValue INITSTYLE "$cfgdir"/style
getFileValue RUNLEVEL_START "$cfgdir"/runlevel
getFileValue RUNLEVEL_START "$cfgdir"/runlevel.start
getFileValue RUNLEVEL_STOP "$cfgdir"/runlevel.stop
getFileArray INITKILL_SEQ "$cfgdir"/killseq || :
+ findFile _gio_env "$cfgdir"/environment \
+ "$__CONFDIR"/.defaults/apps/init/environment \
+ "$__PKGLIBDEFAULTDIR"/environment
+ getFileArray OPTS_ENV "$_gio_env" || :
+
case x"$INITSTYLE" in
(xrescue)
INITCMD_START=( "${INITCMD_RESCUE[@]}" )
INITCMD_STOP=( /sbin/killall5 )
- _IS_FAKEINIT=1
- _NEED_VSHELPER_SYNC=
;;
(xsysv)
INITCMD_STOP=( "$i" "$RUNLEVEL_STOP" )
done
INITCMD_PREPARE=( $_FAKE_RUNLEVEL "$RUNLEVEL_START" /var/run/utmp )
+ OPTS_ENV=( "${OPTS_ENV[@]}" PREVLEVEL=N RUNLEVEL="$RUNLEVEL_START" )
+ if test -n "$OPTION_DEBUG_SYSV"; then
+ INITCMD_START=( /bin/bash -x "${INITCMD_START[@]}" )
+ INITCMD_STOP=( /bin/bash -x "${INITCMD_STOP[@]}" )
+ fi
;;
(xplain)
;;
(xgentoo)
- panic "init-style '$INITSTYLE' is no longer supported; please use plain instead; aborting";;
+ test -n "$RUNLEVEL_START" || RUNLEVEL_START="default"
+ RC_PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+ if test -x "$vdir/vdir/lib/rcscripts/sh/init-vserver.sh"; then
+ RC_WRAP=/lib/rcscripts/sh/init-vserver.sh
+ elif test -x "$vdir/vdir/lib/rc/sh/init-vserver.sh"; then
+ RC_WRAP=/lib/rc/sh/init-vserver.sh
+ else
+ panic "init-vserver.sh not found; aborting"
+ fi
+
+ OPTS_ENV=( "${OPTS_ENV[@]}" TERM=$TERM )
+ INITCMD_START=( $RC_WRAP "$RUNLEVEL_START" )
+ INITCMD_STOP=( env -i PATH=$RC_PATH TERM=$TERM RUNLEVEL=0 /sbin/rc shutdown )
+ 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";;
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\#*) ;;
--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
}
}
_generateCapabilityOptions "$vdir"
_generateFlagOptions "$vdir"
+ _generateUMaskOptions "$vdir"
CHCONTEXT_OPTS=( $SILENT_OPT \
"${CHCONTEXT_FLAG_OPTS[@]}" \
function _generateScheduleOptions
{
local vdir=$1
+ if test -d "$vdir"/sched; then
+ OPTS_VSCHED=( --dir "$vdir"/sched --missingok )
+ return 0
+ fi
+
local f="$vdir"/schedule
test -e "$f" || return 0
return 0
}
+function _getTunInfo
+{
+ local iface="$1"
+
+ test -e "$iface/tun" -o -e "$iface/tap" || return 1
+ test ! -e "$iface/tun" || echo --tun
+ test ! -e "$iface/tap" || echo --tap
+ test ! -e "$iface/nocsum" || echo --~checksum
+ test -e "$iface/shared" || echo --nid-failure-ok "$N_CONTEXT"
+ if test -e "$iface/uid"; then
+ local uid
+ getFileValue uid "$iface/uid"
+ echo --uid "$uid"
+ fi
+ if test -e "$iface/gid"; then
+ local gid
+ getFileValue gid "$iface/gid"
+ echo --gid "$gid"
+ fi
+ if test -e "$iface/linktype"; then
+ local linktype
+ getFileValue linktype "$iface/linktype"
+ echo --linktype "$linktype"
+ fi
+ return 0
+}
+
## Usage: _processSingleInterface <interface-directory>
function _processSingleInterface
{
local mac
local extip
local up="up"
+ local peer
_getInterfaceValue ip '' "$iface"
_getInterfaceValue extip '' "$iface" "$iface/.."
_getInterfaceValue name '' "$iface"
_getInterfaceValue scope '' "$iface" "$iface/.."
_getInterfaceValue mac '' "$iface"
+ _getInterfaceValue peer '' "$iface"
test -n "$ip" || { echo $"Can not read ip for '$iface'" >&2; return 1; }
test -n "$dev" -o -e "$iface"/nodev || {
## LEGACY ALERT
test ! -e "$iface"/only_ip || break
- local vlan_info
- if vlan_info=$(_getVLANInfo "$dev"); then
- test -d /proc/net/vlan || {
- echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
- return 1
- }
- test -f /proc/net/vlan -o -e "$iface"/novlandev || {
+ test -e "$iface/vlandev" \
+ -o \( -e "$iface/../vlandev" -a ! -e "$iface/novlandev" \) \
+ -o \( -e "$__CONFDIR/.defaults/interfaces/vlandev" \
+ -a ! -e "$iface/novlandev" \
+ -a ! -e "$iface/../novlandev" \) && {
+ local vlan_info
+ if vlan_info=$(_getVLANInfo "$dev"); then
+ test -d /proc/net/vlan || {
+ echo -e $"VLAN device-name used, but vlan subsystem not enabled.\nTry to execute 'modprobe 8021q' before starting the vservers" >&2
+ return 1
+ }
_addInterfaceCmd VCONFIG $vlan_info
- }
- fi
+ fi
+ }
if ! test -e "$iface"/indirect; then
- _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" broadcast ${bcast:-+} ${name:+label "$dev:$name"} dev "$dev"
+ # XXX: IPv6 hack
+ local use_bcast="broadcast ${bcast:-+}"
+ echo "$ip" | $_GREP -q : && use_bcast=
+
+ local tun_info
+ if tun_info=$(_getTunInfo "$iface"); then
+ _addInterfaceCmd TUNCTL "$dev" $tun_info
+ fi
+
+ _addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev" ${peer:+peer "$peer"}
#_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
_addInterfaceCmd IP_LINK "$dev" $up
- elif ! test -n "$ctx"; then
+ elif ! test -n "$N_CONTEXT"; then
echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
return 1
else
- test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
+ test -z "$mac" || _generateMac mac "$(basename $iface)" "$N_CONTEXT" || return 1
_addInterfaceCmd MODPROBE dummy "$dev"
_addInterfaceCmd IP_LINK dev dummy0 address "$mac"
_addInterfaceCmd NAMEIF "$dev" "$mac"
_addInterfaceCmd IP_ADDR "$ip${prefix:+/$prefix}" dev "$dev"
- test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
+ test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$N_CONTEXT" "$extip"
fi
break
function _generateInterfaceOptions
{
local iface
- local ctx
- test ! -e "$1"/context || read ctx <"$1"/context
+ # XXX: This is here instead of in _generateChbindOptions
+ # to avoid a circular dependency
+ getFileValue N_CONTEXT "$1/ncontext" "$1/context"
+ test -n "$N_CONTEXT" -o -z "$S_CONTEXT" || N_CONTEXT="$S_CONTEXT"
for iface in "$1/interfaces/"*; do
test -d "$iface" || continue
IP_ADDR_FLUSH) $_IP addr flush "$@";;
IP_LINK) $_IP link set "$@";;
IP_ROUTE) $_IP route add "$@";;
+ TUNCTL)
+ local dev="$1"
+ shift
+ $_TUNCTL --persist "$@" "$dev"
+ ;;
*) echo "Unknown interface-command type '$type'" >&2; false;;
esac
IP_ADDR_FLUSH) ;;
IP_LINK) ;; ## Ignore the link-down command for now
IP_ROUTE) $_IP route del "$@";;
+ TUNCTL)
+ local dev="$1"
+ shift
+ $_TUNCTL --~persist "$@" "$dev"
+ ;;
*) echo "Unknown interface-command type '$type'" >&2; false;;
esac
done
unlock 1
}
+function _generateTagOptions
+{
+ local vdir="$1"
+ local tag
+
+ getFileValue tag "$vdir/tag" "$vdir/context"
+ test -n "$tag" || return 0
+
+ OPTS_VTAG_CREATE=( --tag "$tag" )
+ OPTS_VTAG_ENTER=( --tag "$tag" )
+}
+
+function _generateMemctrlOptions
+{
+ local vdir="$1"
+ local badness
+
+ getFileValue badness "$vdir/badness"
+ test -n "$badness" || return 0
+
+ OPTS_VMEMCTRL=( --badness "$badness" )
+}
+
+function _generateSpaceOptions
+{
+ local vdir="$1"
+ local d="$vdir"/spaces
+ local shared
+ local space
+
+ for space in pid net; do
+ if test -e "$d"/$space; then
+ getFileValue shared "$d"/$space || shared=""
+ if test -z "$shared"; then
+ OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --$space )
+ elif test "$shared" = "0"; then
+ : # Do nothing
+ else
+ OPTS_VSPACE_SHARED=( "${OPTS_VSPACE_SHARED[@]}" --$space )
+ VSPACE_SHARED_CMD=( "${VSPACE_SHARED_CMD[@]}" $_VSPACE --enter "$shared" --$space -- )
+ fi
+ fi
+ done
+
+ local mask
+ getFileValue mask "$d"/mask || \
+ OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --mask "$mask" )
+}
+
## Usage: prepareInit <vserver-directory>
function prepareInit
{
pushd "$1/vdir" >/dev/null
case "$INITSTYLE" in
sysv)
- { find var/run ! -type d -print0; \
- find var/lock ! -type d -print0; } | xargs -0r $_CHROOT_SH rm
+ local -a dirs=( $($_CHROOT_SH realpath /var/run /var/lock | $_SED 's!^/*!!' || :) )
+ local dir
+ for dir in "${dirs[@]}"; do
+ $_FIND $dir ! -type d -print0 | xargs -0r $_CHROOT_SH rm
+ done
;;
plain)
$_CHROOT_SH rm .autofsck forcefsck 2>/dev/null || :
pushd "$1/vdir" >/dev/null
case "$INITSTYLE" in
(sysv)
- export PREVLEVEL=$RUNLEVEL_START # required by Debian's initscripts
+ export PREVLEVEL=$RUNLEVEL_START RUNLEVEL=$RUNLEVEL_STOP # required by Debian's initscripts
;;
esac
"${STOPCMD_PREPARE[@]}"
_generateInterfaceOptions "$1"
test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1"
_generateNiceCommand "$1"
+ _generateIONiceCommand "$1"
_generateInitOptions "$1"
_generateChcontextOptions "$1"
_generateScheduleOptions "$1"
_generatePersonalityOptions "$1"
+ _generateTagOptions "$1"
+ _generateMemctrlOptions "$1"
+ _generateSpaceOptions "$1"
+ _generateCgroupOptions
if test -n "$_IS_FAKEINIT"; then
CHCONTEXT_INIT_OPTS=( --disconnect --flag fakeinit )
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 virtualized; do
+ if test -e "$f"/"$i"; then
+ cat "$f"/"$i" >/dev/cpuset/"$cpuset"/"$i" || {
+ 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"
# magic regarding the mtab file; when etc/mtab can not be touched,
# add the '-n' flag to mount
test -w etc -o -w etc/mtab || xflag=-n
+ if test -h etc/mtab; then
+ local l=$($_READLINK etc/mtab)
+ test "${l##/proc/}" = "$l" || xflag=-n
+ fi
"$@" $_SECURE_MOUNT -a $xflag --chroot --fstab "$fstab" --rootfs no
popd >/dev/null
}
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 \
test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
- test -z "$NAMESPACE_CLEANUP" || isAvoidNamespace "$cfgdir" || \
- $_VNAMESPACE --cleanup
-
_mountVserverInternal "$cfgdir"/fstab
_mountVserverInternal "$cfgdir"/fstab.local
- _mountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}"
+ _mountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}"
+
+ isNamespaceCleanup "$cfgdir" && \
+ _namespaceCleanup "$cfgdir"
+ real_vdir=$(getPhysicalDir "$vdir")
isAvoidNamespace "$cfgdir" || \
- $_SECURE_MOUNT --rbind -n "$vdir" "/"
+ $_SECURE_MOUNT --rbind -n -o dev "$vdir" "$real_vdir"
+ ! $_VSERVER_INFO - FEATURE PIVOT_ROOT || \
+ $_SECURE_MOUNT -n -o shared,rec "$real_vdir" "$real_vdir"
}
function _umountVserverInternal
test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$cfgdir"
pushd "$vdir/" >/dev/null || return 1
- _umountVserverInternal "$cfgdir"/fstab.remote $_CHBIND "${CHBIND_OPTS[@]}" || is_ok=
- _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
- _umountVserverInternal "$cfgdir"/fstab || is_ok=
+ _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok=
+ _umountVserverInternal "$cfgdir"/fstab.local || is_ok=
+ _umountVserverInternal "$cfgdir"/fstab || is_ok=
popd >/dev/null || return 1
test -n "$is_ok"
}
+function fsckAllFS
+{
+ local cfgdir=$1
+ local fstab="$cfgdir"/fstab
+ local FSTAB_FILE
+ local fsck_exitcode
+
+ test -e "$fstab" || return 0
+
+ export FSTAB_FILE="$fstab"
+ $_FSCK -s -n -A -T
+ fsck_exitcode=$?
+ test "$fsck_exitcode" -eq 0 -o \
+ "$fsck_exitcode" -eq 1 || return $fsck_exitcode
+}
+
## Usage: waitForSync <vserver> <context> <vshelper-fifo-varname>
function initSync
{
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
ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
"
- find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
+ $_FIND "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
vshelper.doSanityCheck
panic $"\
/proc/uptime can not be accessed. Usually, this is caused by
procfs-security. Please read the FAQ for more details
-http://www.linux-vserver.org/index.php?page=Linux-Vserver+FAQ"
+http://linux-vserver.org/Proc-Security"
+
+ test -e "$cfgdir"/context || {
+ TYPE=$( $_VSERVER_INFO 49152 XIDTYPE )
+ test "$TYPE" != "static" || panic $"\
+The kernel does not have dynamic contexts enabled. Please configure
+a static one by executing
+
+ echo [number between 2 and 49151] > $cfgdir/context"
+ }
}
$_VDLIMIT --xid $ctx "$directory" | \
$_GREP '_used=' > "$vdir/cache/dlimits/$cachename"
+
+ $_VDLIMIT --xid $ctx --remove "$directory"
}
_saveSingleDiskLimit "$vdir" "$dlimit"
done
}
+
+function _namespaceCleanup
+{
+ local vdir="$1"
+ local root=$($_VSERVER_INFO "$1" VDIR 1)
+ local -a list
+ local -a skip
+ local i
+ local j
+
+ getFileArray skip "$vdir"/namespace-cleanup-skip \
+ "$__CONFDIR"/.defaults/namespace-cleanup-skip || :
+
+ # these are things that have to be accessible post-cleanup
+ for i in "$root" "$__SBINDIR" "$__PKGLIBDIR" "$vdir" \
+ "$__PKGSTATEDIR" "$__LOCKDIR" /usr/local /tmp "${skip[@]}"; do
+ local real=`getPhysicalDir "$i"`
+ test "$i" != "$real" || real=
+ for j in "$i" "$real"; do
+ while test -n "$j"; do
+ list=( "${list[@]}" "$j" )
+ j="${j%/*}"
+ done
+ done
+ done
+
+ local -a list_umount
+ while read -r dev path opts; do
+ test -n "$path" || continue
+ for i in "$root" /dev /proc; do
+ path_dir="${path}/"
+ test "${path_dir#${i}/}" != "${path_dir}" && continue 2
+ done
+ for i in "${list[@]}" /; do
+ test "$path" = "$i" && continue 2
+ done
+ # unmount them in reverse order so mounts further down the tree get unmounted first
+ list_umount=( "$path" "${list_umount[@]}" )
+ done < /proc/mounts
+ # separate loop to avoid races while reading /proc/mounts
+ for i in "${list_umount[@]}"; do
+ $_UMOUNT -l -n -i "$i"
+ done
+}
+
+function handleDeviceMap
+{
+ local op="$1"
+ local xid="$2"
+ local dir="$3"
+ local flags device target
+
+ test -d "$dir" || return 0
+ test -n "$xid" || return 0
+
+ for i in "$dir"/*; do
+ test -d "$i" || continue
+
+ local -a vdevmap_opts=()
+ test -e "$i/create" && vdevmap_opts=( "${vdevmap_opts[@]}" --create )
+ test -e "$i/open" && vdevmap_opts=( "${vdevmap_opts[@]}" --open )
+ test -e "$i/remap" && vdevmap_opts=( "${vdevmap_opts[@]}" --remap )
+
+ getFileValue flags "$i/flags" || :
+ getFileValue device "$i/device" || :
+ getFileValue target "$i/target" || :
+ vdevmap_opts=( "${vdevmap_opts[@]}" ${flags:+--flags "$flags"} \
+ ${device:+--device "$device"} ${target:+--target "$target"} )
+
+ $_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
+ _readFileToArray CGROUP_SUBSYS "$file"
+ else
+ CGROUP_SUBSYS=( $($_SED '/^#/d;/^ns[[:space:]]/d;s/[[:space:]].*//' /proc/cgroups) )
+ fi
+ findFile file "$__CONFDIR/.defaults/cgroup/inherit" ""
+ if test -n "$file"; then
+ _readFileToArray CGROUP_INHERIT "$file" ""
+ fi
+ findFile file "$__CONFDIR/.defaults/cgroup/base" ""
+ if test -n "$file"; then
+ read CGROUP_BASE < "$file"
+ test "$CGROUP_BASE" != "${CGROUP_BASE%/}" || \
+ CGROUP_BASE="${CGROUP_BASE}/"
+ fi
+ findFile file "$__CONFDIR/.defaults/cgroup/per-ss" ""
+ if test -n "$file"; then
+ CGROUP_MNT_PER_SS=1
+ fi
+
+ return 0
+}
+
+function useCgroup
+{
+ hasCgroup || return 1
+ if test -n "$CGROUP_MNT_PER_SS"; then
+ local existing=0
+ local ss
+ for ss in "${CGROUP_SUBSYS[@]}"; do
+ if test -e "$CGROUP_MNT/$ss/tasks"; then
+ let existing=${existing}+1
+ fi
+ done
+ test "$existing" -gt 0 || return 1
+ else
+ test -e "$CGROUP_MNT/tasks" || return 1
+ fi
+ local memcg=""
+ if $_VSERVER_INFO - FEATURE memcg; then
+ memcg=1
+ fi
+ test -d "$1/cgroup" -o \
+ \( \( -d "$__CONFDIR/.defaults/cgroup" -o -n "$memcg" \) -a \
+ ! -e "$1/nocgroup" \)
+}
+
+function _handleCgroup
+{
+ local action="$1"
+ local vdir="$2"
+ local dir
+ local name
+ local i
+ local j
+ local parent
+ local -a mnts
+ local ss
+
+ useCgroup "$vdir" || return 0
+
+ findDir dir "$vdir/cgroup" "$__CONFDIR/.defaults/cgroup" ""
+
+ if test -n "$dir" -a -r "$dir"/name; then
+ read name < "$dir"/name
+ else
+ name="$VSERVER_NAME"
+ fi
+
+ if test -n "$CGROUP_MNT_PER_SS"; then
+ mnts=()
+ for ss in "${CGROUP_SUBSYS[@]}"; do
+ mnts=( "${mnts[@]}" "$CGROUP_MNT/$ss" )
+ done
+ else
+ mnts=( "$CGROUP_MNT" )
+ fi
+ for mnt in "${mnts[@]}"; do
+ test -d "$mnt" || continue
+ if test "$action" = "attach"; then
+ if test -n "$CGROUP_BASE"; then
+ local -a dirs=()
+ i="$mnt/$CGROUP_BASE"
+ while test "$mnt" != "$i"; do
+ dirs=( "$i" "${dirs[@]}" )
+ i="${i%/*}"
+ done
+ for i in "${dirs[@]}"; do
+ if mkdir "$i" 2>/dev/null; then
+ parent="${i%/*}"
+ for j in "${CGROUP_INHERIT[@]}"; do
+ test -f "$parent/$j" || continue
+ cat "$parent/$j" > "$i/$j"
+ done
+ fi
+ done
+ fi
+ if mkdir "$mnt/$CGROUP_BASE$name" 2>/dev/null; then
+ parent="$mnt/$CGROUP_BASE$name"
+ parent="${parent%/*}"
+ for i in "${CGROUP_INHERIT[@]}"; do
+ test -f "$parent/$i" || continue
+ cat "$parent/$i" > "$mnt/$CGROUP_BASE$name/$i"
+ done
+
+ if test -n "$dir"; then
+ shopt -s nullglob
+ for i in "$dir"/*; do
+ f="${i##*/}"
+ test "$f" != mnt -a "$f" != subsys -a \
+ "$f" != inherit -a "$f" != name -a "$f" != base -a \
+ "$f" != per-ss \
+ || continue
+ if test -n "$CGROUP_MNT_PER_SS"; then
+ ss="${f%%.*}"
+ test "$ss" = "${mnt##*/}" || continue
+ fi
+ cat "$i" > "$mnt/$CGROUP_BASE$name/$f"
+ done
+ fi
+ fi
+ echo "$$" > "$mnt/$CGROUP_BASE$name/tasks"
+ elif test "$action" = "destroy"; then
+ rmdir "$mnt/$name" 2>/dev/null || :
+ fi
+ done
+
+ return 0
+}
+
+function attachToCgroup
+{
+ _handleCgroup attach "$@"
+}
+
+function destroyCgroup
+{
+ _handleCgroup destroy "$@"
+}