Index: xen-3.5.0-testing/tools/hotplug/Linux/block
===================================================================
--- xen-3.5.0-testing.orig/tools/hotplug/Linux/block
+++ xen-3.5.0-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
 	;;
 
       "")