ia64/xen-unstable

changeset 19531:72d4c5c83508

xend: Fix xm pci-attach/detach for inactive managed domains

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Apr 09 11:35:14 2009 +0100 (2009-04-09)
parents 0b9b6d5a61c1
children ec77efc14f2f
files tools/python/xen/xend/XendDomainInfo.py
line diff
     1.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Apr 09 09:59:16 2009 +0100
     1.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Apr 09 11:35:14 2009 +0100
     1.3 @@ -685,31 +685,39 @@ class XendDomainInfo:
     1.4          # co-assignment devices hasn't been assigned, or has been assigned to
     1.5          # domN.
     1.6          coassignment_list = pci_device.find_coassigned_devices()
     1.7 -        assigned_pci_device_str_list = get_assigned_pci_devices(self.domid)
     1.8 +        assigned_pci_device_str_list = self._get_assigned_pci_devices()
     1.9          for pci_str in coassignment_list:
    1.10              (domain, bus, dev, func) = parse_pci_name(pci_str) 
    1.11              dev_str =  '0x%x,0x%x,0x%x,0x%x' % (domain, bus, dev, func)
    1.12              if xc.test_assign_device(0, dev_str) == 0:
    1.13                  continue
    1.14              if not pci_str in assigned_pci_device_str_list:
    1.15 -                raise VmError(('pci: failed to pci-attach %s to dom%d" + \
    1.16 +                raise VmError(("pci: failed to pci-attach %s to domain %s" + \
    1.17                      " because one of its co-assignment device %s has been" + \
    1.18 -                    " assigned to other domain.' \
    1.19 -                    )% (pci_device.name, self.domid, pci_str))
    1.20 -
    1.21 -        opts = ''
    1.22 -        if 'opts' in new_dev and len(new_dev['opts']) > 0:
    1.23 -            config_opts = new_dev['opts']
    1.24 -            config_opts = map(lambda (x, y): x+'='+y, config_opts)
    1.25 -            opts = ',' + reduce(lambda x, y: x+','+y, config_opts)
    1.26 -
    1.27 -        bdf_str = "%s:%s:%s.%s%s@%s" % (new_dev['domain'],
    1.28 +                    " assigned to other domain." \
    1.29 +                    )% (pci_device.name, self.info['name_label'], pci_str))
    1.30 +
    1.31 +        if self.domid is not None:
    1.32 +            opts = ''
    1.33 +            if 'opts' in new_dev and len(new_dev['opts']) > 0:
    1.34 +                config_opts = new_dev['opts']
    1.35 +                config_opts = map(lambda (x, y): x+'='+y, config_opts)
    1.36 +                opts = ',' + reduce(lambda x, y: x+','+y, config_opts)
    1.37 +
    1.38 +            bdf_str = "%s:%s:%s.%s%s@%s" % (new_dev['domain'],
    1.39                  new_dev['bus'],
    1.40                  new_dev['slot'],
    1.41                  new_dev['func'],
    1.42                  opts,
    1.43                  new_dev['vslot'])
    1.44 -        self.image.signalDeviceModel('pci-ins', 'pci-inserted', bdf_str)
    1.45 +            self.image.signalDeviceModel('pci-ins', 'pci-inserted', bdf_str)
    1.46 +
    1.47 +            vslot = xstransact.Read("/local/domain/0/device-model/%i/parameter"
    1.48 +                                    % self.getDomid())
    1.49 +        else:
    1.50 +            vslot = new_dev['vslot']
    1.51 +
    1.52 +        return vslot
    1.53  
    1.54  
    1.55      def device_create(self, dev_config):
    1.56 @@ -788,10 +796,8 @@ class XendDomainInfo:
    1.57          if self.info.is_hvm():
    1.58              if pci_state == 'Initialising':
    1.59                  # HVM PCI device attachment
    1.60 -                self.hvm_pci_device_create(dev_config)
    1.61 +                vslot = self.hvm_pci_device_create(dev_config)
    1.62                  # Update vslot
    1.63 -                vslot = xstransact.Read("/local/domain/0/device-model/%i/parameter"
    1.64 -                                        % self.getDomid())
    1.65                  dev['vslot'] = vslot
    1.66                  for n in sxp.children(pci_dev):
    1.67                      if(n[0] == 'vslot'):
    1.68 @@ -825,35 +831,66 @@ class XendDomainInfo:
    1.69              self.device_create(dev_sxp)
    1.70              return True
    1.71  
    1.72 -        # use DevController.reconfigureDevice to change device config
    1.73 -        dev_control = self.getDeviceController(dev_class)
    1.74 -        dev_uuid = dev_control.reconfigureDevice(devid, dev_config)
    1.75 -        if not self.info.is_hvm():
    1.76 -            # in PV case, wait until backend state becomes connected.
    1.77 -            dev_control.waitForDevice_reconfigure(devid)
    1.78 -        num_devs = dev_control.cleanupDevice(devid)
    1.79 -
    1.80 -        # update XendConfig with new device info
    1.81 -        if dev_uuid:
    1.82 -            new_dev_sxp = dev_control.configuration(devid)
    1.83 +        if self.domid is not None:
    1.84 +            # use DevController.reconfigureDevice to change device config
    1.85 +            dev_control = self.getDeviceController(dev_class)
    1.86 +            dev_uuid = dev_control.reconfigureDevice(devid, dev_config)
    1.87 +            if not self.info.is_hvm():
    1.88 +                # in PV case, wait until backend state becomes connected.
    1.89 +                dev_control.waitForDevice_reconfigure(devid)
    1.90 +            num_devs = dev_control.cleanupDevice(devid)
    1.91 +
    1.92 +            # update XendConfig with new device info
    1.93 +            if dev_uuid:
    1.94 +                new_dev_sxp = dev_control.configuration(devid)
    1.95 +                self.info.device_update(dev_uuid, new_dev_sxp)
    1.96 +
    1.97 +            # If there is no device left, destroy pci and remove config.
    1.98 +            if num_devs == 0:
    1.99 +                if self.info.is_hvm():
   1.100 +                    self.destroyDevice('pci', devid, True)
   1.101 +                    del self.info['devices'][dev_uuid]
   1.102 +                    platform = self.info['platform']
   1.103 +                    orig_dev_num = len(platform['pci'])
   1.104 +                    # TODO: can use this to keep some info to ask high level
   1.105 +                    # management tools to hot insert a new passthrough dev
   1.106 +                    # after migration
   1.107 +                    if orig_dev_num != 0:
   1.108 +                        #platform['pci'] = ["%dDEVs" % orig_dev_num]
   1.109 +                        platform['pci'] = []
   1.110 +                else:
   1.111 +                    self.destroyDevice('pci', devid)
   1.112 +                    del self.info['devices'][dev_uuid]
   1.113 +        else:
   1.114 +            new_dev_sxp = ['pci']
   1.115 +            for cur_dev in sxp.children(existing_dev_info, 'dev'):
   1.116 +                if pci_state == 'Closing':
   1.117 +                    if int(dev['domain'], 16) == int(sxp.child_value(cur_dev, 'domain'), 16) and \
   1.118 +                       int(dev['bus'], 16) == int(sxp.child_value(cur_dev, 'bus'), 16) and \
   1.119 +                       int(dev['slot'], 16) == int(sxp.child_value(cur_dev, 'slot'), 16) and \
   1.120 +                       int(dev['func'], 16) == int(sxp.child_value(cur_dev, 'func'), 16):
   1.121 +                        continue
   1.122 +                new_dev_sxp.append(cur_dev)
   1.123 +
   1.124 +            if pci_state == 'Initialising':
   1.125 +                for new_dev in sxp.children(dev_sxp, 'dev'):
   1.126 +                    new_dev_sxp.append(new_dev)
   1.127 +
   1.128 +            dev_uuid = sxp.child_value(existing_dev_info, 'uuid')
   1.129              self.info.device_update(dev_uuid, new_dev_sxp)
   1.130  
   1.131 -        # If there is no device left, destroy pci and remove config.
   1.132 -        if num_devs == 0:
   1.133 -            if self.info.is_hvm():
   1.134 -                self.destroyDevice('pci', devid, True)
   1.135 +            # If there is only 'vscsi' in new_dev_sxp, remove the config.
   1.136 +            if len(sxp.children(new_dev_sxp, 'dev')) == 0:
   1.137                  del self.info['devices'][dev_uuid]
   1.138 -                platform = self.info['platform']
   1.139 -                orig_dev_num = len(platform['pci'])
   1.140 -                # TODO: can use this to keep some info to ask high level
   1.141 -                # management tools to hot insert a new passthrough dev
   1.142 -                # after migration
   1.143 -                if orig_dev_num != 0:
   1.144 -                    #platform['pci'] = ["%dDEVs" % orig_dev_num]
   1.145 -                    platform['pci'] = []
   1.146 -            else:
   1.147 -                self.destroyDevice('pci', devid)
   1.148 -                del self.info['devices'][dev_uuid]
   1.149 +                if self.info.is_hvm():
   1.150 +                    platform = self.info['platform']
   1.151 +                    orig_dev_num = len(platform['pci'])
   1.152 +                    # TODO: can use this to keep some info to ask high level
   1.153 +                    # management tools to hot insert a new passthrough dev
   1.154 +                    # after migration
   1.155 +                    if orig_dev_num != 0:
   1.156 +                        #platform['pci'] = ["%dDEVs" % orig_dev_num]
   1.157 +                        platform['pci'] = []
   1.158  
   1.159          xen.xend.XendDomain.instance().managed_config_save(self)
   1.160  
   1.161 @@ -1054,7 +1091,7 @@ class XendDomainInfo:
   1.162              raise VmError("Device @ vslot 0x%x doesn't exist." % (vslot))
   1.163  
   1.164          if vslot == AUTO_PHP_SLOT:
   1.165 -            raise VmError("Device @ vslot 0x%x do not support hotplug." % (vslot))
   1.166 +            raise VmError("Device @ vslot 0x%x doesn't support hotplug." % (vslot))
   1.167  
   1.168          # Check the co-assignment.
   1.169          # To pci-detach a device D from domN, we should ensure: for each DD in the
   1.170 @@ -1072,19 +1109,20 @@ class XendDomainInfo:
   1.171                      "parse it's resources - "+str(e))
   1.172          coassignment_list = pci_device.find_coassigned_devices()
   1.173          coassignment_list.remove(pci_device.name)
   1.174 -        assigned_pci_device_str_list = get_assigned_pci_devices(self.domid)
   1.175 +        assigned_pci_device_str_list = self._get_assigned_pci_devices()
   1.176          for pci_str in coassignment_list:
   1.177              if pci_str in assigned_pci_device_str_list:
   1.178 -                raise VmError(('pci: failed to pci-detach %s from dom%d" + \
   1.179 +                raise VmError(("pci: failed to pci-detach %s from domain %s" + \
   1.180                      " because one of its co-assignment device %s is still " + \
   1.181 -                    " assigned to the domain.' \
   1.182 -                    )% (pci_device.name, self.domid, pci_str))
   1.183 +                    " assigned to the domain." \
   1.184 +                    )% (pci_device.name, self.info['name_label'], pci_str))
   1.185  
   1.186  
   1.187          bdf_str = "%s:%s:%s.%s" % (x['domain'], x['bus'], x['slot'], x['func'])
   1.188          log.info("hvm_destroyPCIDevice:%s:%s!", x, bdf_str)
   1.189  
   1.190 -        self.image.signalDeviceModel('pci-rem', 'pci-removed', bdf_str)
   1.191 +        if self.domid is not None:
   1.192 +            self.image.signalDeviceModel('pci-rem', 'pci-removed', bdf_str)
   1.193  
   1.194          return 0
   1.195  
   1.196 @@ -1234,6 +1272,26 @@ class XendDomainInfo:
   1.197                  return dev_info
   1.198          return None
   1.199  
   1.200 +    def _get_assigned_pci_devices(self, devid = 0):
   1.201 +        if self.domid is not None:
   1.202 +            return get_assigned_pci_devices(self.domid)
   1.203 +
   1.204 +        dev_str_list = []
   1.205 +        dev_info = self._getDeviceInfo_pci(devid)
   1.206 +        if dev_info is None:
   1.207 +            return dev_str_list
   1.208 +        dev_uuid = sxp.child_value(dev_info, 'uuid')
   1.209 +        pci_conf = self.info['devices'][dev_uuid][1]
   1.210 +        pci_devs = pci_conf['devs']
   1.211 +        for pci_dev in pci_devs:
   1.212 +            domain = int(pci_dev['domain'], 16)
   1.213 +            bus = int(pci_dev['bus'], 16)
   1.214 +            slot = int(pci_dev['slot'], 16)
   1.215 +            func = int(pci_dev['func'], 16)
   1.216 +            dev_str = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
   1.217 +            dev_str_list = dev_str_list + [dev_str]
   1.218 +        return dev_str_list 
   1.219 +
   1.220      def setMemoryTarget(self, target):
   1.221          """Set the memory target of this domain.
   1.222          @param target: In MiB.