xen/block-losetup-retry.diff

212 lines
7.9 KiB
Diff
Raw Normal View History

Index: xen-3.2-testing/tools/examples/block
===================================================================
--- xen-3.2-testing.orig/tools/examples/block
+++ xen-3.2-testing/tools/examples/block
@@ -233,107 +233,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"
@@ -356,8 +360,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
;;
"")