[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