[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] hotplug: Update block-tap
commit 76a484193dbb6a11b101c1d01a5088f468f93080 Author: Jason Andryuk <jandryuk@xxxxxxxxx> AuthorDate: Thu Apr 25 09:46:56 2024 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Thu Apr 25 09:46:56 2024 +0200 hotplug: Update block-tap Implement a sharing check like the regular block script. Checking tapback inside block-tap is too late since it needs to be running to transition the backend to InitWait before block-tap is run. tap-ctl check will be removed when the requirement for the blktap kernel driver is removed. Remove it now as it is of limited use. find_device() needs to be non-fatal allow a sharing check. Only write physical-device-path because that is all that tapback needs. Also write_dev doesn't handled files and would incorrectly store physical-device as 0:0 which would confuse the minor inside tapback Signed-off-by: Jason Andryuk <jandryuk@xxxxxxxxx> Signed-off-by: Jason Andryuk <jason.andryuk@xxxxxxx> Reviewed-by: Anthony PERARD <anthony.perard@xxxxxxxxxx> --- tools/hotplug/Linux/block-tap | 169 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 157 insertions(+), 12 deletions(-) diff --git a/tools/hotplug/Linux/block-tap b/tools/hotplug/Linux/block-tap index 89247921b9..126e472786 100755 --- a/tools/hotplug/Linux/block-tap +++ b/tools/hotplug/Linux/block-tap @@ -18,11 +18,11 @@ # # Usage: # -# Target should be specified using the following syntax: +# Disks should be specified using the following syntax: # -# script=block-tap,vdev=xvda,target=<type>:<file> +# vdev=xvda,backendtype=tap,format=vhd,target=/srv/target.vhd # -# Type is either "aio" (for raw files), or "vhd" +# format is either "aio" (for raw files), or "vhd" dir=$(dirname "$0") . "$dir/block-common.sh" @@ -37,10 +37,6 @@ check_tools() if ! command -v tap-ctl > /dev/null 2>&1; then fatal "Unable to find tap-ctl tool" fi - modprobe blktap - if ! tap-ctl check >& /dev/null ; then - fatal "Blocktap kernel module not available" - fi } # Sets the following global variables based on the params field passed in as @@ -81,7 +77,109 @@ find_device() done if [ -z "$pid" ] || [ -z "$minor" ]; then - fatal "cannot find required parameters" + return 1 + fi + + return 0 +} + +count_using() +{ + local file="$1" + local dom + local dev + local f + + local i=0 + local base_path="$XENBUS_BASE_PATH/$XENBUS_TYPE" + for dom in $(xenstore-list "$base_path") + do + for dev in $(xenstore-list "$base_path/$dom") + do + f=$(xenstore_read_default "$base_path/$dom/$dev/params" "") + f=$(echo "$f" | cut -d ":" -f 2) + + if [ -n "$f" ] && [ "$file" = $f ] ; then + i=$(( i + 1 )) + fi + done + done + + echo "$i" +} + +# tap_shared is used to determine if a shared tap can be closed +# Since a stubdom and a guest both use the same tap, it can only +# be freed when there is a single one left. +tap_shared() { + [ $( count_using "$file" ) -gt 1 ] +} + +check_tap_sharing() +{ + local file="$1" + local mode="$2" + local dom + local dev + + local base_path="$XENBUS_BASE_PATH/$XENBUS_TYPE" + for dom in $(xenstore-list "$base_path") ; do + for dev in $(xenstore-list "$base_path/$dom") ; do + local f=$(xenstore_read_default "$base_path/$dom/$dev/params" "") + f=$(echo "$f" | cut -d ":" -f 2) + + if [ -n "$f" ] && [ "$file" = "$f" ] ; then + if [ "$mode" = 'w' ] ; then + if ! same_vm $dom ; then + echo "guest $f" + return + fi + else + local m=$(xenstore_read_default "$base_path/$dom/$dev/mode" + "") + m=$(canonicalise_mode "$m") + + if [ "$m" = 'w' ] ; then + if ! same_vm $dom ; then + echo "guest $f" + return + fi + fi + fi + fi + done + done + + echo 'ok' +} + +tap_create() +{ + if ! minor=$( tap-ctl allocate ) ; then + fatal "Could not allocate minor" + fi + + # Handle with or without kernel blktap + minor=${minor#/run/blktap-control/tapdisk/tapdisk-} + minor=${minor#/dev/xen/blktap-2/tapdev} + + # tap-ctl is spawning tapdisk which would hold the _lockfd open. + # Ensure it is closed before running tap-ctl spawn, which needs to be + # done in a subshell to continue holding the lock in the parent. + if ! pid=$( ( eval "exec $_lockfd>&-" ; tap-ctl spawn ) ) ; then + tap-ctl free -m "$minor" + fatal "Could not spawn tapdisk for $minor" + fi + + if ! tap-ctl attach -p "$pid" -m "$minor" ; then + tap-ctl free -m "$minor" + fatal "Could not attach $pid and $minor" + fi + + if ! tap-ctl open -p "$pid" -m "$minor" -a "$target" ; then + tap-ctl detach -p "$pid" -m "$minor" + tap-ctl free -m "$minor" + fatal "Could not open \"$target\"" fi } @@ -89,15 +187,54 @@ find_device() # the device add() { - dev=$(tap-ctl create -a $target) - write_dev $dev + local result + + claim_lock "block" + + if find_device; then + result=$( check_tap_sharing "$file" "$mode" ) + if [ "$result" != "ok" ] ; then + do_ebusy "tap $type file $file in use " "$mode" "${result%% *}" + fi + else + tap_create + fi + + # Create nbd unix path. find_device/tap_create set pid & minor + dev=$( printf "/run/blktap-control/nbd%ld.%d" "$pid" "$minor" ) + + xenstore_write "$XENBUS_PATH/pid" "$pid" + xenstore_write "$XENBUS_PATH/minor" "$minor" + # dev, as a unix socket, would end up with major:minor 0:0 in + # physical-device if write_dev were used. tapback would be thrown off by + # that incorrect minor, so just skip writing physical-device. + xenstore_write "$XENBUS_PATH/physical-device-path" "$dev" + + success + + release_lock "block" } # Disconnects the device remove() { - find_device - do_or_die tap-ctl destroy -p ${pid} -m ${minor} > /dev/null + local minor + local pid + + claim_lock "block" + + if tap_shared ; then + return + fi + + minor=$( xenstore_read "$XENBUS_PATH/minor" ) + pid=$( xenstore_read "$XENBUS_PATH/pid" ) + + [ -n "$minor" ] || fatal "minor missing" + [ -n "$pid" ] || fatal "pid missing" + do_or_die tap-ctl destroy -p "$pid" -m "$minor" > /dev/null + + release_lock "block" } command=$1 @@ -110,6 +247,14 @@ parse_target "$target" check_tools || exit 1 +mode=$( xenstore_read $XENBUS_PATH/mode ) +mode=$( canonicalise_mode $mode ) + +# needed for same_vm +FRONTEND_ID=$(xenstore_read "$XENBUS_PATH/frontend-id") +FRONTEND_UUID=$(xenstore_read_default \ + "/local/domain/$FRONTEND_ID/vm" 'unknown') + case $command in add) add -- generated by git-patchbot for /home/xen/git/xen.git#staging
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |