john.levon@sun.com
2007-Jun-08 12:22 UTC
[Xen-devel] [PATCH] Make device detach wait for detach to complete
# HG changeset patch # User john.levon@sun.com # 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@sun.com> 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@lists.xensource.com http://lists.xensource.com/xen-devel