X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=scripts%2Fvserver.functions;h=77ca912b97af9272610a6c13c645e74d9de69e7a;hb=HEAD;hp=3878446b8c31ee7036e3cce1d9ec0a82ab9f0456;hpb=632060253a50825d6553ff56ecb89a5ef7a2dd95;p=util-vserver.git diff --git a/scripts/vserver.functions b/scripts/vserver.functions index 3878446..77ca912 100644 --- a/scripts/vserver.functions +++ b/scripts/vserver.functions @@ -41,13 +41,17 @@ declare -a ENTER_SHELL=() declare -a OPTS_VCONTEXT_CREATE=() declare -a OPTS_VCONTEXT_MIGRATE=() declare -a OPTS_VCONTEXT_ENTER=() +OPT_VCONTEXT_CHROOT=--chroot +OPT_VCONTEXT_CLOSE_FD="" 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 OPTS_VSPACE_SHARED=() +declare -a VSPACE_SHARED_CMD=() declare -a STOPCMD_PREPARE=() @@ -72,8 +76,10 @@ N_CONTEXT= 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")} @@ -109,6 +115,12 @@ function _generateChbindOptions 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 @@ -143,13 +155,21 @@ function _generateNiceCommand 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 @@ -193,6 +213,13 @@ function _generateBCapabilityOptions _readFileToArray "$vdir"/bcapabilities OPTS_VATTRIBUTE --bcap } +function _generateUMaskOptions +{ + local vdir=$1 + + _readFileToArray "$vdir"/umask OPTS_VATTRIBUTE --umask +} + function _generateCapabilityOptions { local vdir=$1 @@ -329,7 +356,7 @@ function _generateInitOptions ! isNumber "${RUNLEVEL_START:-3}" || INITCMD_PREPARE=( $_FAKE_RUNLEVEL "${RUNLEVEL_START:-3}" /var/run/utmp ) ;; - (xgentoo) + (xgentoo|xopenrc) test -n "$RUNLEVEL_START" || RUNLEVEL_START="default" RC_PATH=/usr/sbin:/usr/bin:/sbin:/bin @@ -341,7 +368,8 @@ function _generateInitOptions 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 ) ;; @@ -381,10 +409,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\#*) ;; @@ -398,11 +428,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 } } @@ -424,6 +456,7 @@ function _generateChcontextOptions _generateCapabilityOptions "$vdir" _generateFlagOptions "$vdir" + _generateUMaskOptions "$vdir" CHCONTEXT_OPTS=( $SILENT_OPT \ "${CHCONTEXT_FLAG_OPTS[@]}" \ @@ -435,6 +468,8 @@ function _generateChcontextOptions OPTS_VCONTEXT_CREATE=( $SILENT_OPT \ ${ctx:+--xid "$ctx"} ) + findFile file "$vdir"/keepfds "$__CONFDIR/.defaults/keepfds" "" + test -n "$file" || OPT_VCONTEXT_CLOSE_FD="--closefd" ## put '--secure' at front so that it can be overridden OPTS_VATTRIBUTE=( --secure --flag default "${OPTS_VATTRIBUTE[@]}" ) } @@ -744,7 +779,11 @@ function disableInterfaces 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 @@ -779,16 +818,22 @@ function _generateSpaceOptions { 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 || \ @@ -801,8 +846,11 @@ 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 || : @@ -911,6 +959,10 @@ function _mountVserverInternal # 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 } @@ -938,6 +990,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 \ @@ -958,8 +1012,11 @@ function mountVserver isNamespaceCleanup "$cfgdir" && \ _namespaceCleanup "$cfgdir" + real_vdir=$(getPhysicalDir "$vdir") isAvoidNamespace "$cfgdir" || \ - $_SECURE_MOUNT --rbind -n -o dev "$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 @@ -1201,7 +1258,7 @@ WARNING: There is no cachedirectory configured for this vserver; ln -s ../.defaults/cachebase/$VSERVER_NAME $cfgdir/cache " - find "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';' + $_FIND "$cfgdir" -type f -exec "$_CHECK_UNIXFILE" '{}' ';' vshelper.doSanityCheck @@ -1362,11 +1419,20 @@ function _namespaceCleanup 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 @@ -1419,18 +1485,33 @@ function _generateCgroupOptions 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 -a -d /sys/fs/cgroup/"${CGROUP_SUBSYS[0]}"; 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 } @@ -1438,9 +1519,24 @@ function _generateCgroupOptions 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" \) } @@ -1451,37 +1547,78 @@ function _handleCgroup 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 - read name < "$vdir"/name + 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 }