Index: xen-3.4.1-testing/tools/hotplug/Linux/block =================================================================== --- xen-3.4.1-testing.orig/tools/hotplug/Linux/block +++ xen-3.4.1-testing/tools/hotplug/Linux/block @@ -241,107 +241,111 @@ case "$command" in mount it read-write in a guest domain." fi - loopdev='' - for dev in /dev/loop* + losetup_failure=1 + for do_losetup in 1 2 3 do - if [ ! -b "$dev" ] - then - continue - fi - - f=$(losetup "$dev" 2>/dev/null) || f='' - - if [ "$f" ] - then - # $dev is in use. Check sharing. - if [ "x$mode" = 'x!' ] + loopdev='' + for dev in /dev/loop* + do + if [ ! -b "$dev" ] then continue fi - f=$(echo "$f" | sed -e 's/.*(\(.*\)).*/\1/g') + f=$(losetup "$dev" 2>/dev/null) || f='' - # $f is the filename, as read from losetup, but the loopback - # driver truncates filenames at 64 characters, so we need to go - # trawling through the store if it's longer than that. Truncation - # is indicated by an asterisk at the end of the filename. - if expr index "$f" '*' >/dev/null + if [ "$f" ] then - found="" - for dom in $(xenstore-list "$XENBUS_BASE_PATH") - do - for domdev in $(xenstore-list "$XENBUS_BASE_PATH/$dom") + # $dev is in use. Check sharing. + if [ "x$mode" = 'x!' ] + then + continue + fi + + f=$(echo "$f" | sed -e 's/.*(\(.*\)).*/\1/g') + + # $f is the filename, as read from losetup, but the loopback + # driver truncates filenames at 64 characters, so we need to go + # trawling through the store if it's longer than that. Truncation + # is indicated by an asterisk at the end of the filename. + if expr index "$f" '*' >/dev/null + then + found="" + for dom in $(xenstore-list "$XENBUS_BASE_PATH") do - d=$(xenstore_read_default \ - "$XENBUS_BASE_PATH/$dom/$domdev/node" "") - if [ "$d" = "$dev" ] - then - f=$(xenstore_read "$XENBUS_BASE_PATH/$dom/$domdev/params") - found=1 - break 2 - fi + for domdev in $(xenstore-list "$XENBUS_BASE_PATH/$dom") + do + d=$(xenstore_read_default \ + "$XENBUS_BASE_PATH/$dom/$domdev/node" "") + if [ "$d" = "$dev" ] + then + f=$(xenstore_read "$XENBUS_BASE_PATH/$dom/$domdev/params") + found=1 + break 2 + fi + done done - done - if [ ! "$found" ] - then - # This loopback device is in use by someone else, so skip it. - log debug "Loopback sharing check skips device $dev." - continue + if [ ! "$found" ] + then + # This loopback device is in use by someone else, so skip it. + log debug "Loopback sharing check skips device $dev." + continue + fi fi - fi - # Canonicalise the filename for the comparison. + # Canonicalise the filename for the comparison. - # I have seen this readlink fails because the filename given by - # losetup is only the basename. This cannot happen when the loop - # device is set up through this script, because file is - # canonicalised above, but it may happen when loop devices are set - # up some other way. This readlink may also conceivably fail if - # the file backing this loop device has been removed. + # I have seen this readlink fails because the filename given by + # losetup is only the basename. This cannot happen when the loop + # device is set up through this script, because file is + # canonicalised above, but it may happen when loop devices are set + # up some other way. This readlink may also conceivably fail if + # the file backing this loop device has been removed. - # For maximum safety, in the case that $f does not resolve, we - # assume that $file and $f are in the same directory. + # For maximum safety, in the case that $f does not resolve, we + # assume that $file and $f are in the same directory. - # If you create a loopback filesystem, remove it and continue to - # run on it, and then create another file with the same name, then - # this check will block that -- don't do that. + # If you create a loopback filesystem, remove it and continue to + # run on it, and then create another file with the same name, then + # this check will block that -- don't do that. - # If you create loop devices through some other mechanism, use - # relative filenames, and then use the same filename through this - # script, then this check will block that -- don't do that either. + # If you create loop devices through some other mechanism, use + # relative filenames, and then use the same filename through this + # script, then this check will block that -- don't do that either. - f=$(readlink -f "$f" || echo $(dirname "$file")/$(basename "$f")) + f=$(readlink -f "$f" || echo $(dirname "$file")/$(basename "$f")) - if [ "$f" = "$file" ] - then - check_file_sharing "$file" "$dev" "$mode" - fi - else - # $dev is not in use, so we'll remember it for use later; we want - # to finish the sharing check first. + if [ "$f" = "$file" ] + then + check_file_sharing "$file" "$dev" "$mode" + fi + else + # $dev is not in use, so we'll remember it for use later; we want + # to finish the sharing check first. - if [ "$loopdev" = '' ] - then - loopdev="$dev" + if [ "$loopdev" = '' ] + then + loopdev="$dev" + fi fi + done + + if [ "$loopdev" = '' ] + then + release_lock "block" + fatal 'Failed to find an unused loop device' fi + + losetup "$loopdev" "$file" && losetup_failure="" && break done - if [ "$loopdev" = '' ] + if [ "$losetup_failure" ] then - release_lock "block" - fatal 'Failed to find an unused loop device' + fatal 'losetup $loopdev $file' fi - if LANG=C losetup -h 2>&1 | grep read-only >/dev/null - then - roflag="-$mode"; roflag="${roflag#-w}"; roflag="${roflag#-!}" - else - roflag='' - fi - do_or_die losetup $roflag "$loopdev" "$file" xenstore_write "$XENBUS_PATH/node" "$loopdev" write_dev "$loopdev" release_lock "block" @@ -364,8 +368,18 @@ mount it read-write in a guest domain." file) node=$(xenstore_read "$XENBUS_PATH/node") - losetup -d "$node" - exit 0 + + #In case the loopback is temporarily blocked, retry the losetup -d. + for i in 1 2 3 4 5 + do + if losetup -d "$node" + then + exit 0 + fi + sleep 1 + done + log err "losetup -d $node failed." + exit 1 ;; "")