mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
xend: Fix for removing devices at save/destroy domain.
The function XendDomainInfo:_releaseDevices() is called during the save/destroy phase of a domain. It made some attempt to clean up the devices, but wasn't complete, leaving dangling devices in the xenstore. Not a big problem with normal use of Xen, but a buildup over a large number of save/destroy instances, it would make the xenstore database grow quite large, which in turn meant swap-thrashing in Dom0. This patch makes use of the destroyDevices() function in XendDomainInfo. This function needed some re-writing to make it work correctly - I think it had some old code (not sure how old, as xm annotate says that it's changeset 12071, but that, I think, is when it was split out from XendDomain.py, rather than when it was created). I have tested this over a few hundred save/restore cycles [two domains constantly saved/restored with a short sleep to let them process some work] combined with a loop of "xenstore-ls|wc". The output of the latter is pretty much constant (it obviously varies a bit depending on when in the save/restore cycle it hits). Previously, it would increase by some 10 lines or so per save/restore cycle. Signed-off-by: Mats Petersson <mats.petersson@amd.com>
This commit is contained in:
1 parent
26e96c98bc
commit
be422ace19
1 file changed
+29
-20
@@ -546,20 +546,30 @@ class XendDomainInfo:
|
||||
self.getDeviceController(devclass).waitForDevices()
|
||||
|
||||
def destroyDevice(self, deviceClass, devid, force = False):
|
||||
found = True # Assume devid is an integer.
|
||||
try:
|
||||
devid = int(devid)
|
||||
except ValueError:
|
||||
# devid is not a number, let's search for it in xenstore.
|
||||
devicePath = '%s/device/%s' % (self.dompath, deviceClass)
|
||||
found = False
|
||||
for entry in xstransact.List(devicePath):
|
||||
log.debug("Attempting to find devid at %s/%s", devicePath, entry)
|
||||
backend = xstransact.Read('%s/%s' % (devicePath, entry),
|
||||
"backend")
|
||||
devName = xstransact.Read(backend, "dev")
|
||||
if devName == devid:
|
||||
# We found the integer matching our devid, use it instead
|
||||
devid = entry
|
||||
break
|
||||
|
||||
if backend != None:
|
||||
devName = '%s/%s' % (deviceClass, entry)
|
||||
log.debug("devName=%s", devName)
|
||||
if devName == devid:
|
||||
# We found the integer matching our devid, use it instead
|
||||
devid = int(entry)
|
||||
found = True
|
||||
break
|
||||
|
||||
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)
|
||||
|
||||
def getDeviceSxprs(self, deviceClass):
|
||||
@@ -1338,20 +1348,19 @@ class XendDomainInfo:
|
||||
self.image.destroy(suspend)
|
||||
return
|
||||
|
||||
while True:
|
||||
t = xstransact("%s/device" % self.dompath)
|
||||
for devclass in XendDevices.valid_devices():
|
||||
for dev in t.list(devclass):
|
||||
try:
|
||||
t.remove(dev)
|
||||
except:
|
||||
# Log and swallow any exceptions in removal --
|
||||
# there's nothing more we can do.
|
||||
log.exception(
|
||||
"Device release failed: %s; %s; %s",
|
||||
self.info['name_label'], devclass, dev)
|
||||
if t.commit():
|
||||
break
|
||||
t = xstransact("%s/device" % self.dompath)
|
||||
for devclass in XendDevices.valid_devices():
|
||||
for dev in t.list(devclass):
|
||||
try:
|
||||
log.debug("Removing %s", dev);
|
||||
self.destroyDevice(devclass, dev, False);
|
||||
except:
|
||||
# Log and swallow any exceptions in removal --
|
||||
# there's nothing more we can do.
|
||||
log.exception("Device release failed: %s; %s; %s",
|
||||
self.info['name_label'], devclass, dev)
|
||||
|
||||
|
||||
|
||||
def getDeviceController(self, name):
|
||||
"""Get the device controller for this domain, and if it
|
||||
|
||||