From 82ff4f51e5d0728af09cb71ee89f8cb0fd2b52d625407ea156846bc61355f6a2 Mon Sep 17 00:00:00 2001 From: Charles Arnold Date: Tue, 21 Jun 2016 14:56:06 +0000 Subject: [PATCH] - bsc#954872 - script block-dmmd not working as expected - libxl: error: libxl_dm.c (Additional fixes) block-dmmd OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=441 --- block-dmmd | 361 +++++++++++++++++++++++++++++++--------------------- xen.changes | 7 + 2 files changed, 222 insertions(+), 146 deletions(-) diff --git a/block-dmmd b/block-dmmd index 64475ed..f9cfb67 100644 --- a/block-dmmd +++ b/block-dmmd @@ -2,7 +2,7 @@ # Usage: block-dmmd [add args | remove args] # -# the dmmd device syntax (in xm commands/configs) is something like: +# the dmmd device syntax (in xm/xl commands/configs) is something like: # dmmd:md;/dev/md0;md;/dev/md1;lvm;/dev/vg1/lv1 # or # dmmd:lvm;/dev/vg1/lv1;lvm;/dev/vg1/lv2;md;/dev/md0 @@ -16,30 +16,49 @@ # dmmd:md;My-MD-name;lvm;/dev/vg1/lv1 # # History: +# 2016-05-27, mlatimer@suse.com: +# Merge improvements by loic.devulder@mpsa.com. Highlights include: +# - Re-write and simplification to speed up the script! +# - Add some (useful) logging messages and comments +# Minor tweaks and logging improvements +# 2016-05-26, mlatimer@suse.com: +# Verify MD activation if mdadm returns 2 +# 2016-05-20, mlatimer@suse.com: +# Strip leading "dmmd:" if present in xenstore params value # 2013-07-03, loic.devulder@mpsa.com: -# Partial rewrite of the script for supporting MD activation by name +# Partial rewrite of the script for supporting MD activation by name # 2009-06-09, mh@novell.com: -# Emit debugging messages into a temporary file; if no longer needed, -# just comment the exec I/O redirection below -# Make variables used in functions local to avoid global overridings -# Use vgscan and vgchange where required -# Use the C locale to avoid dealing with localized messages -# Assign output from assembling an MD device to a variable to aid debugging +# Emit debugging messages into a temporary file; if no longer needed, +# just comment the exec I/O redirection below +# Make variables used in functions local to avoid global overridings +# Use vgscan and vgchange where required +# Use the C locale to avoid dealing with localized messages +# Assign output from assembling an MD device to a variable to aid +# debugging -# We do not want to deal with localized messages: -LANG=C -LC_MESSAGES=C -export LANG LC_MESSAGES +# We do not want to deal with localized messages +# We use LC_ALL because LC_ALL superse LANG +# But we also use LANG because some applications may still use LANG... +export LC_ALL=C +export LANG=${LC_ALL} -dir=$(dirname "$0") -. "$dir/block-common.sh" +# Loading common libraries +. $(dirname $0)/block-common.sh -#exec >> /tmp/block-dmmd-`date +%F_%T.%N`.log 2>&1 -#echo shell-flags: $- +# Constants +typeset -rx MDADM_BIN=/sbin/mdadm +typeset -rx LVCHANGE_BIN=/sbin/lvchange +typeset -rx PVSCAN_BIN=/sbin/pvscan +typeset -rx VGSCAN_BIN=/sbin/vgscan +typeset -rx VGCHANGE_BIN=/sbin/vgchange +typeset -rx DATE_LOG="date +%F_%T.%N" +typeset -rx DATE_SEC="date +%s" -command=$1 +# Uncomment for debugging purposes +# exec >> /tmp/block-dmmd-$(${DATE_LOG}).log 2>&1 +# echo shell-flags: $- -# We check for errors ourselves: +# We check for errors ourselves set +e function run_mdadm() @@ -48,21 +67,24 @@ function run_mdadm() local msg local rc - msg="$(/sbin/mdadm $mdadm_cmd 2>&1)" + msg="$(${MDADM_BIN} ${mdadm_cmd} 2>&1)" rc=$? - case "$msg" in - *"has been started"* | *"already active"* ) - return 0 - ;; - *"is already in use"* ) - # hmm, might be used by another device in this domU - # leave it to upper layers to detect a real error - return 2 - ;; - * ) - return $rc - ;; + case "${msg}" in + *"has been started"* | *"already active"*) + return 0 + ;; + *"is already in use"*) + # Hmm, might be used by another device in this domU + # Leave it to upper layers to detect a real error + return 2 + ;; + *) + return ${rc} + ;; esac + + # Normally we should not get here, but if this happens + # we have to return an error return 1 } @@ -72,36 +94,49 @@ function activate_md() local par=$1 local cfg dev dev_path rc t mdadm_opts - if [ ${par} = ${par%%(*} ]; then + if [[ ${par} == ${par%%(*} ]]; then # No configuration file specified - dev=$par - cfg= + dev=${par} + cfg="" else - dev=${par%%(*} - t=${par#*(} - cfg="-c ${t%%)*}" + dev=${par%%(*} + t=${par#*(} + cfg="-c ${t%%)*}" fi # Looking for device name or aliase - if [ ${dev:0:1} = / ]; then - dev_path=${dev%/*} - mdadm_opts= + if [[ ${dev:0:1} == / ]]; then + dev_path=${dev%/*} + mdadm_opts="" else - dev_path=/dev/md - mdadm_opts="-s -N" + dev_path=/dev/md + mdadm_opts="-s -N" fi - # Is md device already active? + # Logging message + echo "[$(${DATE_LOG})] activate MD device ${dev}..." >&2 + + # Is MD device already active? # We need to use full path name, aliase is not possible... if [ -e $dev_path/${dev##*/} ]; then - /sbin/mdadm -Q -D $dev_path/${dev##*/} 2>/dev/null | grep -iq state.*\:.*inactive || return 0 + ${MDADM_BIN} -Q -D $dev_path/${dev##*/} 2>/dev/null \ + | grep -iq state.*\:.*inactive || return 0 fi - run_mdadm "-A $mdadm_opts $dev $cfg" + # Activate MD device + run_mdadm "-A ${mdadm_opts} ${dev} ${cfg}" rc=$? - [ $rc -eq 2 ] && return 0 + # A return code of 2 can indicate the array configuration was incorrect + if [[ ${rc} == 2 ]]; then + # Logging message + echo "[$(${DATE_LOG})] verifying MD device ${dev} activation..." >&2 - return $rc + # If the array is active, return 0, otherwise return an error + ${MDADM_BIN} -Q -D $dev_path/${dev##*/} &>/dev/null && return 0 \ + || return 1 + fi + + return ${rc} } function deactivate_md() @@ -109,22 +144,25 @@ function deactivate_md() local par=$1 local dev - if [ ${par} = ${par%%(*} ]; then + if [[ ${par} == ${par%%(*} ]]; then # No configuration file specified - dev=${par} + dev=${par} else - dev=${par%%(*} + dev=${par%%(*} fi # Looking for device name or aliase - if [ ${dev:0:1} = / ]; then - dev_path=${dev%/*} + if [[ ${dev:0:1} == / ]]; then + dev_path=${dev%/*} else - dev_path=/dev/md + dev_path=/dev/md fi + # Logging message + echo "[$(${DATE_LOG})] deactivate MD device ${dev}..." >&2 + # We need the device name only while deactivating - /sbin/mdadm -S ${dev_path}/${dev##*/} > /dev/null 2>&1 + ${MDADM_BIN} -S ${dev_path}/${dev##*/} > /dev/null 2>&1 return $? } @@ -132,169 +170,200 @@ function deactivate_md() function activate_lvm() { local run_timeout=90 + local parsed_timeout local end_time + # If /etc/xen/xend-config.sxp exists (e.g. SLES11), use + # device-create-timeout, instead of the default setting + if [[ -f /etc/xen/xend-config.sxp ]]; then + parsed_timeout=$(grep -v "^[ \t]*#.*" /etc/xen/xend-config.sxp \ + |sed -n 's/(device-create-timeout \+\([0-9]\+\))/\1/p') + if [[ ! -z $parsed_timeout ]]; then + run_timeout=$((${parsed_timeout}*9/10)) + fi + fi + # First scan for PVs and VGs - # We need this for using md device as PV - /sbin/pvscan > /dev/null 2>&1 -# /sbin/vgscan --mknodes > /dev/null 2>&1 + # We need this for using MD device as PV + ${PVSCAN_BIN} > /dev/null 2>&1 +# ${VGSCAN_BIN} --mknodes > /dev/null 2>&1 + + # Logging message + echo "[$(${DATE_LOG})] activate LVM device ${dev}..." >&2 + + # Set end_time for the loop + (( end_time = $(${DATE_SEC}) + run_timeout )) - end_time=$(($(date +%s)+${run_timeout})) while true; do - /sbin/lvchange -aey $1 > /dev/null 2>&1 + ${LVCHANGE_BIN} -aey $1 > /dev/null 2>&1 - if [ $? -eq 0 -a -e $1 ]; then - return 0 - fi + if [ $? -eq 0 -a -e $1 ]; then + return 0 + fi - sleep 0.1 - if [ $(date +%s) -ge ${end_time} ]; then - log err "Failed to activate $1 within ${run_timeout} seconds" - return 1 - fi + sleep 0.1 + # If it takes too long we need to return an error + if (( $(${DATE_SEC}) >= end_time )); then + log err "Failed to activate $1 within ${run_timeout} seconds" + return 1 + fi done + + # Normally we should not get here, but if this happens + # we have to return an error return 1 } function deactivate_lvm() { - /sbin/lvchange -aen $1 > /dev/null 2>&1 + # Logging message + echo "[$(${DATE_LOG})] deactivate LVM device ${dev}..." >&2 + + ${LVCHANGE_BIN} -aen $1 > /dev/null 2>&1 if [ $? -eq 0 ]; then - # We may have to deactivate the VG now, but can ignore errors: -# /sbin/vgchange -an ${1%/*} || : + # We may have to deactivate the VG now, but can ignore errors: +# ${VGCHANGE_BIN} -an ${1%/*} || : # Maybe we need to cleanup the LVM cache: -# /sbin/vgscan --mknodes || : - return 0 +# ${VGSCAN_BIN} --mknodes || : + return 0 fi return 1 } -BP=100 -SP=$BP -VBD= +# Variables +typeset command=$1 +typeset BP=100 +typeset SP=${BP} +typeset VBD +typeset -a stack -declare -a stack function push() { - if [ -z "$1" ]; then - return - fi - let "SP -= 1" - stack[$SP]="${1}" + local value="$1" + + [[ -n "${value}" ]] \ + && stack[$((--SP))]="${value}" + + return 0 } function pop() { - VBD= + [[ "${SP}" != "${BP}" ]] \ + && VBD=${stack[$((SP++))]} \ + || VBD="" - if [ "$SP" -eq "$BP" ]; then - return - fi - - VBD=${stack[$SP]} - let "SP += 1" + return 0 } function activate_dmmd() { - case $1 in - md) + case "$1" in + "md") activate_md $2 - return + return $? ;; - lvm) + "lvm") activate_lvm $2 - return + return $? ;; esac + + # Normally we should not get here, but if this happens + # we have to return an error + return 1 } function deactivate_dmmd() { case "$1" in - md) + "md") deactivate_md $2 - return + return $? ;; - lvm) + "lvm") deactivate_lvm $2 - return + return $? ;; esac + + # Normally we should not get here, but if this happens + # we have to return an error + return 1 } function cleanup_stack() { - while [ 1 ]; do + while true; do pop - if [ -z "$VBD" ]; then - break - fi - deactivate_dmmd $VBD + [[ -z "${VBD}" ]] && break + deactivate_dmmd ${VBD} done } function parse_par() { - local ac par rc s t # Make these explicitly local vars + # Make these vars explicitly local + local ac par rc s t ac=$1 par="$2" - par="$par;" - while [ 1 ]; do + par="${par};" + while true; do t=${par%%;*} - if [ -z "$t" ]; then - return 0 - fi + + [[ -z "${t}" ]] && return 0 par=${par#*;} s=${par%%;*} - if [ -z "$s" ]; then - return 1 - fi + [[ -z "${s}" ]] && return 1 par=${par#*;} - if [ "$ac" = "activate" ]; then - activate_dmmd $t $s - rc=$? - if [ $rc -ne 0 ]; then - return 1 - fi + if [[ "${ac}" == "activate" ]]; then + activate_dmmd ${t} ${s} \ + || return 1 fi - push "$t $s" + push "${t} ${s}" done } +case "${command}" in + "add") + p=$(xenstore-read ${XENBUS_PATH}/params) || true + claim_lock "dmmd" + dmmd=${p#dmmd:} -case "$command" in - add) - p=`xenstore-read $XENBUS_PATH/params` || true - claim_lock "dmmd" - dmmd=${p#dmmd:} - parse_par activate "$dmmd" - rc=$? - if [ $rc -ne 0 ]; then - cleanup_stack - release_lock "dmmd" - exit 1 - fi - lastparam=${dmmd##*;} - usedevice=${lastparam%(*} - xenstore-write $XENBUS_PATH/node "$usedevice" - write_dev "$usedevice" - release_lock "dmmd" - exit 0 - ;; + if ! parse_par activate "${dmmd}"; then + cleanup_stack + release_lock "dmmd" + exit 1 + fi - remove) - p=`xenstore-read $XENBUS_PATH/params` || true - claim_lock "dmmd" - dmmd=${p#dmmd:} - parse_par noactivate "$dmmd" - cleanup_stack - release_lock "dmmd" - exit 0 - ;; + lastparam=${dmmd##*;} + usedevice=${lastparam%(*} + xenstore-write ${XENBUS_PATH}/node "${usedevice}" + write_dev "${usedevice}" + release_lock "dmmd" + + exit 0 + ;; + + "remove") + p=$(xenstore-read ${XENBUS_PATH}/params) || true + claim_lock "dmmd" + dmmd=${p#dmmd:} + + parse_par noactivate "${dmmd}" + + cleanup_stack + release_lock "dmmd" + + exit 0 + ;; esac + +# Normally we should not get here, but if this happens +# we have to return an error +return 1 diff --git a/xen.changes b/xen.changes index 2a1abff..3654e95 100644 --- a/xen.changes +++ b/xen.changes @@ -5,6 +5,13 @@ Tue Jun 21 08:26:51 MDT 2016 - carnold@suse.com xen-4.7.0-testing-src.tar.bz2 - Drop CVE-2014-3672-qemut-xsa180.patch +------------------------------------------------------------------- +Thu Jun 16 16:27:25 MDT 2016 - carnold@suse.com + +- bsc#954872 - script block-dmmd not working as expected - libxl: + error: libxl_dm.c (Additional fixes) + block-dmmd + ------------------------------------------------------------------- Fri Jun 10 14:23:51 UTC 2016 - ohering@suse.de