[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] Make device detach wait for detach to complete



# HG changeset patch
# User john.levon@xxxxxxx
# Date 1181305288 25200
# Node ID b6e22518c35a85e708a62ac526daeb18d16f28a2
# Parent  286d8ec9ccf4082b8db0a17a8ab74ad32a2bf218
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@xxxxxxx>

diff --git a/tools/python/xen/xend/XendConfig.py 
b/tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -1274,6 +1274,21 @@ class XendConfig(dict):
 
         return False
 
+    def device_remove(self, dev_uuid):
+        """Remove an existing device referred by dev_uuid.
+        """
+
+        if dev_uuid in self['devices']:
+            dev_config = self['devices'].get(dev_uuid)
+            dev_type = dev_config[0]
+
+            del self['devices'][dev_uuid]
+            # Remove dev references for certain device types (see device_add)
+            if dev_type in ('vif', 'vbd', 'vtpm'):
+                param = '%s_refs' % dev_type
+                if param in self:
+                    if dev_uuid in self[param]:
+                        self[param].remove(dev_uuid)
 
     def device_sxpr(self, dev_uuid = None, dev_type = None, dev_info = None):
         """Get Device SXPR by either giving the device UUID or (type, config).
diff --git a/tools/python/xen/xend/XendDomainInfo.py 
b/tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -569,8 +569,25 @@ class XendDomainInfo:
         if not found:
             log.debug("Could not find the device %s", devid)
             return None
+
         log.debug("devid = %s", devid)
-        return self.getDeviceController(deviceClass).destroyDevice(devid, 
force)
+
+        dev_control = self.getDeviceController(deviceClass)
+        dev_uuid = dev_control.readBackend(devid, 'uuid')
+
+        ret = None
+
+        try:
+            ret = dev_control.destroyDevice(devid, force)
+        except EnvironmentError:
+            # We failed to detach the device
+            raise VmError("Failed to detach device %d" % devid)
+
+        # update XendConfig
+        if dev_uuid:
+            self.info.device_remove(dev_uuid)
+
+        return ret
 
     def getDeviceSxprs(self, deviceClass):
         if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
@@ -583,7 +600,6 @@ class XendDomainInfo:
                     sxprs.append([dev_num, dev_info])
                     dev_num += 1
             return sxprs
-
 
     def setMemoryTarget(self, target):
         """Set the memory target of this domain.
diff --git a/tools/python/xen/xend/server/DevController.py 
b/tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py
+++ b/tools/python/xen/xend/server/DevController.py
@@ -29,6 +29,7 @@ import os
 import os
 
 DEVICE_CREATE_TIMEOUT = 100
+DEVICE_DESTROY_TIMEOUT = 10
 HOTPLUG_STATUS_NODE = "hotplug-status"
 HOTPLUG_ERROR_NODE  = "hotplug-error"
 HOTPLUG_STATUS_ERROR = "error"
@@ -211,17 +212,34 @@ class DevController:
 
         devid = int(devid)
 
+        frontpath = self.frontendPath(devid)
+       if frontpath:
+            backpath = xstransact.Read(frontpath, "backend")
+
         # Modify online status /before/ updating state (latter is watched by
         # drivers, so this ordering avoids a race).
         self.writeBackend(devid, 'online', "0")
         self.writeBackend(devid, 'state', str(xenbusState['Closing']))
 
         if force:
-            frontpath = self.frontendPath(devid)
-            backpath = xstransact.Read(frontpath, "backend")
             if backpath:
                 xstransact.Remove(backpath)
-            xstransact.Remove(frontpath)
+           if frontpath:
+                xstransact.Remove(frontpath)
+           return
+
+       # Wait till both frontpath and backpath are removed from
+       # xenstore, or timed out
+       if frontpath:
+           status = self.waitUntilDestroyed(frontpath)
+           if status == Timeout:
+               # Exception will be caught by destroyDevice in XendDomainInfo.py
+               raise EnvironmentError
+       if backpath:
+           status = self.waitUntilDestroyed(backpath)
+           if status == Timeout:
+               # Exception will be caught by destroyDevice in XendDomainInfo.py
+               raise EnvironmentError
 
         self.vm._removeVm("device/%s/%d" % (self.deviceClass, devid))
 
@@ -508,6 +526,16 @@ class DevController:
             return (Missing, None)
 
 
+    def waitUntilDestroyed(self, path):
+       ev = Event()
+       result = { 'path': path, 'status': Timeout }
+
+       xswatch(path, destroyCallback, ev, result)
+
+       ev.wait(DEVICE_DESTROY_TIMEOUT)
+       return result['status']
+
+
     def backendPath(self, backdom, devid):
         """Construct backend path given the backend domain and device id.
 
@@ -537,6 +565,18 @@ class DevController:
                                       self.deviceClass)
 
 
+def destroyCallback(devPath, ev, result):
+    log.debug("destroyCallback %s.", devPath)
+
+    list = xstransact.List(result['path'])
+    if list:
+        return 1
+
+    result['status'] = Missing
+    ev.set()
+    log.debug("destroyCallback %s is destroyed", result['path'])
+    return 0
+
 def hotplugStatusCallback(statusPath, ev, result):
     log.debug("hotplugStatusCallback %s.", statusPath)
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.