Index: xen-4.0.2-testing/tools/python/xen/util/blkif.py
===================================================================
--- xen-4.0.2-testing.orig/tools/python/xen/util/blkif.py
+++ xen-4.0.2-testing/tools/python/xen/util/blkif.py
@@ -71,8 +71,8 @@ def blkdev_segment(name):
                 'type'         : 'Disk' }
     return val
 
-def _parse_uname(uname):
-    fn = taptype = None
+def parse_uname(uname):
+    fn = typ = taptype = None
     if uname.find(":") != -1:
         (typ, fn) = uname.split(":", 1)
 
@@ -88,15 +88,18 @@ def _parse_uname(uname):
                
         if typ in ("tap", "tap2"):
             (taptype, fn) = fn.split(":", 1)
-    return (fn, taptype)
+            if taptype in ("tapdisk", "ioemu"):
+                (taptype, fn) = fn.split(":", 1)
+            return (fn, (typ, taptype))
+    return (fn, (typ,taptype))
 
 def blkdev_uname_to_file(uname):
     """Take a blkdev uname and return the corresponding filename."""
-    return _parse_uname(uname)[0]
+    return parse_uname(uname)[0]
 
 def blkdev_uname_to_taptype(uname):
     """Take a blkdev uname and return the blktap type."""
-    return _parse_uname(uname)[1]
+    return parse_uname(uname)[1]
 
 def mount_mode(name):
     mode = None
Index: xen-4.0.2-testing/tools/python/xen/xend/server/DevController.py
===================================================================
--- xen-4.0.2-testing.orig/tools/python/xen/xend/server/DevController.py
+++ xen-4.0.2-testing/tools/python/xen/xend/server/DevController.py
@@ -592,6 +592,31 @@ class DevController:
             return (Missing, None)
 
 
+    def waitForFrontend(self, devid):
+        def frontendStatusCallback(statusPath, ev, result):
+            status = xstransact.Read(statusPath)
+            log.debug("frontendStatusCallback %s = %s" % (statusPath, status))
+            try:
+                status = int(status)
+                if status == xenbusState['Connected']:
+                    result['status'] = Connected
+                elif status == xenbusState['Closed']:
+                    result['status'] = Error
+                else:
+                    raise
+            except:
+                return 1
+            ev.set()
+            return 0
+        frontpath = self.frontendPath(devid)
+        statusPath = frontpath + '/state'
+        ev = Event()
+        result = { 'status': Timeout }
+        xswatch(statusPath, frontendStatusCallback, ev, result)
+        ev.wait(5)
+        return result['status']
+
+
     def backendPath(self, backdom, devid):
         """Construct backend path given the backend domain and device id.
 
Index: xen-4.0.2-testing/tools/python/xen/xend/XendBootloader.py
===================================================================
--- xen-4.0.2-testing.orig/tools/python/xen/xend/XendBootloader.py
+++ xen-4.0.2-testing/tools/python/xen/xend/XendBootloader.py
@@ -12,7 +12,7 @@
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 #
 
-import os, select, errno, stat, signal, tty
+import os, select, errno, stat, signal, tty, time
 import random
 import shlex
 from xen.xend import sxp
@@ -38,8 +38,25 @@ def bootloader(blexec, disk, dom, quiet
         msg = "Bootloader isn't executable"
         log.error(msg)
         raise VmError(msg)
-    if not os.access(disk, os.R_OK):
-        msg = "Disk isn't accessible"
+
+    # domUloader requires '--entry=foo' in blargs, which is derived from
+    # 'bootargs' entry in domain configuration file.  Ensure it exists
+    # here so a reasonable error message can be returned.
+    if blexec.find('domUloader.py') != -1:
+        if blargs.find('entry') == -1:
+            msg = "domUloader requires specification of bootargs"
+            log.error(msg)
+            raise VmError(msg)
+
+    avail = False
+    for i in xrange(1, 100):
+        avail = os.access(disk, os.R_OK)
+        if avail:
+            break
+        time.sleep(.1)
+
+    if not avail:
+        msg = "Disk '%s' isn't accessible" % disk
         log.error(msg)
         raise VmError(msg)
 
Index: xen-4.0.2-testing/tools/python/xen/xend/XendDomainInfo.py
===================================================================
--- xen-4.0.2-testing.orig/tools/python/xen/xend/XendDomainInfo.py
+++ xen-4.0.2-testing/tools/python/xen/xend/XendDomainInfo.py
@@ -37,7 +37,7 @@ from types import StringTypes
 
 import xen.lowlevel.xc
 from xen.util import asserts, auxbin
-from xen.util.blkif import blkdev_uname_to_file, blkdev_uname_to_taptype
+from xen.util.blkif import parse_uname
 import xen.util.xsm.xsm as security
 from xen.util import xsconstants
 from xen.util import mkdir
@@ -2346,6 +2346,10 @@ class XendDomainInfo:
         deviceClass, config = self.info['devices'].get(dev_uuid)
         self._waitForDevice(deviceClass, config['devid'])
 
+    def _waitForDeviceFrontUUID(self, dev_uuid):
+        deviceClass, config = self.info['devices'].get(dev_uuid)
+        self.getDeviceController(deviceClass).waitForFrontend(config['devid'])
+
     def _waitForDevice_destroy(self, deviceClass, devid, backpath):
         return self.getDeviceController(deviceClass).waitForDevice_destroy(
             devid, backpath)
@@ -3234,7 +3238,7 @@ class XendDomainInfo:
             devtype = devinfo[0]
             disk = devinfo[1]['uname']
 
-            fn = blkdev_uname_to_file(disk)
+            (fn, types) = parse_uname(disk)
 
             # If this is a drbd volume, check if we need to activate it
             if disk.find(":") != -1:
@@ -3245,9 +3249,18 @@ class XendDomainInfo:
                     if state == 'Secondary':
                         os.system('/sbin/drbdadm primary ' + diskname)
 
-            taptype = blkdev_uname_to_taptype(disk)
-            mounted = devtype in ['tap', 'tap2'] and taptype != 'aio' and taptype != 'sync' and not os.stat(fn).st_rdev
             mounted_vbd_uuid = 0
+            def _shouldMount(types):
+                if types[0] in ('file', 'phy'):
+                    return False
+                if types[0] in ('tap', 'tap2'):
+                    if types[1] in ('aio', 'sync'):
+                        return False
+                    else:
+                        return True
+                return os.access('/etc/xen/scripts/block-%s' % types[0], os.X_OK)
+
+            mounted = _shouldMount(types)
             if mounted:
                 # This is a file, not a device.  pygrub can cope with a
                 # file if it's raw, but if it's QCOW or other such formats
@@ -3264,7 +3277,7 @@ class XendDomainInfo:
                 from xen.xend import XendDomain
                 dom0 = XendDomain.instance().privilegedDomain()
                 mounted_vbd_uuid = dom0.create_vbd(vbd, disk);
-                dom0._waitForDeviceUUID(mounted_vbd_uuid)
+                dom0._waitForDeviceFrontUUID(mounted_vbd_uuid)
                 fn = BOOTLOADER_LOOPBACK_DEVICE
 
             try:
@@ -3274,9 +3287,10 @@ class XendDomainInfo:
                 if mounted:
                     log.info("Unmounting %s from %s." %
                              (fn, BOOTLOADER_LOOPBACK_DEVICE))
-                    _, vbd_info = dom0.info['devices'][mounted_vbd_uuid]
-                    dom0.destroyDevice(dom0.getBlockDeviceClass(vbd_info['devid']), 
-                                       BOOTLOADER_LOOPBACK_DEVICE, force = True)
+                    if devtype in ['tap', 'tap2']:
+                        dom0.destroyDevice('tap', BOOTLOADER_LOOPBACK_DEVICE, rm_cfg = True)
+                    else:
+                        dom0.destroyDevice('vbd', BOOTLOADER_LOOPBACK_DEVICE, rm_cfg = True)
 
             if blcfg is None:
                 msg = "Had a bootloader specified, but can't find disk"
