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

[Xen-changelog] [xen-unstable] xend: Fix xm pci-attach/detach for inactive managed domains



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1239273314 -3600
# Node ID 72d4c5c83508a21293a52dfe987fcd988e3376d1
# Parent  0b9b6d5a61c1822452fbf370e1e2fa936adf2213
xend: Fix xm pci-attach/detach for inactive managed domains

Signed-off-by: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
---
 tools/python/xen/xend/XendDomainInfo.py |  154 ++++++++++++++++++++++----------
 1 files changed, 106 insertions(+), 48 deletions(-)

diff -r 0b9b6d5a61c1 -r 72d4c5c83508 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Apr 09 09:59:16 2009 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Apr 09 11:35:14 2009 +0100
@@ -685,31 +685,39 @@ class XendDomainInfo:
         # co-assignment devices hasn't been assigned, or has been assigned to
         # domN.
         coassignment_list = pci_device.find_coassigned_devices()
-        assigned_pci_device_str_list = get_assigned_pci_devices(self.domid)
+        assigned_pci_device_str_list = self._get_assigned_pci_devices()
         for pci_str in coassignment_list:
             (domain, bus, dev, func) = parse_pci_name(pci_str) 
             dev_str =  '0x%x,0x%x,0x%x,0x%x' % (domain, bus, dev, func)
             if xc.test_assign_device(0, dev_str) == 0:
                 continue
             if not pci_str in assigned_pci_device_str_list:
-                raise VmError(('pci: failed to pci-attach %s to dom%d" + \
+                raise VmError(("pci: failed to pci-attach %s to domain %s" + \
                     " because one of its co-assignment device %s has been" + \
-                    " assigned to other domain.' \
-                    )% (pci_device.name, self.domid, pci_str))
-
-        opts = ''
-        if 'opts' in new_dev and len(new_dev['opts']) > 0:
-            config_opts = new_dev['opts']
-            config_opts = map(lambda (x, y): x+'='+y, config_opts)
-            opts = ',' + reduce(lambda x, y: x+','+y, config_opts)
-
-        bdf_str = "%s:%s:%s.%s%s@%s" % (new_dev['domain'],
+                    " assigned to other domain." \
+                    )% (pci_device.name, self.info['name_label'], pci_str))
+
+        if self.domid is not None:
+            opts = ''
+            if 'opts' in new_dev and len(new_dev['opts']) > 0:
+                config_opts = new_dev['opts']
+                config_opts = map(lambda (x, y): x+'='+y, config_opts)
+                opts = ',' + reduce(lambda x, y: x+','+y, config_opts)
+
+            bdf_str = "%s:%s:%s.%s%s@%s" % (new_dev['domain'],
                 new_dev['bus'],
                 new_dev['slot'],
                 new_dev['func'],
                 opts,
                 new_dev['vslot'])
-        self.image.signalDeviceModel('pci-ins', 'pci-inserted', bdf_str)
+            self.image.signalDeviceModel('pci-ins', 'pci-inserted', bdf_str)
+
+            vslot = xstransact.Read("/local/domain/0/device-model/%i/parameter"
+                                    % self.getDomid())
+        else:
+            vslot = new_dev['vslot']
+
+        return vslot
 
 
     def device_create(self, dev_config):
@@ -788,10 +796,8 @@ class XendDomainInfo:
         if self.info.is_hvm():
             if pci_state == 'Initialising':
                 # HVM PCI device attachment
-                self.hvm_pci_device_create(dev_config)
+                vslot = self.hvm_pci_device_create(dev_config)
                 # Update vslot
-                vslot = 
xstransact.Read("/local/domain/0/device-model/%i/parameter"
-                                        % self.getDomid())
                 dev['vslot'] = vslot
                 for n in sxp.children(pci_dev):
                     if(n[0] == 'vslot'):
@@ -825,35 +831,66 @@ class XendDomainInfo:
             self.device_create(dev_sxp)
             return True
 
-        # use DevController.reconfigureDevice to change device config
-        dev_control = self.getDeviceController(dev_class)
-        dev_uuid = dev_control.reconfigureDevice(devid, dev_config)
-        if not self.info.is_hvm():
-            # in PV case, wait until backend state becomes connected.
-            dev_control.waitForDevice_reconfigure(devid)
-        num_devs = dev_control.cleanupDevice(devid)
-
-        # update XendConfig with new device info
-        if dev_uuid:
-            new_dev_sxp = dev_control.configuration(devid)
+        if self.domid is not None:
+            # use DevController.reconfigureDevice to change device config
+            dev_control = self.getDeviceController(dev_class)
+            dev_uuid = dev_control.reconfigureDevice(devid, dev_config)
+            if not self.info.is_hvm():
+                # in PV case, wait until backend state becomes connected.
+                dev_control.waitForDevice_reconfigure(devid)
+            num_devs = dev_control.cleanupDevice(devid)
+
+            # update XendConfig with new device info
+            if dev_uuid:
+                new_dev_sxp = dev_control.configuration(devid)
+                self.info.device_update(dev_uuid, new_dev_sxp)
+
+            # If there is no device left, destroy pci and remove config.
+            if num_devs == 0:
+                if self.info.is_hvm():
+                    self.destroyDevice('pci', devid, True)
+                    del self.info['devices'][dev_uuid]
+                    platform = self.info['platform']
+                    orig_dev_num = len(platform['pci'])
+                    # TODO: can use this to keep some info to ask high level
+                    # management tools to hot insert a new passthrough dev
+                    # after migration
+                    if orig_dev_num != 0:
+                        #platform['pci'] = ["%dDEVs" % orig_dev_num]
+                        platform['pci'] = []
+                else:
+                    self.destroyDevice('pci', devid)
+                    del self.info['devices'][dev_uuid]
+        else:
+            new_dev_sxp = ['pci']
+            for cur_dev in sxp.children(existing_dev_info, 'dev'):
+                if pci_state == 'Closing':
+                    if int(dev['domain'], 16) == int(sxp.child_value(cur_dev, 
'domain'), 16) and \
+                       int(dev['bus'], 16) == int(sxp.child_value(cur_dev, 
'bus'), 16) and \
+                       int(dev['slot'], 16) == int(sxp.child_value(cur_dev, 
'slot'), 16) and \
+                       int(dev['func'], 16) == int(sxp.child_value(cur_dev, 
'func'), 16):
+                        continue
+                new_dev_sxp.append(cur_dev)
+
+            if pci_state == 'Initialising':
+                for new_dev in sxp.children(dev_sxp, 'dev'):
+                    new_dev_sxp.append(new_dev)
+
+            dev_uuid = sxp.child_value(existing_dev_info, 'uuid')
             self.info.device_update(dev_uuid, new_dev_sxp)
 
-        # If there is no device left, destroy pci and remove config.
-        if num_devs == 0:
-            if self.info.is_hvm():
-                self.destroyDevice('pci', devid, True)
+            # If there is only 'vscsi' in new_dev_sxp, remove the config.
+            if len(sxp.children(new_dev_sxp, 'dev')) == 0:
                 del self.info['devices'][dev_uuid]
-                platform = self.info['platform']
-                orig_dev_num = len(platform['pci'])
-                # TODO: can use this to keep some info to ask high level
-                # management tools to hot insert a new passthrough dev
-                # after migration
-                if orig_dev_num != 0:
-                    #platform['pci'] = ["%dDEVs" % orig_dev_num]
-                    platform['pci'] = []
-            else:
-                self.destroyDevice('pci', devid)
-                del self.info['devices'][dev_uuid]
+                if self.info.is_hvm():
+                    platform = self.info['platform']
+                    orig_dev_num = len(platform['pci'])
+                    # TODO: can use this to keep some info to ask high level
+                    # management tools to hot insert a new passthrough dev
+                    # after migration
+                    if orig_dev_num != 0:
+                        #platform['pci'] = ["%dDEVs" % orig_dev_num]
+                        platform['pci'] = []
 
         xen.xend.XendDomain.instance().managed_config_save(self)
 
@@ -1054,7 +1091,7 @@ class XendDomainInfo:
             raise VmError("Device @ vslot 0x%x doesn't exist." % (vslot))
 
         if vslot == AUTO_PHP_SLOT:
-            raise VmError("Device @ vslot 0x%x do not support hotplug." % 
(vslot))
+            raise VmError("Device @ vslot 0x%x doesn't support hotplug." % 
(vslot))
 
         # Check the co-assignment.
         # To pci-detach a device D from domN, we should ensure: for each DD in 
the
@@ -1072,19 +1109,20 @@ class XendDomainInfo:
                     "parse it's resources - "+str(e))
         coassignment_list = pci_device.find_coassigned_devices()
         coassignment_list.remove(pci_device.name)
-        assigned_pci_device_str_list = get_assigned_pci_devices(self.domid)
+        assigned_pci_device_str_list = self._get_assigned_pci_devices()
         for pci_str in coassignment_list:
             if pci_str in assigned_pci_device_str_list:
-                raise VmError(('pci: failed to pci-detach %s from dom%d" + \
+                raise VmError(("pci: failed to pci-detach %s from domain %s" + 
\
                     " because one of its co-assignment device %s is still " + \
-                    " assigned to the domain.' \
-                    )% (pci_device.name, self.domid, pci_str))
+                    " assigned to the domain." \
+                    )% (pci_device.name, self.info['name_label'], pci_str))
 
 
         bdf_str = "%s:%s:%s.%s" % (x['domain'], x['bus'], x['slot'], x['func'])
         log.info("hvm_destroyPCIDevice:%s:%s!", x, bdf_str)
 
-        self.image.signalDeviceModel('pci-rem', 'pci-removed', bdf_str)
+        if self.domid is not None:
+            self.image.signalDeviceModel('pci-rem', 'pci-removed', bdf_str)
 
         return 0
 
@@ -1233,6 +1271,26 @@ class XendDomainInfo:
             if devid == int(sxp.child_value(devs[0], 'devid')):
                 return dev_info
         return None
+
+    def _get_assigned_pci_devices(self, devid = 0):
+        if self.domid is not None:
+            return get_assigned_pci_devices(self.domid)
+
+        dev_str_list = []
+        dev_info = self._getDeviceInfo_pci(devid)
+        if dev_info is None:
+            return dev_str_list
+        dev_uuid = sxp.child_value(dev_info, 'uuid')
+        pci_conf = self.info['devices'][dev_uuid][1]
+        pci_devs = pci_conf['devs']
+        for pci_dev in pci_devs:
+            domain = int(pci_dev['domain'], 16)
+            bus = int(pci_dev['bus'], 16)
+            slot = int(pci_dev['slot'], 16)
+            func = int(pci_dev['func'], 16)
+            dev_str = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
+            dev_str_list = dev_str_list + [dev_str]
+        return dev_str_list 
 
     def setMemoryTarget(self, target):
         """Set the memory target of this domain.

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


 


Rackspace

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