direct-io.hg

changeset 15252:31ee1768e911

xend: Make device detach wait for detach to complete.

*-detach will wait till device is detached or time'ed out.
XendConfig will be updated, if detached.

Signed-off-by: Max Zhen <max.zhen@sun.com>
author kfraser@localhost.localdomain
date Mon Jun 11 10:21:11 2007 +0100 (2007-06-11)
parents 6f06bd06ef47
children ebe4140fe4f8
files tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/DevController.py
line diff
     1.1 --- a/tools/python/xen/xend/XendConfig.py	Mon Jun 11 10:16:54 2007 +0100
     1.2 +++ b/tools/python/xen/xend/XendConfig.py	Mon Jun 11 10:21:11 2007 +0100
     1.3 @@ -1268,6 +1268,21 @@ class XendConfig(dict):
     1.4  
     1.5          return False
     1.6  
     1.7 +    def device_remove(self, dev_uuid):
     1.8 +        """Remove an existing device referred by dev_uuid.
     1.9 +        """
    1.10 +
    1.11 +        if dev_uuid in self['devices']:
    1.12 +            dev_config = self['devices'].get(dev_uuid)
    1.13 +            dev_type = dev_config[0]
    1.14 +
    1.15 +            del self['devices'][dev_uuid]
    1.16 +            # Remove dev references for certain device types (see device_add)
    1.17 +            if dev_type in ('vif', 'vbd', 'vtpm'):
    1.18 +                param = '%s_refs' % dev_type
    1.19 +                if param in self:
    1.20 +                    if dev_uuid in self[param]:
    1.21 +                        self[param].remove(dev_uuid)
    1.22  
    1.23      def device_sxpr(self, dev_uuid = None, dev_type = None, dev_info = None):
    1.24          """Get Device SXPR by either giving the device UUID or (type, config).
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Mon Jun 11 10:16:54 2007 +0100
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Mon Jun 11 10:21:11 2007 +0100
     2.3 @@ -557,7 +557,23 @@ class XendDomainInfo:
     2.4                  return None
     2.5  
     2.6          log.debug("dev = %s", dev)
     2.7 -        return self.getDeviceController(deviceClass).destroyDevice(dev, force)
     2.8 +
     2.9 +        dev_control = self.getDeviceController(deviceClass)
    2.10 +        dev_uuid = dev_control.readBackend(dev, 'uuid')
    2.11 +
    2.12 +        ret = None
    2.13 +
    2.14 +        try:
    2.15 +            ret = dev_control.destroyDevice(dev, force)
    2.16 +        except EnvironmentError:
    2.17 +            # We failed to detach the device
    2.18 +            raise VmError("Failed to detach device %d" % dev)
    2.19 +
    2.20 +        # update XendConfig
    2.21 +        if dev_uuid:
    2.22 +            self.info.device_remove(dev_uuid)
    2.23 +
    2.24 +        return ret
    2.25  
    2.26      def getDeviceSxprs(self, deviceClass):
    2.27          if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
    2.28 @@ -571,7 +587,6 @@ class XendDomainInfo:
    2.29                      dev_num += 1
    2.30              return sxprs
    2.31  
    2.32 -
    2.33      def setMemoryTarget(self, target):
    2.34          """Set the memory target of this domain.
    2.35          @param target: In MiB.
     3.1 --- a/tools/python/xen/xend/server/DevController.py	Mon Jun 11 10:16:54 2007 +0100
     3.2 +++ b/tools/python/xen/xend/server/DevController.py	Mon Jun 11 10:21:11 2007 +0100
     3.3 @@ -29,6 +29,7 @@ from xen.xend.xenstore.xswatch import xs
     3.4  import os
     3.5  
     3.6  DEVICE_CREATE_TIMEOUT = 100
     3.7 +DEVICE_DESTROY_TIMEOUT = 10
     3.8  HOTPLUG_STATUS_NODE = "hotplug-status"
     3.9  HOTPLUG_ERROR_NODE  = "hotplug-error"
    3.10  HOTPLUG_STATUS_ERROR = "error"
    3.11 @@ -211,17 +212,34 @@ class DevController:
    3.12  
    3.13          devid = int(devid)
    3.14  
    3.15 +        frontpath = self.frontendPath(devid)
    3.16 +	if frontpath:
    3.17 +            backpath = xstransact.Read(frontpath, "backend")
    3.18 +
    3.19          # Modify online status /before/ updating state (latter is watched by
    3.20          # drivers, so this ordering avoids a race).
    3.21          self.writeBackend(devid, 'online', "0")
    3.22          self.writeBackend(devid, 'state', str(xenbusState['Closing']))
    3.23  
    3.24          if force:
    3.25 -            frontpath = self.frontendPath(devid)
    3.26 -            backpath = xstransact.Read(frontpath, "backend")
    3.27              if backpath:
    3.28                  xstransact.Remove(backpath)
    3.29 -            xstransact.Remove(frontpath)
    3.30 +	    if frontpath:
    3.31 +                xstransact.Remove(frontpath)
    3.32 +	    return
    3.33 +
    3.34 +	# Wait till both frontpath and backpath are removed from
    3.35 +	# xenstore, or timed out
    3.36 +	if frontpath:
    3.37 +	    status = self.waitUntilDestroyed(frontpath)
    3.38 +	    if status == Timeout:
    3.39 +	        # Exception will be caught by destroyDevice in XendDomainInfo.py
    3.40 +	        raise EnvironmentError
    3.41 +	if backpath:
    3.42 +	    status = self.waitUntilDestroyed(backpath)
    3.43 +	    if status == Timeout:
    3.44 +	        # Exception will be caught by destroyDevice in XendDomainInfo.py
    3.45 +	        raise EnvironmentError
    3.46  
    3.47          self.vm._removeVm("device/%s/%d" % (self.deviceClass, devid))
    3.48  
    3.49 @@ -508,6 +526,16 @@ class DevController:
    3.50              return (Missing, None)
    3.51  
    3.52  
    3.53 +    def waitUntilDestroyed(self, path):
    3.54 +       ev = Event()
    3.55 +       result = { 'path': path, 'status': Timeout }
    3.56 +
    3.57 +       xswatch(path, destroyCallback, ev, result)
    3.58 +
    3.59 +       ev.wait(DEVICE_DESTROY_TIMEOUT)
    3.60 +       return result['status']
    3.61 +
    3.62 +
    3.63      def backendPath(self, backdom, devid):
    3.64          """Construct backend path given the backend domain and device id.
    3.65  
    3.66 @@ -537,6 +565,18 @@ class DevController:
    3.67                                        self.deviceClass)
    3.68  
    3.69  
    3.70 +def destroyCallback(devPath, ev, result):
    3.71 +    log.debug("destroyCallback %s.", devPath)
    3.72 +
    3.73 +    list = xstransact.List(result['path'])
    3.74 +    if list:
    3.75 +        return 1
    3.76 +
    3.77 +    result['status'] = Missing
    3.78 +    ev.set()
    3.79 +    log.debug("destroyCallback %s is destroyed", result['path'])
    3.80 +    return 0
    3.81 +
    3.82  def hotplugStatusCallback(statusPath, ev, result):
    3.83      log.debug("hotplugStatusCallback %s.", statusPath)
    3.84