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=()
SILENT_OPT=
CGROUP_MNT=/dev/cgroup
-CGROUP_SUBSYS=all
+declare -a CGROUP_SUBSYS=()
declare -a CGROUP_INHERIT=( cpuset.cpus cpuset.mems )
+CGROUP_BASE=""
+CGROUP_MNT_PER_SS=""
: ${VSERVER_NAME:=$(basename "$VSERVER_DIR")}
test -n "$_HAVE_INTERFACE_OPTIONS" || _generateInterfaceOptions "$vdir"
+ 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
function _generateIONiceCommand
{
local vdir=$1
- local ionice_class=2
- local ionice_priority=0
+ 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
- IONICE_CMD=( $_IONICE -c$ionice_class -n$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
_readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap
}
+function _generateUMaskOptions
+{
+ local vdir=$1
+
+ _readFileToArray "$vdir"/umask OPTS_VATTRIBUTE --umask
+}
+
function _generateCapabilityOptions
{
local vdir=$1
panic "init-vserver.sh not found; aborting"
fi
- INITCMD_START=( env TERM=$TERM $RC_WRAP "$RUNLEVEL_START" )
+ 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 )
;;
_generateCapabilityOptions "$vdir"
_generateFlagOptions "$vdir"
+ _generateUMaskOptions "$vdir"
CHCONTEXT_OPTS=( $SILENT_OPT \
"${CHCONTEXT_FLAG_OPTS[@]}" \
IP_ADDR_FLUSH) ;;
IP_LINK) ;; ## Ignore the link-down command for now
IP_ROUTE) $_IP route del "$@";;
- TUNCTL) $_TUNCTL --~persist "$1";;
+ TUNCTL)
+ local dev="$1"
+ shift
+ $_TUNCTL --~persist "$@" "$dev"
+ ;;
*) echo "Unknown interface-command type '$type'" >&2; false;;
esac
done
{
local vdir="$1"
local d="$vdir"/spaces
-
- ( test ! -e "$d"/pid ) || \
- OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --pid )
-
- test ! -e "$d"/net || {
- OPTS_VSPACE=( "${OPTS_VSPACE[@]}" --net )
- # network context and namespace don't make much sense
- _HAVE_CHBIND_OPTIONS=1
- CHBIND_CMD=()
- }
+ 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 || \
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 || :
# 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
}
ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache
"
- find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
+ $_FIND "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';'
vshelper.doSanityCheck
done
done
+ # keep cgroup mount points
+ list=( "${list[@]}" "${CGROUP_MNT}" )
+ if test -n "$CGROUP_MNT_PER_SS"; then
+ for ss in "${CGROUP_SUBSYS[@]}"; do
+ list=( "${list[@]}" "${CGROUP_MNT}/${ss}" )
+ done
+ fi
+
local -a list_umount
while read -r dev path opts; do
test -n "$path" || continue
- for i in "$root" /dev /proc; do
- test "${path#$i}" != "$path" && continue 2
+ path_dir="${path}/"
+ for i in "$root" /dev /proc /sys; do
+ test "${path_dir#${i}/}" != "${path_dir}" && continue 2
done
for i in "${list[@]}" /; do
test "$path" = "$i" && continue 2
hasCgroup || return 0
- findFile file "$__CONFDIR/.defaults/cgroup/mnt" ""
+ findFile file "$__CONFDIR/.defaults/cgroup/subsys" ""
if test -n "$file"; then
- read CGROUP_MNT < "$file"
+ _readFileToArray CGROUP_SUBSYS "$file"
+ else
+ CGROUP_SUBSYS=( $($_AWK '/^#/ { next; } $1 == "ns" { next; } $4 != "0" { print $1; }' /proc/cgroups) )
fi
- findFile file "$__CONFDIR/.defaults/cgroup/subsys" ""
+ findFile file "$__CONFDIR/.defaults/cgroup/mnt" ""
if test -n "$file"; then
- read CGROUP_SUBSYS < "$file"
+ read CGROUP_MNT < "$file"
+ elif test -d /sys/fs/cgroup; then
+ CGROUP_MNT=/sys/fs/cgroup
+ CGROUP_MNT_PER_SS=1
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
- test -d "$CGROUP_MNT" || 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" -a \
+ \( \( -d "$__CONFDIR/.defaults/cgroup" -o -n "$memcg" \) -a \
! -e "$1/nocgroup" \)
}
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" ""
- test -d "$dir" || return 0
- if test -r "$dir"/name; then
+ if test -n "$dir" -a -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 || :
+ 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
}