[Kimchi-devel] [PATCH v2] Fix passthrough bugs

Paulo Ricardo Paz Vital pvital at linux.vnet.ibm.com
Fri Oct 23 09:39:48 UTC 2015


Reviewed-By: Paulo Vital <pvital at linux.vnet.ibm.com>

On Thu, 2015-10-22 at 23:02 -0200, Jose Ricardo Ziviani wrote:
>  - when the guest is turned off, a multi function pci device must be
>    attached using mutifunction attribute in the pci address.
> Otherwise
>    the pci won't be attached correctly. Libvirt doesn't support
>    multifunction hotplug, so we don't change anything if the guest is
>    running.
>  - after any recent libvirt update, the device dettachment must be
>    done just before attaching it into the guest because they query
>    /sys to retrieve some device state.
> 
> Signed-off-by: Jose Ricardo Ziviani <joserz at linux.vnet.ibm.com>
> ---
>  src/wok/plugins/kimchi/model/vmhostdevs.py | 63
> ++++++++++++++++++++++++++++--
>  1 file changed, 59 insertions(+), 4 deletions(-)
> 
> diff --git a/src/wok/plugins/kimchi/model/vmhostdevs.py
> b/src/wok/plugins/kimchi/model/vmhostdevs.py
> index 7d13585..c7ce454 100644
> --- a/src/wok/plugins/kimchi/model/vmhostdevs.py
> +++ b/src/wok/plugins/kimchi/model/vmhostdevs.py
> @@ -23,6 +23,7 @@ import os
>  import platform
>  from lxml import etree, objectify
>  from lxml.builder import E
> +from operator import itemgetter
> 
>  from wok.exception import InvalidOperation, InvalidParameter,
> NotFoundError
>  from wok.exception import OperationFailed
> @@ -62,6 +63,9 @@ class VMHostDevsModel(object):
>          self._passthrough_device_validate(dev_name)
>          dev_info = DeviceModel(conn=self.conn).lookup(dev_name)
> 
> +        if dev_info['device_type'] == 'pci':
> +            return self._attach_pci_device(vmid, dev_info)
> +
>          with RollbackContext() as rollback:
>              try:
>                  dev =
> self.conn.get().nodeDeviceLookupByName(dev_name)
> @@ -79,7 +83,7 @@ class VMHostDevsModel(object):
> 
>          return info
> 
> -    def _get_pci_device_xml(self, dev_info):
> +    def _get_pci_device_xml(self, dev_info, slot, is_multifunction):
>          if 'detach_driver' not in dev_info:
>              dev_info['detach_driver'] = 'kvm'
> 
> @@ -88,8 +92,29 @@ class VMHostDevsModel(object):
>                                      slot=str(dev_info['slot']),
>                                     
>  function=str(dev_info['function'])))
>          driver = E.driver(name=dev_info['detach_driver'])
> -        host_dev = E.hostdev(source, driver,
> -                             mode='subsystem', type='pci',
> managed='yes')
> +
> +        if is_multifunction:
> +            multi = E.address(type='pci',
> +                              domain='0',
> +                              bus='0',
> +                              slot=str(slot),
> +                              function=str(dev_info['function']))
> +
> +            if dev_info['function'] == 0:
> +                multi = E.address(type='pci',
> +                                  domain='0',
> +                                  bus='0',
> +                                  slot=str(slot),
> +                                 
>  function=str(dev_info['function']),
> +                                  multifunction='on')
> +
> +
> +            host_dev = E.hostdev(source, driver, multi,
> +                                 mode='subsystem', type='pci',
> managed='yes')
> +
> +        else:
> +            host_dev = E.hostdev(source, driver,
> +                                 mode='subsystem', type='pci',
> managed='yes')
> 
>          return etree.tostring(host_dev)
> 
> @@ -110,6 +135,27 @@ class VMHostDevsModel(object):
>              if rc != 0:
>                  wok_log.warning("Unable to turn on sebool
> virt_use_sysfs")
> 
> +    def _available_slot(self, dom):
> +        xmlstr = dom.XMLDesc(0)
> +        root = objectify.fromstring(xmlstr)
> +        slots = []
> +        try:
> +            devices = root.devices
> +            slots = [DeviceModel._toint(dev.attrib['slot'])
> +                     for dev in devices.findall('.//address')
> +                     if 'slot' in dev.attrib]
> +
> +        except AttributeError:
> +            return 1
> +
> +        slots = sorted(slots)
> +
> +        for free, slot in enumerate(slots, start=1):
> +            if free < slot:
> +                return free
> +
> +        return free+1
> +
>      def _attach_pci_device(self, vmid, dev_info):
>          self._validate_pci_passthrough_env()
> 
> @@ -135,6 +181,10 @@ class VMHostDevsModel(object):
>          pci_infos = [dev_model.lookup(dev_name) for dev_name in
> group_names]
>          pci_infos.append(dev_info)
> 
> +        is_multifunction = len(pci_infos) > 1 and \
> +                DOM_STATE_MAP[dom.info()[0]] == "shutoff"
> +        pci_infos = sorted(pci_infos, key=itemgetter('name'))
> +
>          # all devices in the group that is going to be attached to
> the vm
>          # must be detached from the host first
>          with RollbackContext() as rollback:
> @@ -153,10 +203,15 @@ class VMHostDevsModel(object):
> 
>          device_flags = get_vm_config_flag(dom, mode='all')
> 
> +        slot = 0
> +        if is_multifunction:
> +            slot = self._available_slot(dom)
>          with RollbackContext() as rollback:
>              for pci_info in pci_infos:
>                  pci_info['detach_driver'] = driver
> -                xmlstr = self._get_pci_device_xml(pci_info)
> +                xmlstr = self._get_pci_device_xml(pci_info,
> +                                                  slot,
> +                                                  is_multifunction)
>                  try:
>                      dom.attachDeviceFlags(xmlstr, device_flags)
>                  except libvirt.libvirtError:




More information about the Kimchi-devel mailing list