[libvirt] [PATCH v14 00/49] write separate module for hostdev passthrough

These patches implements a separate module for hostdev passthrough so that it could be shared by different drivers and can maintain a global state of a host device. Patch 1: fix memory leak in virscsi.c Patch 2: improve virHostdevManager to use virOject wrapper and keep reference Patches 3~7: switch existing qemu and lxc driver to use virHostdevManager's lists, so that to maintain a global state of every host device. Patches 8~45 are to extract general code from qemu_hostdev.c piece by piece, make them reusable common APIs. Patches 46: unit test for the virhostdev common library Patches 47: add a hostdev backend type for xen Patches 48: add pci passthrough to libxl driver based on the common library Patches 49: change lxc to use common library APIs --- changes to v13: * change virHostdevManager, use virObject and keep reference, solve 'free' problem * add .hostdevMgr to qemu/lxc/libxl driver, get virHostdevManager in StateInitialize for once and keep reference, instead of getting it every time virHostdevManager is used. * fix v13 3/49 "qemu-reuse-hostdev-interfaces-to-avoid-duplicate.patch": update qemuPrepareHostUSBDevices parameters to specify hostdevs and nhostdevs, so that could be reused in qemu_hotplug. * rebase left patches Chunyan Liu (49): virscsi: fix memory leak virhostdev: use virObject to virHostdevManager to keep reference update qemuPrepareHostUSBDevices parameters to keep consistency qemu: reuse hostdev interfaces to avoid duplicate qemu: remove functions used internally only from qemu_hostdev.h qemu: use general virhostdev lists instead of its own lxc: use general virhostdev lists instead of its own qemu_hostdev: move cfg->relaxedACS as a flag qemu_hostdev: move ColdBoot as a flag qemu_hostdev: move netconfig file location to virhostdev stateDir extract general code from qemuPrepareHostdevPCIDevices rename qemu*NetConfigRestore/Replace to virHostdevNetConfigRestore/Replace rename qemuGet*PciHostDeviceList to virHostdevGet*PciHostDeviceList pass driver name as a parameter to virHostdevPrepareHostdevPCIDevices extract general code from qemuDomainReAttachHostdevDevices pass driver name as a parameter to virHostdevReAttachPCIDevices rename qemuReAttachPciDevice to virHostdevReAttachPciDevice move virHostdevPrepare(ReAttach)PCIDevices to virhostdev.c extract general code from qemuUpdateActivePciHostdevs extract general code from qemuUpdateActiveUsbHostdevs extract general code from qemuUpdateActiveScsiHostdevs pass driver_name as parameter of virHostdevUpdate*Hostdevs functions move virHostdevUpdate* functions to virhostdev.c extract general code from qemuPrepareHostUSBDevices rename qemu*USBDevices to virHostdev*USBDevices pass driver name to virHostdevPrepareUSBDevices move virHostdevPrepareHostUSBDevices to virhostdev.c extract general code from qemuPrepareHostSCSIDevices pass driver name as parameter to virHostdevPrepareSCSIDevices move virHostdevPrepareHostSCSIDevices to virhostdev.c extract general code from qemuDomainReAttachHostUsbDevices pass driver name as paramter to virHostdevReAttachUsbHostdevs move virHostdevReAttachUsbHostdevs to virhostdev.c extract general code from qemuDomainReAttachHostScsiDevices pass driver name as parameter to virHostdevReAttachScciHostdevs move virHostdevReAttachHostScsiDevices to virhostdev.c extract general code of NodeDeviceDetach extract general code of NodeDeviceReAttach extract general code of NodeDeviceReset move virHostdevNodeDevice* to virhostdev.c improve parameter name to let it more meaningful rename some function names to keep consistency improve virHostdevUpdate* parameters to make it more widely used add 3 wrapper functions for prepare/reattach/update domain hostdevs add parameter checks to common interfaces add unit test for new virhostdev common library change lxc_hostdev.c to use virhostdev common library APIs add hostdev pci backend type for xen add pci passthrough to libxl driver .gitignore | 1 + docs/schemas/domaincommon.rng | 1 + src/conf/domain_conf.c | 3 +- src/conf/domain_conf.h | 1 + src/libvirt_private.syms | 15 + src/libxl/libxl_conf.c | 63 ++ src/libxl/libxl_conf.h | 7 +- src/libxl/libxl_domain.c | 9 + src/libxl/libxl_driver.c | 454 +++++++++++- src/lxc/lxc_conf.h | 5 +- src/lxc/lxc_driver.c | 12 +- src/lxc/lxc_hostdev.c | 307 +------- src/qemu/qemu_command.c | 3 +- src/qemu/qemu_conf.h | 9 +- src/qemu/qemu_driver.c | 76 +- src/qemu/qemu_hostdev.c | 1203 ++----------------------------- src/qemu/qemu_hostdev.h | 29 +- src/qemu/qemu_hotplug.c | 78 +- src/qemu/qemu_process.c | 8 +- src/util/virhostdev.c | 1565 ++++++++++++++++++++++++++++++++++++++++- src/util/virhostdev.h | 96 +++ src/util/virscsi.c | 13 +- tests/Makefile.am | 5 + tests/virhostdevtest.c | 507 +++++++++++++ 24 files changed, 2832 insertions(+), 1638 deletions(-) create mode 100644 tests/virhostdevtest.c -- 1.9.0

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virscsi.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/util/virscsi.c b/src/util/virscsi.c index 69eae24..627b3f8 100644 --- a/src/util/virscsi.c +++ b/src/util/virscsi.c @@ -296,12 +296,17 @@ virSCSIDeviceSetUsedBy(virSCSIDevicePtr dev, virUsedByInfoPtr copy; if (VIR_ALLOC(copy) < 0) return -1; - if (VIR_STRDUP(copy->drvname, drvname) < 0) - return -1; - if (VIR_STRDUP(copy->domname, domname) < 0) - return -1; + if (VIR_STRDUP(copy->drvname, drvname) < 0 || + VIR_STRDUP(copy->domname, domname) < 0) + goto cleanup; return VIR_APPEND_ELEMENT(dev->used_by, dev->n_used_by, copy); + +cleanup: + VIR_FREE(copy->drvname); + VIR_FREE(copy->domname); + VIR_FREE(copy); + return -1; } bool -- 1.9.0

On 03/07/2014 05:52 AM, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virscsi.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/util/virscsi.c b/src/util/virscsi.c index 69eae24..627b3f8 100644 --- a/src/util/virscsi.c +++ b/src/util/virscsi.c @@ -296,12 +296,17 @@ virSCSIDeviceSetUsedBy(virSCSIDevicePtr dev, virUsedByInfoPtr copy; if (VIR_ALLOC(copy) < 0) return -1; - if (VIR_STRDUP(copy->drvname, drvname) < 0) - return -1; - if (VIR_STRDUP(copy->domname, domname) < 0) - return -1; + if (VIR_STRDUP(copy->drvname, drvname) < 0 || + VIR_STRDUP(copy->domname, domname) < 0) + goto cleanup;
return VIR_APPEND_ELEMENT(dev->used_by, dev->n_used_by, copy); + +cleanup: + VIR_FREE(copy->drvname); + VIR_FREE(copy->domname); + VIR_FREE(copy); + return -1; }
bool
This should be a separate patch as a result of : http://www.redhat.com/archives/libvir-list/2014-March/msg00282.html I also don't think this is the right way to fix it. See the following for what I think is a more appropriate way: http://www.redhat.com/archives/libvir-list/2014-March/msg00484.html John

On Fri, Mar 07, 2014 at 06:52:28PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virscsi.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
John already pushed an alternative patch, so we can skip this one. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Use virObject to virHostdevManager, so that each driver using virHostdevManager can keep a reference to it, and through counting refs to make virHostdevManager get freed. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virhostdev.c | 54 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index cc8ae78..bb2888f 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -41,11 +41,31 @@ #define VIR_FROM_THIS VIR_FROM_NONE #define HOSTDEV_STATE_DIR LOCALSTATEDIR "/run/libvirt/hostdevmgr" -static virHostdevManagerPtr hostdevMgr; +static virHostdevManagerPtr g_hostdev_mgr; /* global hostdev manager*/ + +static virClassPtr virHostdevManagerClass; +static void virHostdevManagerDispose(void *obj); + +static int virHostdevManagerOnceInit(void) +{ + virHostdevManagerClass = virClassNew(virClassForObject(), + "virHostdevManager", + sizeof(virHostdevManager), + virHostdevManagerDispose); + + if (!virHostdevManagerClass) + return -1; + else + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virHostdevManager) static void -virHostdevManagerCleanup(void) +virHostdevManagerDispose(void *obj) { + virHostdevManagerPtr hostdevMgr = obj; + if (!hostdevMgr) return; @@ -58,11 +78,16 @@ virHostdevManagerCleanup(void) VIR_FREE(hostdevMgr); } -static int -virHostdevOnceInit(void) +static virHostdevManagerPtr +virHostdevManagerNew(void) { - if (VIR_ALLOC(hostdevMgr) < 0) - goto error; + virHostdevManagerPtr hostdevMgr; + + if (virHostdevManagerInitialize() < 0) + return NULL; + + if (!(hostdevMgr = virObjectNew(virHostdevManagerClass))) + return NULL; if ((hostdevMgr->activePciHostdevs = virPCIDeviceListNew()) == NULL) goto error; @@ -86,19 +111,20 @@ virHostdevOnceInit(void) goto error; } - return 0; + return hostdevMgr; error: - virHostdevManagerCleanup(); - return -1; + virObjectUnref(hostdevMgr); + return NULL; } -VIR_ONCE_GLOBAL_INIT(virHostdev) - virHostdevManagerPtr virHostdevManagerGetDefault(void) { - if (virHostdevInitialize() < 0) - return NULL; - return hostdevMgr; + if (g_hostdev_mgr == NULL) { + g_hostdev_mgr = virHostdevManagerNew(); + return g_hostdev_mgr; + } else { + return virObjectRef(g_hostdev_mgr); + } } -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:29PM +0800, Chunyan Liu wrote:
Use virObject to virHostdevManager, so that each driver using virHostdevManager can keep a reference to it, and through counting refs to make virHostdevManager get freed.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virhostdev.c | 54 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 14 deletions(-)
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index cc8ae78..bb2888f 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -41,11 +41,31 @@ #define VIR_FROM_THIS VIR_FROM_NONE #define HOSTDEV_STATE_DIR LOCALSTATEDIR "/run/libvirt/hostdevmgr"
-static virHostdevManagerPtr hostdevMgr; +static virHostdevManagerPtr g_hostdev_mgr; /* global hostdev manager*/ + +static virClassPtr virHostdevManagerClass; +static void virHostdevManagerDispose(void *obj); + +static int virHostdevManagerOnceInit(void) +{ + virHostdevManagerClass = virClassNew(virClassForObject(), + "virHostdevManager", + sizeof(virHostdevManager), + virHostdevManagerDispose); + + if (!virHostdevManagerClass) + return -1; + else + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virHostdevManager)
static void -virHostdevManagerCleanup(void) +virHostdevManagerDispose(void *obj) { + virHostdevManagerPtr hostdevMgr = obj; + if (!hostdevMgr) return;
@@ -58,11 +78,16 @@ virHostdevManagerCleanup(void) VIR_FREE(hostdevMgr); }
-static int -virHostdevOnceInit(void) +static virHostdevManagerPtr +virHostdevManagerNew(void) { - if (VIR_ALLOC(hostdevMgr) < 0) - goto error; + virHostdevManagerPtr hostdevMgr; + + if (virHostdevManagerInitialize() < 0) + return NULL; + + if (!(hostdevMgr = virObjectNew(virHostdevManagerClass))) + return NULL;
if ((hostdevMgr->activePciHostdevs = virPCIDeviceListNew()) == NULL) goto error; @@ -86,19 +111,20 @@ virHostdevOnceInit(void) goto error; }
- return 0; + return hostdevMgr;
error: - virHostdevManagerCleanup(); - return -1; + virObjectUnref(hostdevMgr); + return NULL; }
-VIR_ONCE_GLOBAL_INIT(virHostdev) - virHostdevManagerPtr virHostdevManagerGetDefault(void) { - if (virHostdevInitialize() < 0) - return NULL; - return hostdevMgr; + if (g_hostdev_mgr == NULL) { + g_hostdev_mgr = virHostdevManagerNew(); + return g_hostdev_mgr; + } else { + return virObjectRef(g_hostdev_mgr); + } }
Technically this is not threadsafe, but we only use it during libvirtd daemon initialization so we're ok IMHO. Also if the last reference is removed,the we never clear g_hostdev_mgr - could do that in the dispose method easily enough so I'll fix that. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Update parameters from vm->def to specific name, hostdevs, nhostdevs to keep consistentcy with PreparePCIDevices and PrepareSCSIDevices. And, at the same time, make it reusable in later patch. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index e4f6b1b..47c7f96 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -993,15 +993,15 @@ out: static int qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, - virDomainDefPtr def, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, bool coldBoot) { size_t i; int ret = -1; virUSBDeviceListPtr list; virUSBDevicePtr tmp; - virDomainHostdevDefPtr *hostdevs = def->hostdevs; - int nhostdevs = def->nhostdevs; /* To prevent situation where USB device is assigned to two domains * we need to keep a list of currently assigned USB devices. @@ -1041,7 +1041,7 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, * and add them do driver list. However, if something goes * wrong, perform rollback. */ - if (qemuPrepareHostdevUSBDevices(driver, def->name, list) < 0) + if (qemuPrepareHostdevUSBDevices(driver, name, list) < 0) goto cleanup; /* Loop 2: Temporary list was successfully merged with @@ -1201,7 +1201,8 @@ qemuPrepareHostDevices(virQEMUDriverPtr driver, qemuCaps) < 0) return -1; - if (qemuPrepareHostUSBDevices(driver, def, coldBoot) < 0) + if (qemuPrepareHostUSBDevices(driver, def->name, + def->hostdevs, def->nhostdevs, coldBoot) < 0) return -1; if (qemuPrepareHostdevSCSIDevices(driver, def->name, -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:30PM +0800, Chunyan Liu wrote:
Update parameters from vm->def to specific name, hostdevs, nhostdevs to keep consistentcy with PreparePCIDevices and PrepareSCSIDevices. And, at the same time, make it reusable in later patch.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Same logic of preparing/reattaching hostdevs could be used in attach/detach hotplug places, so reuse hostdev interfaces to avoid duplicate, also for later extracting general code to common library. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 4 ++-- src/qemu/qemu_hostdev.h | 11 +++++++++ src/qemu/qemu_hotplug.c | 63 ++++--------------------------------------------- 3 files changed, 18 insertions(+), 60 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 47c7f96..c4dc9e9 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -991,7 +991,7 @@ out: } -static int +int qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, @@ -1334,7 +1334,7 @@ cleanup: } -static void +void qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h index ffb3167..00c37d0 100644 --- a/src/qemu/qemu_hostdev.h +++ b/src/qemu/qemu_hostdev.h @@ -47,6 +47,12 @@ int qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, const char *name, virUSBDeviceListPtr list); +int +qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + bool coldBoot); int qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, @@ -55,6 +61,11 @@ int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, virQEMUCapsPtr qemuCaps, bool coldBoot); +void +qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs); void qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 6703c92..40b2b4e 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1454,28 +1454,16 @@ qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver, virDomainHostdevDefPtr hostdev) { qemuDomainObjPrivatePtr priv = vm->privateData; - virUSBDeviceList *list = NULL; - virUSBDevicePtr usb = NULL; char *devstr = NULL; bool added = false; bool teardowncgroup = false; bool teardownlabel = false; int ret = -1; - if (qemuFindHostdevUSBDevice(hostdev, true, &usb) < 0) - return -1; - - if (!(list = virUSBDeviceListNew())) - goto cleanup; - - if (virUSBDeviceListAdd(list, usb) < 0) - goto cleanup; - - if (qemuPrepareHostdevUSBDevices(driver, vm->def->name, list) < 0) + if (qemuPrepareHostUSBDevices(driver, vm->def->name, &hostdev, 1, 0) < 0) goto cleanup; added = true; - virUSBDeviceListSteal(list, usb); if (qemuSetupHostdevCGroup(vm, hostdev) < 0) goto cleanup; @@ -1520,13 +1508,8 @@ cleanup: vm->def, hostdev, NULL) < 0) VIR_WARN("Unable to restore host device labelling on hotplug fail"); if (added) - virUSBDeviceListSteal(driver->activeUsbHostdevs, usb); + qemuDomainReAttachHostUsbDevices(driver, vm->def->name, &hostdev, 1); } - if (list && usb && - !virUSBDeviceListFind(list, usb) && - !virUSBDeviceListFind(driver->activeUsbHostdevs, usb)) - virUSBDeviceFree(usb); - virObjectUnref(list); VIR_FREE(devstr); return ret; } @@ -2531,50 +2514,16 @@ qemuDomainRemovePCIHostDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr hostdev) { - virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys; - virPCIDevicePtr pci; - virPCIDevicePtr activePci; - - virObjectLock(driver->activePciHostdevs); - virObjectLock(driver->inactivePciHostdevs); - pci = virPCIDeviceNew(subsys->u.pci.addr.domain, subsys->u.pci.addr.bus, - subsys->u.pci.addr.slot, subsys->u.pci.addr.function); - if (pci) { - activePci = virPCIDeviceListSteal(driver->activePciHostdevs, pci); - if (activePci && - virPCIDeviceReset(activePci, driver->activePciHostdevs, - driver->inactivePciHostdevs) == 0) { - qemuReattachPciDevice(activePci, driver); - } else { - /* reset of the device failed, treat it as if it was returned */ - virPCIDeviceFree(activePci); - } - virPCIDeviceFree(pci); - } - virObjectUnlock(driver->activePciHostdevs); - virObjectUnlock(driver->inactivePciHostdevs); - + qemuDomainReAttachHostdevDevices(driver, vm->def->name, &hostdev, 1); qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL); } static void qemuDomainRemoveUSBHostDevice(virQEMUDriverPtr driver, - virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainObjPtr vm, virDomainHostdevDefPtr hostdev) { - virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys; - virUSBDevicePtr usb; - - usb = virUSBDeviceNew(subsys->u.usb.bus, subsys->u.usb.device, NULL); - if (usb) { - virObjectLock(driver->activeUsbHostdevs); - virUSBDeviceListDel(driver->activeUsbHostdevs, usb); - virObjectUnlock(driver->activeUsbHostdevs); - virUSBDeviceFree(usb); - } else { - VIR_WARN("Unable to find device %03d.%03d in list of used USB devices", - subsys->u.usb.bus, subsys->u.usb.device); - } + qemuDomainReAttachHostUsbDevices(driver, vm->def->name, &hostdev, 1); } static void @@ -2622,8 +2571,6 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, virDomainAuditHostdev(vm, hostdev, "detach", true); - qemuDomainHostdevNetConfigRestore(hostdev, cfg->stateDir); - switch ((enum virDomainHostdevSubsysType) hostdev->source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: qemuDomainRemovePCIHostDevice(driver, vm, hostdev); -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:31PM +0800, Chunyan Liu wrote:
Same logic of preparing/reattaching hostdevs could be used in attach/detach hotplug places, so reuse hostdev interfaces to avoid duplicate, also for later extracting general code to common library.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 4 ++-- src/qemu/qemu_hostdev.h | 11 +++++++++ src/qemu/qemu_hotplug.c | 63 ++++--------------------------------------------- 3 files changed, 18 insertions(+), 60 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 12 ++++++------ src/qemu/qemu_hostdev.h | 13 ------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index c4dc9e9..0814263 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -310,7 +310,7 @@ qemuDomainHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, } -int +static int qemuDomainHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev) { char *sysfs_path = NULL; @@ -396,7 +396,7 @@ qemuDomainHostdevNetConfigVirtPortProfile(const char *linkdev, int vf, } -int +static int qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev, const unsigned char *uuid, char *stateDir) @@ -465,7 +465,7 @@ cleanup: } -int +static int qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, char *stateDir) { @@ -846,7 +846,7 @@ cleanup: } -int +static int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, const char *name, virUSBDeviceListPtr list) @@ -903,7 +903,7 @@ error: } -int +static int qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, bool mandatory, virUSBDevicePtr *usb) @@ -1217,7 +1217,7 @@ qemuPrepareHostDevices(virQEMUDriverPtr driver, * Pre-condition: driver->inactivePciHostdevs & driver->activePciHostdevs * are locked */ -void +static void qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver) { int retries = 100; diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h index 00c37d0..6d5daa7 100644 --- a/src/qemu/qemu_hostdev.h +++ b/src/qemu/qemu_hostdev.h @@ -41,12 +41,6 @@ int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, virDomainHostdevDefPtr *hostdevs, int nhostdevs, virQEMUCapsPtr qemuCaps); -int qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, - bool mandatory, - virUSBDevicePtr *usb); -int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, - const char *name, - virUSBDeviceListPtr list); int qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, const char *name, @@ -70,18 +64,11 @@ void qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs); -void qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver); void qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs); void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def); -int qemuDomainHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev); -int qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev, - const unsigned char *uuid, - char *stateDir); -int qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, - char *stateDir); #endif /* __QEMU_HOSTDEV_H__ */ -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:32PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 12 ++++++------ src/qemu/qemu_hostdev.h | 13 ------------- 2 files changed, 6 insertions(+), 19 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_conf.h | 9 +-- src/qemu/qemu_driver.c | 59 ++++++++----------- src/qemu/qemu_hostdev.c | 151 ++++++++++++++++++++++++++---------------------- 3 files changed, 108 insertions(+), 111 deletions(-) diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index ece185b..c57fd41 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -44,6 +44,7 @@ # include "locking/lock_manager.h" # include "qemu_capabilities.h" # include "virclosecallbacks.h" +# include "virhostdev.h" # ifdef CPU_SETSIZE /* Linux */ # define QEMUD_CPUMASK_LEN CPU_SETSIZE @@ -215,13 +216,7 @@ struct _virQEMUDriver { /* Immutable pointer. self-locking APIs */ virSecurityManagerPtr securityManager; - /* Immutable pointers. Requires locks to be held before - * calling APIs. activePciHostdevs must be locked before - * inactivePciHostdevs */ - virPCIDeviceListPtr activePciHostdevs; - virPCIDeviceListPtr inactivePciHostdevs; - virUSBDeviceListPtr activeUsbHostdevs; - virSCSIDeviceListPtr activeScsiHostdevs; + virHostdevManagerPtr hostdevMgr; /* Immutable pointer. Unsafe APIs. XXX */ virHashTablePtr sharedDevices; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f3a1f58..3d25d14 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -95,6 +95,7 @@ #include "viraccessapicheck.h" #include "viraccessapicheckqemu.h" #include "storage/storage_driver.h" +#include "virhostdev.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -695,16 +696,7 @@ qemuStateInitialize(bool privileged, if (qemuSecurityInit(qemu_driver) < 0) goto error; - if ((qemu_driver->activePciHostdevs = virPCIDeviceListNew()) == NULL) - goto error; - - if ((qemu_driver->activeUsbHostdevs = virUSBDeviceListNew()) == NULL) - goto error; - - if ((qemu_driver->inactivePciHostdevs = virPCIDeviceListNew()) == NULL) - goto error; - - if ((qemu_driver->activeScsiHostdevs = virSCSIDeviceListNew()) == NULL) + if (!(qemu_driver->hostdevMgr = virHostdevManagerGetDefault())) goto error; if (!(qemu_driver->sharedDevices = virHashCreate(30, qemuSharedDeviceEntryFree))) @@ -983,10 +975,7 @@ qemuStateCleanup(void) { virNWFilterUnRegisterCallbackDriver(&qemuCallbackDriver); virObjectUnref(qemu_driver->config); - virObjectUnref(qemu_driver->activePciHostdevs); - virObjectUnref(qemu_driver->inactivePciHostdevs); - virObjectUnref(qemu_driver->activeUsbHostdevs); - virObjectUnref(qemu_driver->activeScsiHostdevs); + virObjectUnref(qemu_driver->hostdevMgr); virHashFree(qemu_driver->sharedDevices); virObjectUnref(qemu_driver->caps); virQEMUCapsCacheFree(qemu_driver->qemuCapsCache); @@ -11290,6 +11279,7 @@ qemuNodeDeviceDetachFlags(virNodeDevicePtr dev, char *xml = NULL; bool legacy = qemuHostdevHostSupportsPassthroughLegacy(); bool vfio = qemuHostdevHostSupportsPassthroughVFIO(); + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; virCheckFlags(0, -1); @@ -11348,18 +11338,18 @@ qemuNodeDeviceDetachFlags(virNodeDevicePtr dev, goto cleanup; } - virObjectLock(driver->activePciHostdevs); - virObjectLock(driver->inactivePciHostdevs); + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); - if (virPCIDeviceDetach(pci, driver->activePciHostdevs, - driver->inactivePciHostdevs) < 0) { + if (virPCIDeviceDetach(pci, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) { goto out; } ret = 0; out: - virObjectUnlock(driver->inactivePciHostdevs); - virObjectUnlock(driver->activePciHostdevs); + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); cleanup: virPCIDeviceFree(pci); virNodeDeviceDefFree(def); @@ -11383,6 +11373,7 @@ qemuNodeDeviceReAttach(virNodeDevicePtr dev) int ret = -1; virNodeDeviceDefPtr def = NULL; char *xml = NULL; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; xml = virNodeDeviceGetXMLDesc(dev, 0); if (!xml) @@ -11402,9 +11393,9 @@ qemuNodeDeviceReAttach(virNodeDevicePtr dev) if (!pci) goto cleanup; - virObjectLock(driver->activePciHostdevs); - virObjectLock(driver->inactivePciHostdevs); - other = virPCIDeviceListFind(driver->activePciHostdevs, pci); + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); + other = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, pci); if (other) { const char *other_drvname = NULL; const char *other_domname = NULL; @@ -11425,14 +11416,14 @@ qemuNodeDeviceReAttach(virNodeDevicePtr dev) virPCIDeviceReattachInit(pci); - if (virPCIDeviceReattach(pci, driver->activePciHostdevs, - driver->inactivePciHostdevs) < 0) + if (virPCIDeviceReattach(pci, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) goto out; ret = 0; out: - virObjectUnlock(driver->inactivePciHostdevs); - virObjectUnlock(driver->activePciHostdevs); + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); virPCIDeviceFree(pci); cleanup: virNodeDeviceDefFree(def); @@ -11449,6 +11440,7 @@ qemuNodeDeviceReset(virNodeDevicePtr dev) int ret = -1; virNodeDeviceDefPtr def = NULL; char *xml = NULL; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; xml = virNodeDeviceGetXMLDesc(dev, 0); if (!xml) @@ -11468,17 +11460,16 @@ qemuNodeDeviceReset(virNodeDevicePtr dev) if (!pci) goto cleanup; - virObjectLock(driver->activePciHostdevs); - virObjectLock(driver->inactivePciHostdevs); - - if (virPCIDeviceReset(pci, driver->activePciHostdevs, - driver->inactivePciHostdevs) < 0) + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); + if (virPCIDeviceReset(pci, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) goto out; ret = 0; out: - virObjectUnlock(driver->inactivePciHostdevs); - virObjectUnlock(driver->activePciHostdevs); + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); virPCIDeviceFree(pci); cleanup: virNodeDeviceDefFree(def); diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 0814263..a4ee611 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -37,6 +37,7 @@ #include "virscsi.h" #include "virnetdev.h" #include "virfile.h" +#include "virhostdev.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -99,10 +100,10 @@ qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs) * * Return the new list, or NULL if there was a failure. * - * Pre-condition: driver->activePciHostdevs is locked + * Pre-condition: activePciHostdevs is locked */ static virPCIDeviceListPtr -qemuGetActivePciHostDeviceList(virQEMUDriverPtr driver, +qemuGetActivePciHostDeviceList(virHostdevManagerPtr mgr, virDomainHostdevDefPtr *hostdevs, int nhostdevs) { @@ -123,7 +124,7 @@ qemuGetActivePciHostDeviceList(virQEMUDriverPtr driver, continue; addr = &hostdev->source.subsys.u.pci.addr; - activeDev = virPCIDeviceListFindByIDs(driver->activePciHostdevs, + activeDev = virPCIDeviceListFindByIDs(mgr->activePciHostdevs, addr->domain, addr->bus, addr->slot, addr->function); if (activeDev && virPCIDeviceListAddCopy(list, activeDev) < 0) { @@ -144,12 +145,13 @@ qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, virPCIDevicePtr dev = NULL; size_t i; int ret = -1; + virHostdevManagerPtr mgr = driver->hostdevMgr; if (!def->nhostdevs) return 0; - virObjectLock(driver->activePciHostdevs); - virObjectLock(driver->inactivePciHostdevs); + virObjectLock(mgr->activePciHostdevs); + virObjectLock(mgr->inactivePciHostdevs); for (i = 0; i < def->nhostdevs; i++) { hostdev = def->hostdevs[i]; @@ -184,7 +186,7 @@ qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, virPCIDeviceSetRemoveSlot(dev, hostdev->origstates.states.pci.remove_slot); virPCIDeviceSetReprobe(dev, hostdev->origstates.states.pci.reprobe); - if (virPCIDeviceListAdd(driver->activePciHostdevs, dev) < 0) + if (virPCIDeviceListAdd(mgr->activePciHostdevs, dev) < 0) goto cleanup; dev = NULL; } @@ -192,12 +194,11 @@ qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, ret = 0; cleanup: virPCIDeviceFree(dev); - virObjectUnlock(driver->activePciHostdevs); - virObjectUnlock(driver->inactivePciHostdevs); + virObjectUnlock(mgr->activePciHostdevs); + virObjectUnlock(mgr->inactivePciHostdevs); return ret; } - int qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, virDomainDefPtr def) @@ -205,11 +206,12 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, virDomainHostdevDefPtr hostdev = NULL; size_t i; int ret = -1; + virHostdevManagerPtr mgr = driver->hostdevMgr; if (!def->nhostdevs) return 0; - virObjectLock(driver->activeUsbHostdevs); + virObjectLock(mgr->activeUsbHostdevs); for (i = 0; i < def->nhostdevs; i++) { virUSBDevicePtr usb = NULL; hostdev = def->hostdevs[i]; @@ -232,14 +234,14 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, virUSBDeviceSetUsedBy(usb, QEMU_DRIVER_NAME, def->name); - if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) { + if (virUSBDeviceListAdd(mgr->activeUsbHostdevs, usb) < 0) { virUSBDeviceFree(usb); goto cleanup; } } ret = 0; cleanup: - virObjectUnlock(driver->activeUsbHostdevs); + virObjectUnlock(mgr->activeUsbHostdevs); return ret; } @@ -252,11 +254,12 @@ qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, int ret = -1; virSCSIDevicePtr scsi = NULL; virSCSIDevicePtr tmp = NULL; + virHostdevManagerPtr mgr = driver->hostdevMgr; if (!def->nhostdevs) return 0; - virObjectLock(driver->activeScsiHostdevs); + virObjectLock(mgr->activeScsiHostdevs); for (i = 0; i < def->nhostdevs; i++) { hostdev = def->hostdevs[i]; @@ -273,7 +276,7 @@ qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, hostdev->shareable))) goto cleanup; - if ((tmp = virSCSIDeviceListFind(driver->activeScsiHostdevs, scsi))) { + if ((tmp = virSCSIDeviceListFind(mgr->activeScsiHostdevs, scsi))) { if (virSCSIDeviceSetUsedBy(tmp, QEMU_DRIVER_NAME, def->name) < 0) { virSCSIDeviceFree(scsi); goto cleanup; @@ -281,7 +284,7 @@ qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, virSCSIDeviceFree(scsi); } else { if (virSCSIDeviceSetUsedBy(scsi, QEMU_DRIVER_NAME, def->name) < 0 || - virSCSIDeviceListAdd(driver->activeScsiHostdevs, scsi) < 0) { + virSCSIDeviceListAdd(mgr->activeScsiHostdevs, scsi) < 0) { virSCSIDeviceFree(scsi); goto cleanup; } @@ -290,7 +293,7 @@ qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, ret = 0; cleanup: - virObjectUnlock(driver->activeScsiHostdevs); + virObjectUnlock(mgr->activeScsiHostdevs); return ret; } @@ -657,12 +660,13 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, size_t i; int ret = -1; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps)) - goto cleanup; + goto out; - virObjectLock(driver->activePciHostdevs); - virObjectLock(driver->inactivePciHostdevs); + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs))) goto cleanup; @@ -690,9 +694,9 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, goto cleanup; } /* The device is in use by other active domain if - * the dev is in list driver->activePciHostdevs. + * the dev is in list activePciHostdevs. */ - if ((other = virPCIDeviceListFind(driver->activePciHostdevs, dev))) { + if ((other = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev))) { const char *other_drvname; const char *other_domname; @@ -715,7 +719,7 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); if (virPCIDeviceGetManaged(dev) && - virPCIDeviceDetach(dev, driver->activePciHostdevs, NULL) < 0) + virPCIDeviceDetach(dev, hostdev_mgr->activePciHostdevs, NULL) < 0) goto reattachdevs; } @@ -724,8 +728,8 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - if (virPCIDeviceReset(dev, driver->activePciHostdevs, - driver->inactivePciHostdevs) < 0) + if (virPCIDeviceReset(dev, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) goto reattachdevs; } @@ -750,24 +754,24 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, /* Loop 5: Now mark all the devices as active */ for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - if (virPCIDeviceListAdd(driver->activePciHostdevs, dev) < 0) + if (virPCIDeviceListAdd(hostdev_mgr->activePciHostdevs, dev) < 0) goto inactivedevs; } /* Loop 6: Now remove the devices from inactive list. */ for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - virPCIDeviceListDel(driver->inactivePciHostdevs, dev); + virPCIDeviceListDel(hostdev_mgr->inactivePciHostdevs, dev); } /* Loop 7: Now set the used_by_domain of the device in - * driver->activePciHostdevs as domain name. + * activePciHostdevs as domain name. */ for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev, activeDev; dev = virPCIDeviceListGet(pcidevs, i); - activeDev = virPCIDeviceListFind(driver->activePciHostdevs, dev); + activeDev = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev); if (activeDev) virPCIDeviceSetUsedBy(activeDev, QEMU_DRIVER_NAME, name); @@ -813,12 +817,12 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, goto cleanup; inactivedevs: - /* Only steal all the devices from driver->activePciHostdevs. We will + /* Only steal all the devices from activePciHostdevs. We will * free them in virObjectUnref(). */ for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - virPCIDeviceListSteal(driver->activePciHostdevs, dev); + virPCIDeviceListSteal(hostdev_mgr->activePciHostdevs, dev); } resetvfnetconfig: @@ -833,21 +837,22 @@ reattachdevs: /* NB: This doesn't actually re-bind to original driver, just * unbinds from the stub driver */ - ignore_value(virPCIDeviceReattach(dev, driver->activePciHostdevs, + ignore_value(virPCIDeviceReattach(dev, hostdev_mgr->activePciHostdevs, NULL)); } cleanup: - virObjectUnlock(driver->activePciHostdevs); - virObjectUnlock(driver->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); virObjectUnref(pcidevs); +out: virObjectUnref(cfg); return ret; } static int -qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, +qemuPrepareHostdevUSBDevices(virHostdevManagerPtr mgr, const char *name, virUSBDeviceListPtr list) { @@ -855,12 +860,12 @@ qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, unsigned int count; virUSBDevicePtr tmp; - virObjectLock(driver->activeUsbHostdevs); + virObjectLock(mgr->activeUsbHostdevs); count = virUSBDeviceListCount(list); for (i = 0; i < count; i++) { virUSBDevicePtr usb = virUSBDeviceListGet(list, i); - if ((tmp = virUSBDeviceListFind(driver->activeUsbHostdevs, usb))) { + if ((tmp = virUSBDeviceListFind(mgr->activeUsbHostdevs, usb))) { const char *other_drvname; const char *other_domname; @@ -886,19 +891,19 @@ qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, * from the virUSBDeviceList that passed in on success, * perform rollback on failure. */ - if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) + if (virUSBDeviceListAdd(mgr->activeUsbHostdevs, usb) < 0) goto error; } - virObjectUnlock(driver->activeUsbHostdevs); + virObjectUnlock(mgr->activeUsbHostdevs); return 0; error: for (j = 0; j < i; j++) { tmp = virUSBDeviceListGet(list, i); - virUSBDeviceListSteal(driver->activeUsbHostdevs, tmp); + virUSBDeviceListSteal(mgr->activeUsbHostdevs, tmp); } - virObjectUnlock(driver->activeUsbHostdevs); + virObjectUnlock(mgr->activeUsbHostdevs); return -1; } @@ -1002,6 +1007,7 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, int ret = -1; virUSBDeviceListPtr list; virUSBDevicePtr tmp; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; /* To prevent situation where USB device is assigned to two domains * we need to keep a list of currently assigned USB devices. @@ -1041,7 +1047,7 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, * and add them do driver list. However, if something goes * wrong, perform rollback. */ - if (qemuPrepareHostdevUSBDevices(driver, name, list) < 0) + if (qemuPrepareHostdevUSBDevices(hostdev_mgr, name, list) < 0) goto cleanup; /* Loop 2: Temporary list was successfully merged with @@ -1071,6 +1077,7 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, int count; virSCSIDeviceListPtr list; virSCSIDevicePtr tmp; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; /* Loop 1: Add the shared scsi host device to shared device * table. @@ -1130,12 +1137,13 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, * and add them to driver list. However, if something goes * wrong, perform rollback. */ - virObjectLock(driver->activeScsiHostdevs); + virObjectLock(hostdev_mgr->activeScsiHostdevs); count = virSCSIDeviceListCount(list); for (i = 0; i < count; i++) { virSCSIDevicePtr scsi = virSCSIDeviceListGet(list, i); - if ((tmp = virSCSIDeviceListFind(driver->activeScsiHostdevs, scsi))) { + if ((tmp = virSCSIDeviceListFind(hostdev_mgr->activeScsiHostdevs, + scsi))) { bool scsi_shareable = virSCSIDeviceGetShareable(scsi); bool tmp_shareable = virSCSIDeviceGetShareable(tmp); @@ -1156,12 +1164,12 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, VIR_DEBUG("Adding %s to activeScsiHostdevs", virSCSIDeviceGetName(scsi)); - if (virSCSIDeviceListAdd(driver->activeScsiHostdevs, scsi) < 0) + if (virSCSIDeviceListAdd(hostdev_mgr->activeScsiHostdevs, scsi) < 0) goto error; } } - virObjectUnlock(driver->activeScsiHostdevs); + virObjectUnlock(hostdev_mgr->activeScsiHostdevs); /* Loop 4: Temporary list was successfully merged with * driver list, so steal all items to avoid freeing them @@ -1178,9 +1186,9 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, error: for (j = 0; j < i; j++) { tmp = virSCSIDeviceListGet(list, i); - virSCSIDeviceListSteal(driver->activeScsiHostdevs, tmp); + virSCSIDeviceListSteal(hostdev_mgr->activeScsiHostdevs, tmp); } - virObjectUnlock(driver->activeScsiHostdevs); + virObjectUnlock(hostdev_mgr->activeScsiHostdevs); cleanup: virObjectUnref(list); return -1; @@ -1214,11 +1222,11 @@ qemuPrepareHostDevices(virQEMUDriverPtr driver, /* - * Pre-condition: driver->inactivePciHostdevs & driver->activePciHostdevs + * Pre-condition: inactivePciHostdevs & activePciHostdevs * are locked */ static void -qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver) +qemuReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) { int retries = 100; @@ -1226,7 +1234,7 @@ qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver) * successfully, it must have been inactive. */ if (!virPCIDeviceGetManaged(dev)) { - if (virPCIDeviceListAdd(driver->inactivePciHostdevs, dev) < 0) + if (virPCIDeviceListAdd(mgr->inactivePciHostdevs, dev) < 0) virPCIDeviceFree(dev); return; } @@ -1237,8 +1245,8 @@ qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver) retries--; } - if (virPCIDeviceReattach(dev, driver->activePciHostdevs, - driver->inactivePciHostdevs) < 0) { + if (virPCIDeviceReattach(dev, mgr->activePciHostdevs, + mgr->inactivePciHostdevs) < 0) { virErrorPtr err = virGetLastError(); VIR_ERROR(_("Failed to re-attach PCI device: %s"), err ? err->message : _("unknown error")); @@ -1257,11 +1265,12 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, virPCIDeviceListPtr pcidevs; size_t i; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - virObjectLock(driver->activePciHostdevs); - virObjectLock(driver->inactivePciHostdevs); + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); - if (!(pcidevs = qemuGetActivePciHostDeviceList(driver, + if (!(pcidevs = qemuGetActivePciHostDeviceList(hostdev_mgr, hostdevs, nhostdevs))) { virErrorPtr err = virGetLastError(); @@ -1283,7 +1292,7 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, * other domain. Or delete it from activePciHostDevs if it had * been used by this domain. */ - activeDev = virPCIDeviceListFind(driver->activePciHostdevs, dev); + activeDev = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev); if (activeDev) { const char *usedby_drvname; const char *usedby_domname; @@ -1295,7 +1304,7 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, } } - virPCIDeviceListDel(driver->activePciHostdevs, dev); + virPCIDeviceListDel(hostdev_mgr->activePciHostdevs, dev); } /* At this point, any device that had been used by the guest is in @@ -1312,8 +1321,8 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - if (virPCIDeviceReset(dev, driver->activePciHostdevs, - driver->inactivePciHostdevs) < 0) { + if (virPCIDeviceReset(dev, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) { virErrorPtr err = virGetLastError(); VIR_ERROR(_("Failed to reset PCI device: %s"), err ? err->message : _("unknown error")); @@ -1323,13 +1332,13 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, while (virPCIDeviceListCount(pcidevs) > 0) { virPCIDevicePtr dev = virPCIDeviceListStealIndex(pcidevs, 0); - qemuReattachPciDevice(dev, driver); + qemuReattachPciDevice(dev, hostdev_mgr); } virObjectUnref(pcidevs); cleanup: - virObjectUnlock(driver->activePciHostdevs); - virObjectUnlock(driver->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); virObjectUnref(cfg); } @@ -1341,8 +1350,9 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, int nhostdevs) { size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - virObjectLock(driver->activeUsbHostdevs); + virObjectLock(hostdev_mgr->activeUsbHostdevs); for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; virUSBDevicePtr usb, tmp; @@ -1374,7 +1384,7 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, * Therefore we want to steal only those devices from * the list which were taken by @name */ - tmp = virUSBDeviceListFind(driver->activeUsbHostdevs, usb); + tmp = virUSBDeviceListFind(hostdev_mgr->activeUsbHostdevs, usb); virUSBDeviceFree(usb); if (!tmp) { @@ -1393,10 +1403,10 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, hostdev->source.subsys.u.usb.device, name); - virUSBDeviceListDel(driver->activeUsbHostdevs, tmp); + virUSBDeviceListDel(hostdev_mgr->activeUsbHostdevs, tmp); } } - virObjectUnlock(driver->activeUsbHostdevs); + virObjectUnlock(hostdev_mgr->activeUsbHostdevs); } @@ -1407,8 +1417,9 @@ qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, int nhostdevs) { size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - virObjectLock(driver->activeScsiHostdevs); + virObjectLock(hostdev_mgr->activeScsiHostdevs); for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; virSCSIDevicePtr scsi; @@ -1443,7 +1454,7 @@ qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, /* Only delete the devices which are marked as being used by @name, * because qemuProcessStart could fail on the half way. */ - if (!(tmp = virSCSIDeviceListFind(driver->activeScsiHostdevs, scsi))) { + if (!(tmp = virSCSIDeviceListFind(hostdev_mgr->activeScsiHostdevs, scsi))) { VIR_WARN("Unable to find device %s:%d:%d:%d " "in list of active SCSI devices", hostdev->source.subsys.u.scsi.adapter, @@ -1461,10 +1472,10 @@ qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, hostdev->source.subsys.u.scsi.unit, name); - virSCSIDeviceListDel(driver->activeScsiHostdevs, tmp, QEMU_DRIVER_NAME, name); + virSCSIDeviceListDel(hostdev_mgr->activeScsiHostdevs, tmp, QEMU_DRIVER_NAME, name); virSCSIDeviceFree(scsi); } - virObjectUnlock(driver->activeScsiHostdevs); + virObjectUnlock(hostdev_mgr->activeScsiHostdevs); } void -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:33PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_conf.h | 9 +-- src/qemu/qemu_driver.c | 59 ++++++++----------- src/qemu/qemu_hostdev.c | 151 ++++++++++++++++++++++++++---------------------- 3 files changed, 108 insertions(+), 111 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/lxc/lxc_conf.h | 5 ++--- src/lxc/lxc_driver.c | 12 +++++++----- src/lxc/lxc_hostdev.c | 32 ++++++++++++++++++-------------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h index e04dcdd..8340b1f 100644 --- a/src/lxc/lxc_conf.h +++ b/src/lxc/lxc_conf.h @@ -37,6 +37,7 @@ # include "virsysinfo.h" # include "virusb.h" # include "virclosecallbacks.h" +# include "virhostdev.h" # define LXC_DRIVER_NAME "LXC" @@ -93,9 +94,7 @@ struct _virLXCDriver { /* Immutable pointer, self-locking APIs */ virDomainObjListPtr domains; - /* Immutable pointer. Requires lock to be held before - * calling APIs. */ - virUSBDeviceListPtr activeUsbHostdevs; + virHostdevManagerPtr hostdevMgr; /* Immutable pointer, self-locking APIs */ virObjectEventStatePtr domainEventState; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 10e0fbb..e1d9ad4 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -71,6 +71,7 @@ #include "virstring.h" #include "viraccessapicheck.h" #include "viraccessapichecklxc.h" +#include "virhostdev.h" #define VIR_FROM_THIS VIR_FROM_LXC @@ -1557,7 +1558,7 @@ static int lxcStateInitialize(bool privileged, if (!(lxc_driver->securityManager = lxcSecurityInit(cfg))) goto cleanup; - if ((lxc_driver->activeUsbHostdevs = virUSBDeviceListNew()) == NULL) + if (!(lxc_driver->hostdevMgr = virHostdevManagerGetDefault())) goto cleanup; if ((virLXCDriverGetCapabilities(lxc_driver, true)) == NULL) @@ -1674,7 +1675,7 @@ static int lxcStateCleanup(void) virSysinfoDefFree(lxc_driver->hostsysinfo); - virObjectUnref(lxc_driver->activeUsbHostdevs); + virObjectUnref(lxc_driver->hostdevMgr); virObjectUnref(lxc_driver->caps); virObjectUnref(lxc_driver->securityManager); virObjectUnref(lxc_driver->xmlopt); @@ -4697,6 +4698,7 @@ lxcDomainDetachDeviceHostdevUSBLive(virLXCDriverPtr driver, int idx, ret = -1; char *dst = NULL; virUSBDevicePtr usb = NULL; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; if ((idx = virDomainHostdevFind(vm->def, dev->data.hostdev, @@ -4733,9 +4735,9 @@ lxcDomainDetachDeviceHostdevUSBLive(virLXCDriverPtr driver, VIR_WARN("cannot deny device %s for domain %s", dst, vm->def->name); - virObjectLock(driver->activeUsbHostdevs); - virUSBDeviceListDel(driver->activeUsbHostdevs, usb); - virObjectUnlock(driver->activeUsbHostdevs); + virObjectLock(hostdev_mgr->activeUsbHostdevs); + virUSBDeviceListDel(hostdev_mgr->activeUsbHostdevs, usb); + virObjectUnlock(hostdev_mgr->activeUsbHostdevs); virDomainHostdevRemove(vm->def, idx); virDomainHostdevDefFree(def); diff --git a/src/lxc/lxc_hostdev.c b/src/lxc/lxc_hostdev.c index b7248df..635f2e5 100644 --- a/src/lxc/lxc_hostdev.c +++ b/src/lxc/lxc_hostdev.c @@ -27,6 +27,7 @@ #include "viralloc.h" #include "virlog.h" #include "virerror.h" +#include "virhostdev.h" #define VIR_FROM_THIS VIR_FROM_LXC @@ -36,6 +37,7 @@ virLXCUpdateActiveUsbHostdevs(virLXCDriverPtr driver, { virDomainHostdevDefPtr hostdev = NULL; size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; if (!def->nhostdevs) return 0; @@ -62,13 +64,13 @@ virLXCUpdateActiveUsbHostdevs(virLXCDriverPtr driver, virUSBDeviceSetUsedBy(usb, LXC_DRIVER_NAME, def->name); - virObjectLock(driver->activeUsbHostdevs); - if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) { - virObjectUnlock(driver->activeUsbHostdevs); + virObjectLock(hostdev_mgr->activeUsbHostdevs); + if (virUSBDeviceListAdd(hostdev_mgr->activeUsbHostdevs, usb) < 0) { + virObjectUnlock(hostdev_mgr->activeUsbHostdevs); virUSBDeviceFree(usb); return -1; } - virObjectUnlock(driver->activeUsbHostdevs); + virObjectUnlock(hostdev_mgr->activeUsbHostdevs); } return 0; @@ -83,13 +85,14 @@ virLXCPrepareHostdevUSBDevices(virLXCDriverPtr driver, size_t i, j; unsigned int count; virUSBDevicePtr tmp; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; count = virUSBDeviceListCount(list); - virObjectLock(driver->activeUsbHostdevs); + virObjectLock(hostdev_mgr->activeUsbHostdevs); for (i = 0; i < count; i++) { virUSBDevicePtr usb = virUSBDeviceListGet(list, i); - if ((tmp = virUSBDeviceListFind(driver->activeUsbHostdevs, usb))) { + if ((tmp = virUSBDeviceListFind(hostdev_mgr->activeUsbHostdevs, usb))) { const char *other_drvname; const char *other_domname; @@ -115,18 +118,18 @@ virLXCPrepareHostdevUSBDevices(virLXCDriverPtr driver, * from the virUSBDeviceList that passed in on success, * perform rollback on failure. */ - if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) + if (virUSBDeviceListAdd(hostdev_mgr->activeUsbHostdevs, usb) < 0) goto error; } - virObjectUnlock(driver->activeUsbHostdevs); + virObjectUnlock(hostdev_mgr->activeUsbHostdevs); return 0; error: for (j = 0; j < i; j++) { tmp = virUSBDeviceListGet(list, i); - virUSBDeviceListSteal(driver->activeUsbHostdevs, tmp); + virUSBDeviceListSteal(hostdev_mgr->activeUsbHostdevs, tmp); } - virObjectUnlock(driver->activeUsbHostdevs); + virObjectUnlock(hostdev_mgr->activeUsbHostdevs); return -1; } @@ -350,8 +353,9 @@ virLXCDomainReAttachHostUsbDevices(virLXCDriverPtr driver, int nhostdevs) { size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - virObjectLock(driver->activeUsbHostdevs); + virObjectLock(hostdev_mgr->activeUsbHostdevs); for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; virUSBDevicePtr usb, tmp; @@ -383,7 +387,7 @@ virLXCDomainReAttachHostUsbDevices(virLXCDriverPtr driver, * Therefore we want to steal only those devices from * the list which were taken by @name */ - tmp = virUSBDeviceListFind(driver->activeUsbHostdevs, usb); + tmp = virUSBDeviceListFind(hostdev_mgr->activeUsbHostdevs, usb); virUSBDeviceFree(usb); if (!tmp) { @@ -402,10 +406,10 @@ virLXCDomainReAttachHostUsbDevices(virLXCDriverPtr driver, hostdev->source.subsys.u.usb.device, name); - virUSBDeviceListDel(driver->activeUsbHostdevs, tmp); + virUSBDeviceListDel(hostdev_mgr->activeUsbHostdevs, tmp); } } - virObjectUnlock(driver->activeUsbHostdevs); + virObjectUnlock(hostdev_mgr->activeUsbHostdevs); } void virLXCDomainReAttachHostDevices(virLXCDriverPtr driver, -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:34PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/lxc/lxc_conf.h | 5 ++--- src/lxc/lxc_driver.c | 12 +++++++----- src/lxc/lxc_hostdev.c | 32 ++++++++++++++++++-------------- 3 files changed, 27 insertions(+), 22 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

For extracting hostdev codes from qemu_hostdev.c to common library, change qemu specific cfg->relaxedACS handling to be a flag, and pass it to hostdev functions. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 11 +++++++---- src/qemu/qemu_hostdev.h | 10 ++++++++-- src/qemu/qemu_hotplug.c | 11 +++++++++-- src/qemu/qemu_process.c | 5 ++++- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index a4ee611..32b5921 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -653,7 +653,8 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, int nhostdevs, - virQEMUCapsPtr qemuCaps) + virQEMUCapsPtr qemuCaps, + unsigned int flags) { virPCIDeviceListPtr pcidevs = NULL; int last_processed_hostdev_vf = -1; @@ -686,8 +687,9 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); virPCIDevicePtr other; + bool strict_acs_check = !!(flags & VIR_HOSTDEV_STRICT_ACS_CHECK); - if (!virPCIDeviceIsAssignable(dev, !cfg->relaxedACS)) { + if (!virPCIDeviceIsAssignable(dev, strict_acs_check)) { virReportError(VIR_ERR_OPERATION_INVALID, _("PCI device %s is not assignable"), virPCIDeviceGetName(dev)); @@ -1199,14 +1201,15 @@ int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, virQEMUCapsPtr qemuCaps, - bool coldBoot) + bool coldBoot, + unsigned int flags) { if (!def->nhostdevs) return 0; if (qemuPrepareHostdevPCIDevices(driver, def->name, def->uuid, def->hostdevs, def->nhostdevs, - qemuCaps) < 0) + qemuCaps, flags) < 0) return -1; if (qemuPrepareHostUSBDevices(driver, def->name, diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h index 6d5daa7..d0ed82f 100644 --- a/src/qemu/qemu_hostdev.h +++ b/src/qemu/qemu_hostdev.h @@ -27,6 +27,10 @@ # include "qemu_conf.h" # include "domain_conf.h" +typedef enum { + VIR_HOSTDEV_STRICT_ACS_CHECK = (1 << 0), /* strict acs check */ +} virHostdevFlag; + int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, virDomainDefPtr def); int qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, @@ -40,7 +44,8 @@ int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, int nhostdevs, - virQEMUCapsPtr qemuCaps); + virQEMUCapsPtr qemuCaps, + unsigned int flags); int qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, const char *name, @@ -54,7 +59,8 @@ int qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, virQEMUCapsPtr qemuCaps, - bool coldBoot); + bool coldBoot, + unsigned int flags); void qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, const char *name, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 40b2b4e..420cb28 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1154,13 +1154,17 @@ qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver, bool teardownlabel = false; int backend; unsigned long long memKB; + virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + unsigned int flags = 0; if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0) return -1; + if (!cfg->relaxedACS) + flags |= VIR_HOSTDEV_STRICT_ACS_CHECK; if (qemuPrepareHostdevPCIDevices(driver, vm->def->name, vm->def->uuid, - &hostdev, 1, priv->qemuCaps) < 0) - return -1; + &hostdev, 1, priv->qemuCaps, flags) < 0) + goto cleanup; /* this could have been changed by qemuPrepareHostdevPCIDevices */ backend = hostdev->source.subsys.u.pci.backend; @@ -1254,6 +1258,7 @@ qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver, VIR_FREE(devstr); VIR_FREE(configfd_name); VIR_FORCE_CLOSE(configfd); + virObjectUnref(cfg); return 0; @@ -1274,6 +1279,8 @@ error: VIR_FREE(configfd_name); VIR_FORCE_CLOSE(configfd); +cleanup: + virObjectUnref(cfg); return -1; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index ffa939a..5e7672f 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3596,6 +3596,7 @@ int qemuProcessStart(virConnectPtr conn, unsigned int stop_flags; virQEMUDriverConfigPtr cfg; virCapsPtr caps = NULL; + unsigned int hostdev_flags = 0; VIR_DEBUG("vm=%p name=%s id=%d pid=%llu", vm, vm->def->name, vm->def->id, @@ -3685,8 +3686,10 @@ int qemuProcessStart(virConnectPtr conn, /* Must be run before security labelling */ VIR_DEBUG("Preparing host devices"); + if (!cfg->relaxedACS) + hostdev_flags |= VIR_HOSTDEV_STRICT_ACS_CHECK; if (qemuPrepareHostDevices(driver, vm->def, priv->qemuCaps, - !migrateFrom) < 0) + !migrateFrom, hostdev_flags) < 0) goto cleanup; VIR_DEBUG("Preparing chr devices"); -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:35PM +0800, Chunyan Liu wrote:
For extracting hostdev codes from qemu_hostdev.c to common library, change qemu specific cfg->relaxedACS handling to be a flag, and pass it to hostdev functions.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 11 +++++++---- src/qemu/qemu_hostdev.h | 10 ++++++++-- src/qemu/qemu_hotplug.c | 11 +++++++++-- src/qemu/qemu_process.c | 5 ++++- 4 files changed, 28 insertions(+), 9 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

For extracting hostdev codes from qemu_hostdev.c to common library, change qemu specific COLD_BOOT handling to be a flag, and pass it to hostdev functions. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 6 +++--- src/qemu/qemu_hostdev.h | 4 ++-- src/qemu/qemu_process.c | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 32b5921..72d84c8 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -1003,13 +1003,14 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs, - bool coldBoot) + unsigned int flags) { size_t i; int ret = -1; virUSBDeviceListPtr list; virUSBDevicePtr tmp; virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + bool coldBoot = !!(flags & VIR_HOSTDEV_COLD_BOOT); /* To prevent situation where USB device is assigned to two domains * we need to keep a list of currently assigned USB devices. @@ -1201,7 +1202,6 @@ int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, virQEMUCapsPtr qemuCaps, - bool coldBoot, unsigned int flags) { if (!def->nhostdevs) @@ -1213,7 +1213,7 @@ qemuPrepareHostDevices(virQEMUDriverPtr driver, return -1; if (qemuPrepareHostUSBDevices(driver, def->name, - def->hostdevs, def->nhostdevs, coldBoot) < 0) + def->hostdevs, def->nhostdevs, flags) < 0) return -1; if (qemuPrepareHostdevSCSIDevices(driver, def->name, diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h index d0ed82f..7c4e95a 100644 --- a/src/qemu/qemu_hostdev.h +++ b/src/qemu/qemu_hostdev.h @@ -29,6 +29,7 @@ typedef enum { VIR_HOSTDEV_STRICT_ACS_CHECK = (1 << 0), /* strict acs check */ + VIR_HOSTDEV_COLD_BOOT = (1 << 1), /* cold boot */ } virHostdevFlag; int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, @@ -51,7 +52,7 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs, - bool coldBoot); + unsigned int flags); int qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, @@ -59,7 +60,6 @@ int qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, virQEMUCapsPtr qemuCaps, - bool coldBoot, unsigned int flags); void qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 5e7672f..7d71e9e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3688,8 +3688,10 @@ int qemuProcessStart(virConnectPtr conn, VIR_DEBUG("Preparing host devices"); if (!cfg->relaxedACS) hostdev_flags |= VIR_HOSTDEV_STRICT_ACS_CHECK; + if (!migrateFrom) + hostdev_flags |= VIR_HOSTDEV_COLD_BOOT; if (qemuPrepareHostDevices(driver, vm->def, priv->qemuCaps, - !migrateFrom, hostdev_flags) < 0) + hostdev_flags) < 0) goto cleanup; VIR_DEBUG("Preparing chr devices"); -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:36PM +0800, Chunyan Liu wrote:
For extracting hostdev codes from qemu_hostdev.c to common library, change qemu specific COLD_BOOT handling to be a flag, and pass it to hostdev functions.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 6 +++--- src/qemu/qemu_hostdev.h | 4 ++-- src/qemu/qemu_process.c | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 72d84c8..a95fbb6 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -467,10 +467,17 @@ cleanup: return ret; } - +/* @oldStateDir: + * For upgrade purpose: + * To an existing VM on QEMU, the hostdev netconfig file is originally stored + * in cfg->stateDir (/var/run/libvirt/qemu). Switch to new version, it uses new + * location (hostdev_mgr->stateDir) but certainly will not find it. In this + * case, try to find in the old state dir. + */ static int qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, - char *stateDir) + char *stateDir, + char *oldStateDir) { char *linkdev = NULL; virNetDevVPortProfilePtr virtPort; @@ -501,12 +508,15 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, virtPort = virDomainNetGetActualVirtPortProfile( hostdev->parent.data.net); - if (virtPort) + if (virtPort) { ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort, &hostdev->parent.data.net->mac, NULL, port_profile_associate); - else + } else { ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir); + if (ret < 0 && oldStateDir != NULL) + ret = virNetDevRestoreNetConfig(linkdev, vf, oldStateDir); + } VIR_FREE(linkdev); @@ -660,7 +670,6 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, int last_processed_hostdev_vf = -1; size_t i; int ret = -1; - virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps)) @@ -746,7 +755,7 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET && hostdev->parent.data.net) { if (qemuDomainHostdevNetConfigReplace(hostdev, uuid, - cfg->stateDir) < 0) { + hostdev_mgr->stateDir) < 0) { goto resetvfnetconfig; } } @@ -830,7 +839,8 @@ inactivedevs: resetvfnetconfig: for (i = 0; last_processed_hostdev_vf != -1 && i < last_processed_hostdev_vf; i++) - qemuDomainHostdevNetConfigRestore(hostdevs[i], cfg->stateDir); + qemuDomainHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, + NULL); reattachdevs: for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { @@ -848,7 +858,6 @@ cleanup: virObjectUnlock(hostdev_mgr->inactivePciHostdevs); virObjectUnref(pcidevs); out: - virObjectUnref(cfg); return ret; } @@ -1268,6 +1277,7 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, virPCIDeviceListPtr pcidevs; size_t i; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + char *oldStateDir = cfg->stateDir; virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; virObjectLock(hostdev_mgr->activePciHostdevs); @@ -1319,7 +1329,8 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, * reset and reattach device */ for (i = 0; i < nhostdevs; i++) - qemuDomainHostdevNetConfigRestore(hostdevs[i], cfg->stateDir); + qemuDomainHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, + oldStateDir); for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:37PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Extract general code from qemuPrepareHostdevPCIDevices to virHostdevPrepareHostdevPCIDevices. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index a95fbb6..5dc68a6 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -656,24 +656,18 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs, return true; } - -int -qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, - const char *name, - const unsigned char *uuid, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - virQEMUCapsPtr qemuCaps, - unsigned int flags) +static int +virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, + const char *name, + const unsigned char *uuid, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + unsigned int flags) { virPCIDeviceListPtr pcidevs = NULL; int last_processed_hostdev_vf = -1; size_t i; int ret = -1; - virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - - if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps)) - goto out; virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); @@ -857,6 +851,26 @@ cleanup: virObjectUnlock(hostdev_mgr->activePciHostdevs); virObjectUnlock(hostdev_mgr->inactivePciHostdevs); virObjectUnref(pcidevs); + return ret; +} + +int +qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, + const char *name, + const unsigned char *uuid, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + virQEMUCapsPtr qemuCaps, + unsigned int flags) +{ + int ret = -1; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps)) + goto out; + + ret = virHostdevPreparePCIDevices(hostdev_mgr, name, uuid, hostdevs, + nhostdevs, flags); out: return ret; } @@ -1024,7 +1038,7 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, /* To prevent situation where USB device is assigned to two domains * we need to keep a list of currently assigned USB devices. * This is done in several loops which cannot be joined into one big - * loop. See qemuPrepareHostdevPCIDevices() + * loop. See virHostdevPreparePCIDevices() */ if (!(list = virUSBDeviceListNew())) goto cleanup; @@ -1110,7 +1124,7 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, /* To prevent situation where SCSI device is assigned to two domains * we need to keep a list of currently assigned SCSI devices. * This is done in several loops which cannot be joined into one big - * loop. See qemuPrepareHostdevPCIDevices() + * loop. See virHostdevPreparePCIDevices() */ if (!(list = virSCSIDeviceListNew())) goto cleanup; -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:38PM +0800, Chunyan Liu wrote:
Extract general code from qemuPrepareHostdevPCIDevices to virHostdevPrepareHostdevPCIDevices.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 64 ++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 5dc68a6..d733fef 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -299,8 +299,8 @@ cleanup: static int -qemuDomainHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, - char **sysfs_path) +virHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, + char **sysfs_path) { virPCIDeviceAddress config_address; @@ -314,12 +314,12 @@ qemuDomainHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, static int -qemuDomainHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev) +virHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev) { char *sysfs_path = NULL; int ret = -1; - if (qemuDomainHostdevPciSysfsPath(hostdev, &sysfs_path) < 0) + if (virHostdevPciSysfsPath(hostdev, &sysfs_path) < 0) return ret; ret = virPCIIsVirtualFunction(sysfs_path); @@ -331,13 +331,13 @@ qemuDomainHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev) static int -qemuDomainHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev, - int *vf) +virHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev, + int *vf) { int ret = -1; char *sysfs_path = NULL; - if (qemuDomainHostdevPciSysfsPath(hostdev, &sysfs_path) < 0) + if (virHostdevPciSysfsPath(hostdev, &sysfs_path) < 0) return ret; if (virPCIIsVirtualFunction(sysfs_path) == 1) { @@ -360,11 +360,11 @@ cleanup: static int -qemuDomainHostdevNetConfigVirtPortProfile(const char *linkdev, int vf, - virNetDevVPortProfilePtr virtPort, - const virMacAddr *macaddr, - const unsigned char *uuid, - bool associate) +virHostdevNetConfigVirtPortProfile(const char *linkdev, int vf, + virNetDevVPortProfilePtr virtPort, + const virMacAddr *macaddr, + const unsigned char *uuid, + bool associate) { int ret = -1; @@ -400,9 +400,9 @@ qemuDomainHostdevNetConfigVirtPortProfile(const char *linkdev, int vf, static int -qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev, - const unsigned char *uuid, - char *stateDir) +virHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev, + const unsigned char *uuid, + char *stateDir) { char *linkdev = NULL; virNetDevVlanPtr vlan; @@ -413,7 +413,7 @@ qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev, bool port_profile_associate = true; int isvf; - isvf = qemuDomainHostdevIsVirtualFunction(hostdev); + isvf = virHostdevIsVirtualFunction(hostdev); if (isvf <= 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Interface type hostdev is currently supported on" @@ -421,7 +421,7 @@ qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev, return ret; } - if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0) + if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0) return ret; vlan = virDomainNetGetActualVlan(hostdev->parent.data.net); @@ -435,7 +435,7 @@ qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev, virNetDevVPortTypeToString(virtPort->virtPortType)); goto cleanup; } - ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, + ret = virHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort, &hostdev->parent.data.net->mac, uuid, port_profile_associate); } else { @@ -475,9 +475,9 @@ cleanup: * case, try to find in the old state dir. */ static int -qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, - char *stateDir, - char *oldStateDir) +virHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, + char *stateDir, + char *oldStateDir) { char *linkdev = NULL; virNetDevVPortProfilePtr virtPort; @@ -495,7 +495,7 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, !hostdev->parent.data.net) return 0; - isvf = qemuDomainHostdevIsVirtualFunction(hostdev); + isvf = virHostdevIsVirtualFunction(hostdev); if (isvf <= 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Interface type hostdev is currently supported on" @@ -503,15 +503,16 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, return ret; } - if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0) + if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0) return ret; virtPort = virDomainNetGetActualVirtPortProfile( hostdev->parent.data.net); if (virtPort) { - ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort, - &hostdev->parent.data.net->mac, NULL, - port_profile_associate); + ret = virHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort, + &hostdev->parent.data.net->mac, + NULL, + port_profile_associate); } else { ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir); if (ret < 0 && oldStateDir != NULL) @@ -748,8 +749,8 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, continue; if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET && hostdev->parent.data.net) { - if (qemuDomainHostdevNetConfigReplace(hostdev, uuid, - hostdev_mgr->stateDir) < 0) { + if (virHostdevNetConfigReplace(hostdev, uuid, + hostdev_mgr->stateDir) < 0) { goto resetvfnetconfig; } } @@ -833,8 +834,7 @@ inactivedevs: resetvfnetconfig: for (i = 0; last_processed_hostdev_vf != -1 && i < last_processed_hostdev_vf; i++) - qemuDomainHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, - NULL); + virHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, NULL); reattachdevs: for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { @@ -1343,8 +1343,8 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, * reset and reattach device */ for (i = 0; i < nhostdevs; i++) - qemuDomainHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, - oldStateDir); + virHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, + oldStateDir); for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:39PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 64 ++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 32 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index d733fef..ec5e0d5 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -42,7 +42,7 @@ #define VIR_FROM_THIS VIR_FROM_QEMU static virPCIDeviceListPtr -qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs) +virHostdevGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs) { virPCIDeviceListPtr list; size_t i; @@ -94,7 +94,7 @@ qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs) /* - * qemuGetActivePciHostDeviceList - make a new list with a *copy* of + * virHostdevGetActivePciHostDeviceList - make a new list with a *copy* of * every virPCIDevice object that is found on the activePciHostdevs * list *and* is in the hostdev list for this domain. * @@ -103,9 +103,9 @@ qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs) * Pre-condition: activePciHostdevs is locked */ static virPCIDeviceListPtr -qemuGetActivePciHostDeviceList(virHostdevManagerPtr mgr, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) +virHostdevGetActivePciHostDeviceList(virHostdevManagerPtr mgr, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) { virPCIDeviceListPtr list; size_t i; @@ -673,7 +673,7 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); - if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs))) + if (!(pcidevs = virHostdevGetPciHostDeviceList(hostdevs, nhostdevs))) goto cleanup; /* We have to use 9 loops here. *All* devices must @@ -1297,9 +1297,9 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); - if (!(pcidevs = qemuGetActivePciHostDeviceList(hostdev_mgr, - hostdevs, - nhostdevs))) { + if (!(pcidevs = virHostdevGetActivePciHostDeviceList(hostdev_mgr, + hostdevs, + nhostdevs))) { virErrorPtr err = virGetLastError(); VIR_ERROR(_("Failed to allocate PCI device list: %s"), err ? err->message : _("unknown error")); -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:40PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index ec5e0d5..7f8f93c 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -659,6 +659,7 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs, static int virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, const char *name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, @@ -780,7 +781,7 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, activeDev = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev); if (activeDev) - virPCIDeviceSetUsedBy(activeDev, QEMU_DRIVER_NAME, name); + virPCIDeviceSetUsedBy(activeDev, drv_name, name); } /* Loop 8: Now set the original states for hostdev def */ @@ -869,7 +870,8 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps)) goto out; - ret = virHostdevPreparePCIDevices(hostdev_mgr, name, uuid, hostdevs, + ret = virHostdevPreparePCIDevices(hostdev_mgr, QEMU_DRIVER_NAME, + name, uuid, hostdevs, nhostdevs, flags); out: return ret; -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:41PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 7f8f93c..e578519 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -1283,18 +1283,18 @@ qemuReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) virPCIDeviceFree(dev); } - -void -qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) +/* @oldStateDir: + * For upgrade purpose: see virHostdevNetConfigRestore + */ +static void +virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + char *oldStateDir) { virPCIDeviceListPtr pcidevs; size_t i; - virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); - char *oldStateDir = cfg->stateDir; - virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); @@ -1369,6 +1369,21 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, cleanup: virObjectUnlock(hostdev_mgr->activePciHostdevs); virObjectUnlock(hostdev_mgr->inactivePciHostdevs); +} + +void +qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + char *oldStateDir = cfg->stateDir; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + virHostdevReAttachPCIDevices(hostdev_mgr, name, + hostdevs, nhostdevs, oldStateDir); + virObjectUnref(cfg); } -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:42PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 7f8f93c..e578519 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -1283,18 +1283,18 @@ qemuReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) virPCIDeviceFree(dev); }
- -void -qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) +/* @oldStateDir: + * For upgrade purpose: see virHostdevNetConfigRestore + */ +static void +virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + char *oldStateDir) { virPCIDeviceListPtr pcidevs; size_t i; - virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); - char *oldStateDir = cfg->stateDir; - virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); @@ -1369,6 +1369,21 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, cleanup: virObjectUnlock(hostdev_mgr->activePciHostdevs); virObjectUnlock(hostdev_mgr->inactivePciHostdevs); +} + +void +qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + char *oldStateDir = cfg->stateDir;
This ought to be 'const' but thats a pre-existing bug :-) ACK I'll fix that. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index e578519..5fa6eb4 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -1288,6 +1288,7 @@ qemuReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) */ static void virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs, @@ -1326,7 +1327,7 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, const char *usedby_drvname; const char *usedby_domname; virPCIDeviceGetUsedBy(activeDev, &usedby_drvname, &usedby_domname); - if (STRNEQ_NULLABLE(QEMU_DRIVER_NAME, usedby_drvname) || + if (STRNEQ_NULLABLE(drv_name, usedby_drvname) || STRNEQ_NULLABLE(name, usedby_domname)) { virPCIDeviceListDel(pcidevs, dev); continue; @@ -1381,7 +1382,7 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, char *oldStateDir = cfg->stateDir; virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - virHostdevReAttachPCIDevices(hostdev_mgr, name, + virHostdevReAttachPCIDevices(hostdev_mgr, QEMU_DRIVER_NAME, name, hostdevs, nhostdevs, oldStateDir); virObjectUnref(cfg); -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:43PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 5fa6eb4..2dfe252 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -1254,10 +1254,8 @@ qemuPrepareHostDevices(virQEMUDriverPtr driver, * are locked */ static void -qemuReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) +virHostdevReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) { - int retries = 100; - /* If the device is not managed and was attached to guest * successfully, it must have been inactive. */ @@ -1267,10 +1265,14 @@ qemuReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) return; } - while (virPCIDeviceWaitForCleanup(dev, "kvm_assigned_device") - && retries) { - usleep(100*1000); - retries--; + /* Wait for device cleanup if it is qemu/kvm */ + if (STREQ(virPCIDeviceGetStubDriver(dev), "pci-stub")) { + int retries = 100; + while (virPCIDeviceWaitForCleanup(dev, "kvm_assigned_device") + && retries) { + usleep(100*1000); + retries--; + } } if (virPCIDeviceReattach(dev, mgr->activePciHostdevs, @@ -1363,7 +1365,7 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, while (virPCIDeviceListCount(pcidevs) > 0) { virPCIDevicePtr dev = virPCIDeviceListStealIndex(pcidevs, 0); - qemuReattachPciDevice(dev, hostdev_mgr); + virHostdevReattachPciDevice(dev, hostdev_mgr); } virObjectUnref(pcidevs); -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:44PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 5fa6eb4..2dfe252 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -1254,10 +1254,8 @@ qemuPrepareHostDevices(virQEMUDriverPtr driver, * are locked */ static void -qemuReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) +virHostdevReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) { - int retries = 100; - /* If the device is not managed and was attached to guest * successfully, it must have been inactive. */ @@ -1267,10 +1265,14 @@ qemuReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) return; }
- while (virPCIDeviceWaitForCleanup(dev, "kvm_assigned_device") - && retries) { - usleep(100*1000); - retries--; + /* Wait for device cleanup if it is qemu/kvm */ + if (STREQ(virPCIDeviceGetStubDriver(dev), "pci-stub")) { + int retries = 100; + while (virPCIDeviceWaitForCleanup(dev, "kvm_assigned_device") + && retries) { + usleep(100*1000); + retries--; + } }
if (virPCIDeviceReattach(dev, mgr->activePciHostdevs,
Looks like this commit is 2 separate patches merged into one. I can easily split this in two though.
@@ -1363,7 +1365,7 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr,
while (virPCIDeviceListCount(pcidevs) > 0) { virPCIDevicePtr dev = virPCIDeviceListStealIndex(pcidevs, 0); - qemuReattachPciDevice(dev, hostdev_mgr); + virHostdevReattachPciDevice(dev, hostdev_mgr); }
virObjectUnref(pcidevs);
ACK when split in two. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 3 +- src/qemu/qemu_hostdev.c | 647 ---------------------------------------------- src/qemu/qemu_hostdev.h | 5 - src/qemu/qemu_process.c | 1 + src/util/virhostdev.c | 648 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 25 ++ 6 files changed, 676 insertions(+), 653 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 80070c5..70085c7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1294,7 +1294,8 @@ virHookPresent; #util/virhostdev.h virHostdevManagerGetDefault; - +virHostdevPreparePCIDevices; +virHostdevReAttachPCIDevices; # util/viridentity.h virIdentityGetAttr; diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 2dfe252..9fe4019 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -41,102 +41,6 @@ #define VIR_FROM_THIS VIR_FROM_QEMU -static virPCIDeviceListPtr -virHostdevGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs) -{ - virPCIDeviceListPtr list; - size_t i; - - if (!(list = virPCIDeviceListNew())) - return NULL; - - for (i = 0; i < nhostdevs; i++) { - virDomainHostdevDefPtr hostdev = hostdevs[i]; - virPCIDevicePtr dev; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - continue; - - dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain, - hostdev->source.subsys.u.pci.addr.bus, - hostdev->source.subsys.u.pci.addr.slot, - hostdev->source.subsys.u.pci.addr.function); - if (!dev) { - virObjectUnref(list); - return NULL; - } - - if (virPCIDeviceListAdd(list, dev) < 0) { - virPCIDeviceFree(dev); - virObjectUnref(list); - return NULL; - } - - virPCIDeviceSetManaged(dev, hostdev->managed); - if (hostdev->source.subsys.u.pci.backend - == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { - if (virPCIDeviceSetStubDriver(dev, "vfio-pci") < 0) { - virObjectUnref(list); - return NULL; - } - } else { - if (virPCIDeviceSetStubDriver(dev, "pci-stub") < 0) { - virObjectUnref(list); - return NULL; - } - } - } - - return list; -} - - -/* - * virHostdevGetActivePciHostDeviceList - make a new list with a *copy* of - * every virPCIDevice object that is found on the activePciHostdevs - * list *and* is in the hostdev list for this domain. - * - * Return the new list, or NULL if there was a failure. - * - * Pre-condition: activePciHostdevs is locked - */ -static virPCIDeviceListPtr -virHostdevGetActivePciHostDeviceList(virHostdevManagerPtr mgr, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) -{ - virPCIDeviceListPtr list; - size_t i; - - if (!(list = virPCIDeviceListNew())) - return NULL; - - for (i = 0; i < nhostdevs; i++) { - virDomainHostdevDefPtr hostdev = hostdevs[i]; - virDevicePCIAddressPtr addr; - virPCIDevicePtr activeDev; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - continue; - - addr = &hostdev->source.subsys.u.pci.addr; - activeDev = virPCIDeviceListFindByIDs(mgr->activePciHostdevs, - addr->domain, addr->bus, - addr->slot, addr->function); - if (activeDev && virPCIDeviceListAddCopy(list, activeDev) < 0) { - virObjectUnref(list); - return NULL; - } - } - - return list; -} - - int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, virDomainDefPtr def) @@ -298,233 +202,6 @@ cleanup: } -static int -virHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, - char **sysfs_path) -{ - virPCIDeviceAddress config_address; - - config_address.domain = hostdev->source.subsys.u.pci.addr.domain; - config_address.bus = hostdev->source.subsys.u.pci.addr.bus; - config_address.slot = hostdev->source.subsys.u.pci.addr.slot; - config_address.function = hostdev->source.subsys.u.pci.addr.function; - - return virPCIDeviceAddressGetSysfsFile(&config_address, sysfs_path); -} - - -static int -virHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev) -{ - char *sysfs_path = NULL; - int ret = -1; - - if (virHostdevPciSysfsPath(hostdev, &sysfs_path) < 0) - return ret; - - ret = virPCIIsVirtualFunction(sysfs_path); - - VIR_FREE(sysfs_path); - - return ret; -} - - -static int -virHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev, - int *vf) -{ - int ret = -1; - char *sysfs_path = NULL; - - if (virHostdevPciSysfsPath(hostdev, &sysfs_path) < 0) - return ret; - - if (virPCIIsVirtualFunction(sysfs_path) == 1) { - if (virPCIGetVirtualFunctionInfo(sysfs_path, linkdev, - vf) < 0) - goto cleanup; - } else { - if (virPCIGetNetName(sysfs_path, linkdev) < 0) - goto cleanup; - *vf = -1; - } - - ret = 0; - -cleanup: - VIR_FREE(sysfs_path); - - return ret; -} - - -static int -virHostdevNetConfigVirtPortProfile(const char *linkdev, int vf, - virNetDevVPortProfilePtr virtPort, - const virMacAddr *macaddr, - const unsigned char *uuid, - bool associate) -{ - int ret = -1; - - if (!virtPort) - return ret; - - switch (virtPort->virtPortType) { - case VIR_NETDEV_VPORT_PROFILE_NONE: - case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH: - case VIR_NETDEV_VPORT_PROFILE_8021QBG: - case VIR_NETDEV_VPORT_PROFILE_LAST: - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("virtualport type %s is " - "currently not supported on interfaces of type " - "hostdev"), - virNetDevVPortTypeToString(virtPort->virtPortType)); - break; - - case VIR_NETDEV_VPORT_PROFILE_8021QBH: - if (associate) - ret = virNetDevVPortProfileAssociate(NULL, virtPort, macaddr, - linkdev, vf, uuid, - VIR_NETDEV_VPORT_PROFILE_OP_CREATE, false); - else - ret = virNetDevVPortProfileDisassociate(NULL, virtPort, - macaddr, linkdev, vf, - VIR_NETDEV_VPORT_PROFILE_OP_DESTROY); - break; - } - - return ret; -} - - -static int -virHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev, - const unsigned char *uuid, - char *stateDir) -{ - char *linkdev = NULL; - virNetDevVlanPtr vlan; - virNetDevVPortProfilePtr virtPort; - int ret = -1; - int vf = -1; - int vlanid = -1; - bool port_profile_associate = true; - int isvf; - - isvf = virHostdevIsVirtualFunction(hostdev); - if (isvf <= 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Interface type hostdev is currently supported on" - " SR-IOV Virtual Functions only")); - return ret; - } - - if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0) - return ret; - - vlan = virDomainNetGetActualVlan(hostdev->parent.data.net); - virtPort = virDomainNetGetActualVirtPortProfile( - hostdev->parent.data.net); - if (virtPort) { - if (vlan) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("direct setting of the vlan tag is not allowed " - "for hostdev devices using %s mode"), - virNetDevVPortTypeToString(virtPort->virtPortType)); - goto cleanup; - } - ret = virHostdevNetConfigVirtPortProfile(linkdev, vf, - virtPort, &hostdev->parent.data.net->mac, uuid, - port_profile_associate); - } else { - /* Set only mac and vlan */ - if (vlan) { - if (vlan->nTags != 1 || vlan->trunk) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("vlan trunking is not supported " - "by SR-IOV network devices")); - goto cleanup; - } - if (vf == -1) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("vlan can only be set for SR-IOV VFs, but " - "%s is not a VF"), linkdev); - goto cleanup; - } - vlanid = vlan->tag[0]; - } else if (vf >= 0) { - vlanid = 0; /* assure any current vlan tag is reset */ - } - - ret = virNetDevReplaceNetConfig(linkdev, vf, - &hostdev->parent.data.net->mac, - vlanid, stateDir); - } -cleanup: - VIR_FREE(linkdev); - return ret; -} - -/* @oldStateDir: - * For upgrade purpose: - * To an existing VM on QEMU, the hostdev netconfig file is originally stored - * in cfg->stateDir (/var/run/libvirt/qemu). Switch to new version, it uses new - * location (hostdev_mgr->stateDir) but certainly will not find it. In this - * case, try to find in the old state dir. - */ -static int -virHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, - char *stateDir, - char *oldStateDir) -{ - char *linkdev = NULL; - virNetDevVPortProfilePtr virtPort; - int ret = -1; - int vf = -1; - bool port_profile_associate = false; - int isvf; - - /* This is only needed for PCI devices that have been defined - * using <interface type='hostdev'>. For all others, it is a NOP. - */ - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || - hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI || - hostdev->parent.type != VIR_DOMAIN_DEVICE_NET || - !hostdev->parent.data.net) - return 0; - - isvf = virHostdevIsVirtualFunction(hostdev); - if (isvf <= 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Interface type hostdev is currently supported on" - " SR-IOV Virtual Functions only")); - return ret; - } - - if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0) - return ret; - - virtPort = virDomainNetGetActualVirtPortProfile( - hostdev->parent.data.net); - if (virtPort) { - ret = virHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort, - &hostdev->parent.data.net->mac, - NULL, - port_profile_associate); - } else { - ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir); - if (ret < 0 && oldStateDir != NULL) - ret = virNetDevRestoreNetConfig(linkdev, vf, oldStateDir); - } - - VIR_FREE(linkdev); - - return ret; -} - - bool qemuHostdevHostSupportsPassthroughVFIO(void) { @@ -657,204 +334,6 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs, return true; } -static int -virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *name, - const unsigned char *uuid, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - unsigned int flags) -{ - virPCIDeviceListPtr pcidevs = NULL; - int last_processed_hostdev_vf = -1; - size_t i; - int ret = -1; - - virObjectLock(hostdev_mgr->activePciHostdevs); - virObjectLock(hostdev_mgr->inactivePciHostdevs); - - if (!(pcidevs = virHostdevGetPciHostDeviceList(hostdevs, nhostdevs))) - goto cleanup; - - /* We have to use 9 loops here. *All* devices must - * be detached before we reset any of them, because - * in some cases you have to reset the whole PCI, - * which impacts all devices on it. Also, all devices - * must be reset before being marked as active. - */ - - /* Loop 1: validate that non-managed device isn't in use, eg - * by checking that device is either un-bound, or bound - * to pci-stub.ko - */ - - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - virPCIDevicePtr other; - bool strict_acs_check = !!(flags & VIR_HOSTDEV_STRICT_ACS_CHECK); - - if (!virPCIDeviceIsAssignable(dev, strict_acs_check)) { - virReportError(VIR_ERR_OPERATION_INVALID, - _("PCI device %s is not assignable"), - virPCIDeviceGetName(dev)); - goto cleanup; - } - /* The device is in use by other active domain if - * the dev is in list activePciHostdevs. - */ - if ((other = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev))) { - const char *other_drvname; - const char *other_domname; - - virPCIDeviceGetUsedBy(other, &other_drvname, &other_domname); - if (other_drvname && other_domname) - virReportError(VIR_ERR_OPERATION_INVALID, - _("PCI device %s is in use by " - "driver %s, domain %s"), - virPCIDeviceGetName(dev), - other_drvname, other_domname); - else - virReportError(VIR_ERR_OPERATION_INVALID, - _("PCI device %s is already in use"), - virPCIDeviceGetName(dev)); - goto cleanup; - } - } - - /* Loop 2: detach managed devices (i.e. bind to appropriate stub driver) */ - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - if (virPCIDeviceGetManaged(dev) && - virPCIDeviceDetach(dev, hostdev_mgr->activePciHostdevs, NULL) < 0) - goto reattachdevs; - } - - /* Loop 3: Now that all the PCI hostdevs have been detached, we - * can safely reset them */ - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - - if (virPCIDeviceReset(dev, hostdev_mgr->activePciHostdevs, - hostdev_mgr->inactivePciHostdevs) < 0) - goto reattachdevs; - } - - /* Loop 4: For SRIOV network devices, Now that we have detached the - * the network device, set the netdev config */ - for (i = 0; i < nhostdevs; i++) { - virDomainHostdevDefPtr hostdev = hostdevs[i]; - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - continue; - if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET && - hostdev->parent.data.net) { - if (virHostdevNetConfigReplace(hostdev, uuid, - hostdev_mgr->stateDir) < 0) { - goto resetvfnetconfig; - } - } - last_processed_hostdev_vf = i; - } - - /* Loop 5: Now mark all the devices as active */ - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - if (virPCIDeviceListAdd(hostdev_mgr->activePciHostdevs, dev) < 0) - goto inactivedevs; - } - - /* Loop 6: Now remove the devices from inactive list. */ - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - virPCIDeviceListDel(hostdev_mgr->inactivePciHostdevs, dev); - } - - /* Loop 7: Now set the used_by_domain of the device in - * activePciHostdevs as domain name. - */ - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev, activeDev; - - dev = virPCIDeviceListGet(pcidevs, i); - activeDev = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev); - - if (activeDev) - virPCIDeviceSetUsedBy(activeDev, drv_name, name); - } - - /* Loop 8: Now set the original states for hostdev def */ - for (i = 0; i < nhostdevs; i++) { - virPCIDevicePtr dev; - virPCIDevicePtr pcidev; - virDomainHostdevDefPtr hostdev = hostdevs[i]; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - continue; - - dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain, - hostdev->source.subsys.u.pci.addr.bus, - hostdev->source.subsys.u.pci.addr.slot, - hostdev->source.subsys.u.pci.addr.function); - - /* original states "unbind_from_stub", "remove_slot", - * "reprobe" were already set by pciDettachDevice in - * loop 2. - */ - if ((pcidev = virPCIDeviceListFind(pcidevs, dev))) { - hostdev->origstates.states.pci.unbind_from_stub = - virPCIDeviceGetUnbindFromStub(pcidev); - hostdev->origstates.states.pci.remove_slot = - virPCIDeviceGetRemoveSlot(pcidev); - hostdev->origstates.states.pci.reprobe = - virPCIDeviceGetReprobe(pcidev); - } - - virPCIDeviceFree(dev); - } - - /* Loop 9: Now steal all the devices from pcidevs */ - while (virPCIDeviceListCount(pcidevs) > 0) - virPCIDeviceListStealIndex(pcidevs, 0); - - ret = 0; - goto cleanup; - -inactivedevs: - /* Only steal all the devices from activePciHostdevs. We will - * free them in virObjectUnref(). - */ - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - virPCIDeviceListSteal(hostdev_mgr->activePciHostdevs, dev); - } - -resetvfnetconfig: - for (i = 0; - last_processed_hostdev_vf != -1 && i < last_processed_hostdev_vf; i++) - virHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, NULL); - -reattachdevs: - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - - /* NB: This doesn't actually re-bind to original driver, just - * unbinds from the stub driver - */ - ignore_value(virPCIDeviceReattach(dev, hostdev_mgr->activePciHostdevs, - NULL)); - } - -cleanup: - virObjectUnlock(hostdev_mgr->activePciHostdevs); - virObjectUnlock(hostdev_mgr->inactivePciHostdevs); - virObjectUnref(pcidevs); - return ret; -} - int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const char *name, @@ -1248,132 +727,6 @@ qemuPrepareHostDevices(virQEMUDriverPtr driver, return 0; } - -/* - * Pre-condition: inactivePciHostdevs & activePciHostdevs - * are locked - */ -static void -virHostdevReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) -{ - /* If the device is not managed and was attached to guest - * successfully, it must have been inactive. - */ - if (!virPCIDeviceGetManaged(dev)) { - if (virPCIDeviceListAdd(mgr->inactivePciHostdevs, dev) < 0) - virPCIDeviceFree(dev); - return; - } - - /* Wait for device cleanup if it is qemu/kvm */ - if (STREQ(virPCIDeviceGetStubDriver(dev), "pci-stub")) { - int retries = 100; - while (virPCIDeviceWaitForCleanup(dev, "kvm_assigned_device") - && retries) { - usleep(100*1000); - retries--; - } - } - - if (virPCIDeviceReattach(dev, mgr->activePciHostdevs, - mgr->inactivePciHostdevs) < 0) { - virErrorPtr err = virGetLastError(); - VIR_ERROR(_("Failed to re-attach PCI device: %s"), - err ? err->message : _("unknown error")); - virResetError(err); - } - virPCIDeviceFree(dev); -} - -/* @oldStateDir: - * For upgrade purpose: see virHostdevNetConfigRestore - */ -static void -virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - char *oldStateDir) -{ - virPCIDeviceListPtr pcidevs; - size_t i; - - virObjectLock(hostdev_mgr->activePciHostdevs); - virObjectLock(hostdev_mgr->inactivePciHostdevs); - - if (!(pcidevs = virHostdevGetActivePciHostDeviceList(hostdev_mgr, - hostdevs, - nhostdevs))) { - virErrorPtr err = virGetLastError(); - VIR_ERROR(_("Failed to allocate PCI device list: %s"), - err ? err->message : _("unknown error")); - virResetError(err); - goto cleanup; - } - - /* Again 4 loops; mark all devices as inactive before reset - * them and reset all the devices before re-attach. - * Attach mac and port profile parameters to devices - */ - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - virPCIDevicePtr activeDev = NULL; - - /* delete the copy of the dev from pcidevs if it's used by - * other domain. Or delete it from activePciHostDevs if it had - * been used by this domain. - */ - activeDev = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev); - if (activeDev) { - const char *usedby_drvname; - const char *usedby_domname; - virPCIDeviceGetUsedBy(activeDev, &usedby_drvname, &usedby_domname); - if (STRNEQ_NULLABLE(drv_name, usedby_drvname) || - STRNEQ_NULLABLE(name, usedby_domname)) { - virPCIDeviceListDel(pcidevs, dev); - continue; - } - } - - virPCIDeviceListDel(hostdev_mgr->activePciHostdevs, dev); - } - - /* At this point, any device that had been used by the guest is in - * pcidevs, but has been removed from activePciHostdevs. - */ - - /* - * For SRIOV net host devices, unset mac and port profile before - * reset and reattach device - */ - for (i = 0; i < nhostdevs; i++) - virHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, - oldStateDir); - - for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { - virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); - - if (virPCIDeviceReset(dev, hostdev_mgr->activePciHostdevs, - hostdev_mgr->inactivePciHostdevs) < 0) { - virErrorPtr err = virGetLastError(); - VIR_ERROR(_("Failed to reset PCI device: %s"), - err ? err->message : _("unknown error")); - virResetError(err); - } - } - - while (virPCIDeviceListCount(pcidevs) > 0) { - virPCIDevicePtr dev = virPCIDeviceListStealIndex(pcidevs, 0); - virHostdevReattachPciDevice(dev, hostdev_mgr); - } - - virObjectUnref(pcidevs); -cleanup: - virObjectUnlock(hostdev_mgr->activePciHostdevs); - virObjectUnlock(hostdev_mgr->inactivePciHostdevs); -} - void qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, const char *name, diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h index 7c4e95a..86ba171 100644 --- a/src/qemu/qemu_hostdev.h +++ b/src/qemu/qemu_hostdev.h @@ -27,11 +27,6 @@ # include "qemu_conf.h" # include "domain_conf.h" -typedef enum { - VIR_HOSTDEV_STRICT_ACS_CHECK = (1 << 0), /* strict acs check */ - VIR_HOSTDEV_COLD_BOOT = (1 << 1), /* cold boot */ -} virHostdevFlag; - int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, virDomainDefPtr def); int qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 7d71e9e..c51029b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -66,6 +66,7 @@ #include "viratomic.h" #include "virnuma.h" #include "virstring.h" +#include "virhostdev.h" #define VIR_FROM_THIS VIR_FROM_QEMU diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index bb2888f..dec3c83 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -1,5 +1,7 @@ /* virhostdev.c: hostdev management * + * Copyright (C) 2006-2007, 2009-2013 Red Hat, Inc. + * Copyright (C) 2006 Daniel P. Berrange * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. * * This library is free software; you can redistribute it and/or @@ -16,6 +18,7 @@ * License along with this library. If not, see * <http://www.gnu.org/licenses/>. * + * Author: Daniel P. Berrange <berrange@redhat.com> * Author: Chunyan Liu <cyliu@suse.com> */ @@ -36,6 +39,7 @@ #include "virerror.h" #include "virlog.h" #include "virutil.h" +#include "virnetdev.h" #include "configmake.h" #define VIR_FROM_THIS VIR_FROM_NONE @@ -128,3 +132,647 @@ virHostdevManagerGetDefault(void) return virObjectRef(g_hostdev_mgr); } } + +static virPCIDeviceListPtr +virHostdevGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs) +{ + virPCIDeviceListPtr list; + size_t i; + + if (!(list = virPCIDeviceListNew())) + return NULL; + + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virPCIDevicePtr dev; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + continue; + + dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain, + hostdev->source.subsys.u.pci.addr.bus, + hostdev->source.subsys.u.pci.addr.slot, + hostdev->source.subsys.u.pci.addr.function); + if (!dev) { + virObjectUnref(list); + return NULL; + } + + if (virPCIDeviceListAdd(list, dev) < 0) { + virPCIDeviceFree(dev); + virObjectUnref(list); + return NULL; + } + + virPCIDeviceSetManaged(dev, hostdev->managed); + if (hostdev->source.subsys.u.pci.backend + == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (virPCIDeviceSetStubDriver(dev, "vfio-pci") < 0) { + virObjectUnref(list); + return NULL; + } + } else { + if (virPCIDeviceSetStubDriver(dev, "pci-stub") < 0) { + virObjectUnref(list); + return NULL; + } + } + } + + return list; +} + + +/* + * virHostdevGetActivePciHostDeviceList - make a new list with a *copy* of + * every virPCIDevice object that is found on the activePciHostdevs + * list *and* is in the hostdev list for this domain. + * + * Return the new list, or NULL if there was a failure. + * + * Pre-condition: activePciHostdevs is locked + */ +static virPCIDeviceListPtr +virHostdevGetActivePciHostDeviceList(virHostdevManagerPtr mgr, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + virPCIDeviceListPtr list; + size_t i; + + if (!(list = virPCIDeviceListNew())) + return NULL; + + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virDevicePCIAddressPtr addr; + virPCIDevicePtr activeDev; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + continue; + + addr = &hostdev->source.subsys.u.pci.addr; + activeDev = virPCIDeviceListFindByIDs(mgr->activePciHostdevs, + addr->domain, addr->bus, + addr->slot, addr->function); + if (activeDev && virPCIDeviceListAddCopy(list, activeDev) < 0) { + virObjectUnref(list); + return NULL; + } + } + + return list; +} + +static int +virHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, + char **sysfs_path) +{ + virPCIDeviceAddress config_address; + + config_address.domain = hostdev->source.subsys.u.pci.addr.domain; + config_address.bus = hostdev->source.subsys.u.pci.addr.bus; + config_address.slot = hostdev->source.subsys.u.pci.addr.slot; + config_address.function = hostdev->source.subsys.u.pci.addr.function; + + return virPCIDeviceAddressGetSysfsFile(&config_address, sysfs_path); +} + + +static int +virHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev) +{ + char *sysfs_path = NULL; + int ret = -1; + + if (virHostdevPciSysfsPath(hostdev, &sysfs_path) < 0) + return ret; + + ret = virPCIIsVirtualFunction(sysfs_path); + + VIR_FREE(sysfs_path); + + return ret; +} + + +static int +virHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev, + int *vf) +{ + int ret = -1; + char *sysfs_path = NULL; + + if (virHostdevPciSysfsPath(hostdev, &sysfs_path) < 0) + return ret; + + if (virPCIIsVirtualFunction(sysfs_path) == 1) { + if (virPCIGetVirtualFunctionInfo(sysfs_path, linkdev, + vf) < 0) + goto cleanup; + } else { + if (virPCIGetNetName(sysfs_path, linkdev) < 0) + goto cleanup; + *vf = -1; + } + + ret = 0; + +cleanup: + VIR_FREE(sysfs_path); + + return ret; +} + + +static int +virHostdevNetConfigVirtPortProfile(const char *linkdev, int vf, + virNetDevVPortProfilePtr virtPort, + const virMacAddr *macaddr, + const unsigned char *uuid, + bool associate) +{ + int ret = -1; + + if (!virtPort) + return ret; + + switch (virtPort->virtPortType) { + case VIR_NETDEV_VPORT_PROFILE_NONE: + case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH: + case VIR_NETDEV_VPORT_PROFILE_8021QBG: + case VIR_NETDEV_VPORT_PROFILE_LAST: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("virtualport type %s is " + "currently not supported on interfaces of type " + "hostdev"), + virNetDevVPortTypeToString(virtPort->virtPortType)); + break; + + case VIR_NETDEV_VPORT_PROFILE_8021QBH: + if (associate) + ret = virNetDevVPortProfileAssociate(NULL, virtPort, macaddr, + linkdev, vf, uuid, + VIR_NETDEV_VPORT_PROFILE_OP_CREATE, false); + else + ret = virNetDevVPortProfileDisassociate(NULL, virtPort, + macaddr, linkdev, vf, + VIR_NETDEV_VPORT_PROFILE_OP_DESTROY); + break; + } + + return ret; +} + + +static int +virHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev, + const unsigned char *uuid, + char *stateDir) +{ + char *linkdev = NULL; + virNetDevVlanPtr vlan; + virNetDevVPortProfilePtr virtPort; + int ret = -1; + int vf = -1; + int vlanid = -1; + bool port_profile_associate = true; + int isvf; + + isvf = virHostdevIsVirtualFunction(hostdev); + if (isvf <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Interface type hostdev is currently supported on" + " SR-IOV Virtual Functions only")); + return ret; + } + + if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0) + return ret; + + vlan = virDomainNetGetActualVlan(hostdev->parent.data.net); + virtPort = virDomainNetGetActualVirtPortProfile( + hostdev->parent.data.net); + if (virtPort) { + if (vlan) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("direct setting of the vlan tag is not allowed " + "for hostdev devices using %s mode"), + virNetDevVPortTypeToString(virtPort->virtPortType)); + goto cleanup; + } + ret = virHostdevNetConfigVirtPortProfile(linkdev, vf, + virtPort, &hostdev->parent.data.net->mac, uuid, + port_profile_associate); + } else { + /* Set only mac and vlan */ + if (vlan) { + if (vlan->nTags != 1 || vlan->trunk) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("vlan trunking is not supported " + "by SR-IOV network devices")); + goto cleanup; + } + if (vf == -1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("vlan can only be set for SR-IOV VFs, but " + "%s is not a VF"), linkdev); + goto cleanup; + } + vlanid = vlan->tag[0]; + } else if (vf >= 0) { + vlanid = 0; /* assure any current vlan tag is reset */ + } + + ret = virNetDevReplaceNetConfig(linkdev, vf, + &hostdev->parent.data.net->mac, + vlanid, stateDir); + } +cleanup: + VIR_FREE(linkdev); + return ret; +} + +/* @oldStateDir: + * For upgrade purpose: + * To an existing VM on QEMU, the hostdev netconfig file is originally stored + * in cfg->stateDir (/var/run/libvirt/qemu). Switch to new version, it uses new + * location (hostdev_mgr->stateDir) but certainly will not find it. In this + * case, try to find in the old state dir. + */ +static int +virHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, + char *stateDir, + char *oldStateDir) +{ + char *linkdev = NULL; + virNetDevVPortProfilePtr virtPort; + int ret = -1; + int vf = -1; + bool port_profile_associate = false; + int isvf; + + /* This is only needed for PCI devices that have been defined + * using <interface type='hostdev'>. For all others, it is a NOP. + */ + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI || + hostdev->parent.type != VIR_DOMAIN_DEVICE_NET || + !hostdev->parent.data.net) + return 0; + + isvf = virHostdevIsVirtualFunction(hostdev); + if (isvf <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Interface type hostdev is currently supported on" + " SR-IOV Virtual Functions only")); + return ret; + } + + if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0) + return ret; + + virtPort = virDomainNetGetActualVirtPortProfile( + hostdev->parent.data.net); + if (virtPort) { + ret = virHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort, + &hostdev->parent.data.net->mac, + NULL, + port_profile_associate); + } else { + ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir); + if (ret < 0 && oldStateDir != NULL) + ret = virNetDevRestoreNetConfig(linkdev, vf, oldStateDir); + } + + VIR_FREE(linkdev); + + return ret; +} + +int +virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + const unsigned char *uuid, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + unsigned int flags) +{ + virPCIDeviceListPtr pcidevs = NULL; + int last_processed_hostdev_vf = -1; + size_t i; + int ret = -1; + + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); + + if (!(pcidevs = virHostdevGetPciHostDeviceList(hostdevs, nhostdevs))) + goto cleanup; + + /* We have to use 9 loops here. *All* devices must + * be detached before we reset any of them, because + * in some cases you have to reset the whole PCI, + * which impacts all devices on it. Also, all devices + * must be reset before being marked as active. + */ + + /* Loop 1: validate that non-managed device isn't in use, eg + * by checking that device is either un-bound, or bound + * to pci-stub.ko + */ + + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); + virPCIDevicePtr other; + bool strict_acs_check = !!(flags & VIR_HOSTDEV_STRICT_ACS_CHECK); + + if (!virPCIDeviceIsAssignable(dev, strict_acs_check)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("PCI device %s is not assignable"), + virPCIDeviceGetName(dev)); + goto cleanup; + } + /* The device is in use by other active domain if + * the dev is in list activePciHostdevs. + */ + if ((other = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev))) { + const char *other_drvname; + const char *other_domname; + + virPCIDeviceGetUsedBy(other, &other_drvname, &other_domname); + if (other_drvname && other_domname) + virReportError(VIR_ERR_OPERATION_INVALID, + _("PCI device %s is in use by " + "driver %s, domain %s"), + virPCIDeviceGetName(dev), + other_drvname, other_domname); + else + virReportError(VIR_ERR_OPERATION_INVALID, + _("PCI device %s is already in use"), + virPCIDeviceGetName(dev)); + goto cleanup; + } + } + + /* Loop 2: detach managed devices (i.e. bind to appropriate stub driver) */ + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); + if (virPCIDeviceGetManaged(dev) && + virPCIDeviceDetach(dev, hostdev_mgr->activePciHostdevs, NULL) < 0) + goto reattachdevs; + } + + /* Loop 3: Now that all the PCI hostdevs have been detached, we + * can safely reset them */ + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); + + if (virPCIDeviceReset(dev, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) + goto reattachdevs; + } + + /* Loop 4: For SRIOV network devices, Now that we have detached the + * the network device, set the netdev config */ + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + continue; + if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET && + hostdev->parent.data.net) { + if (virHostdevNetConfigReplace(hostdev, uuid, + hostdev_mgr->stateDir) < 0) { + goto resetvfnetconfig; + } + } + last_processed_hostdev_vf = i; + } + + /* Loop 5: Now mark all the devices as active */ + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); + if (virPCIDeviceListAdd(hostdev_mgr->activePciHostdevs, dev) < 0) + goto inactivedevs; + } + + /* Loop 6: Now remove the devices from inactive list. */ + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); + virPCIDeviceListDel(hostdev_mgr->inactivePciHostdevs, dev); + } + + /* Loop 7: Now set the used_by_domain of the device in + * activePciHostdevs as domain name. + */ + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev, activeDev; + + dev = virPCIDeviceListGet(pcidevs, i); + activeDev = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev); + + if (activeDev) + virPCIDeviceSetUsedBy(activeDev, drv_name, name); + } + + /* Loop 8: Now set the original states for hostdev def */ + for (i = 0; i < nhostdevs; i++) { + virPCIDevicePtr dev; + virPCIDevicePtr pcidev; + virDomainHostdevDefPtr hostdev = hostdevs[i]; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + continue; + + dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain, + hostdev->source.subsys.u.pci.addr.bus, + hostdev->source.subsys.u.pci.addr.slot, + hostdev->source.subsys.u.pci.addr.function); + + /* original states "unbind_from_stub", "remove_slot", + * "reprobe" were already set by pciDettachDevice in + * loop 2. + */ + if ((pcidev = virPCIDeviceListFind(pcidevs, dev))) { + hostdev->origstates.states.pci.unbind_from_stub = + virPCIDeviceGetUnbindFromStub(pcidev); + hostdev->origstates.states.pci.remove_slot = + virPCIDeviceGetRemoveSlot(pcidev); + hostdev->origstates.states.pci.reprobe = + virPCIDeviceGetReprobe(pcidev); + } + + virPCIDeviceFree(dev); + } + + /* Loop 9: Now steal all the devices from pcidevs */ + while (virPCIDeviceListCount(pcidevs) > 0) + virPCIDeviceListStealIndex(pcidevs, 0); + + ret = 0; + goto cleanup; + +inactivedevs: + /* Only steal all the devices from activePciHostdevs. We will + * free them in virObjectUnref(). + */ + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); + virPCIDeviceListSteal(hostdev_mgr->activePciHostdevs, dev); + } + +resetvfnetconfig: + for (i = 0; + last_processed_hostdev_vf != -1 && i < last_processed_hostdev_vf; i++) + virHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, NULL); + +reattachdevs: + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); + + /* NB: This doesn't actually re-bind to original driver, just + * unbinds from the stub driver + */ + ignore_value(virPCIDeviceReattach(dev, hostdev_mgr->activePciHostdevs, + NULL)); + } + +cleanup: + virObjectUnlock(hostdev_mgr->activePciHostdevs); + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); + virObjectUnref(pcidevs); + return ret; +} + +/* + * Pre-condition: inactivePciHostdevs & activePciHostdevs + * are locked + */ +static void +virHostdevReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) +{ + /* If the device is not managed and was attached to guest + * successfully, it must have been inactive. + */ + if (!virPCIDeviceGetManaged(dev)) { + if (virPCIDeviceListAdd(mgr->inactivePciHostdevs, dev) < 0) + virPCIDeviceFree(dev); + return; + } + + /* Wait for device cleanup if it is qemu/kvm */ + if (STREQ(virPCIDeviceGetStubDriver(dev), "pci-stub")) { + int retries = 100; + while (virPCIDeviceWaitForCleanup(dev, "kvm_assigned_device") + && retries) { + usleep(100*1000); + retries--; + } + } + + if (virPCIDeviceReattach(dev, mgr->activePciHostdevs, + mgr->inactivePciHostdevs) < 0) { + virErrorPtr err = virGetLastError(); + VIR_ERROR(_("Failed to re-attach PCI device: %s"), + err ? err->message : _("unknown error")); + virResetError(err); + } + virPCIDeviceFree(dev); +} + +/* @oldStateDir: + * For upgrade purpose: see virHostdevNetConfigRestore + */ +void +virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + char *oldStateDir) +{ + virPCIDeviceListPtr pcidevs; + size_t i; + + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); + + if (!(pcidevs = virHostdevGetActivePciHostDeviceList(hostdev_mgr, + hostdevs, + nhostdevs))) { + virErrorPtr err = virGetLastError(); + VIR_ERROR(_("Failed to allocate PCI device list: %s"), + err ? err->message : _("unknown error")); + virResetError(err); + goto cleanup; + } + + /* Again 4 loops; mark all devices as inactive before reset + * them and reset all the devices before re-attach. + * Attach mac and port profile parameters to devices + */ + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); + virPCIDevicePtr activeDev = NULL; + + /* delete the copy of the dev from pcidevs if it's used by + * other domain. Or delete it from activePciHostDevs if it had + * been used by this domain. + */ + activeDev = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev); + if (activeDev) { + const char *usedby_drvname; + const char *usedby_domname; + virPCIDeviceGetUsedBy(activeDev, &usedby_drvname, &usedby_domname); + if (STRNEQ_NULLABLE(drv_name, usedby_drvname) || + STRNEQ_NULLABLE(name, usedby_domname)) { + virPCIDeviceListDel(pcidevs, dev); + continue; + } + } + + virPCIDeviceListDel(hostdev_mgr->activePciHostdevs, dev); + } + + /* At this point, any device that had been used by the guest is in + * pcidevs, but has been removed from activePciHostdevs. + */ + + /* + * For SRIOV net host devices, unset mac and port profile before + * reset and reattach device + */ + for (i = 0; i < nhostdevs; i++) + virHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir, + oldStateDir); + + for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) { + virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i); + + if (virPCIDeviceReset(dev, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) { + virErrorPtr err = virGetLastError(); + VIR_ERROR(_("Failed to reset PCI device: %s"), + err ? err->message : _("unknown error")); + virResetError(err); + } + } + + while (virPCIDeviceListCount(pcidevs) > 0) { + virPCIDevicePtr dev = virPCIDeviceListStealIndex(pcidevs, 0); + virHostdevReattachPciDevice(dev, hostdev_mgr); + } + + virObjectUnref(pcidevs); +cleanup: + virObjectUnlock(hostdev_mgr->activePciHostdevs); + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); +} diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index d4b1b82..c8b17e6 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -1,5 +1,7 @@ /* virhostdev.h: hostdev management * + * Copyright (C) 2006-2007, 2009-2013 Red Hat, Inc. + * Copyright (C) 2006 Daniel P. Berrange * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. * * This library is free software; you can redistribute it and/or @@ -16,6 +18,7 @@ * License along with this library. If not, see * <http://www.gnu.org/licenses/>. * + * Author: Daniel P. Berrange <berrange@redhat.com> * Author: Chunyan Liu <cyliu@suse.com> */ @@ -27,6 +30,13 @@ # include "virpci.h" # include "virusb.h" # include "virscsi.h" +# include "domain_conf.h" + +typedef enum { + VIR_HOSTDEV_STRICT_ACS_CHECK = (1 << 0), /* strict acs check */ + VIR_HOSTDEV_COLD_BOOT = (1 << 1), /* cold boot */ +} virHostdevFlag; + typedef struct _virHostdevManager virHostdevManager; typedef virHostdevManager *virHostdevManagerPtr; @@ -40,5 +50,20 @@ struct _virHostdevManager { }; virHostdevManagerPtr virHostdevManagerGetDefault(void); +int +virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + const unsigned char *uuid, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + unsigned int flags); +void +virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + char *oldStateDir); #endif /* __VIR_HOSTDEV_H__ */ -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:45PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 3 +- src/qemu/qemu_hostdev.c | 647 ---------------------------------------------- src/qemu/qemu_hostdev.h | 5 - src/qemu/qemu_process.c | 1 + src/util/virhostdev.c | 648 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 25 ++ 6 files changed, 676 insertions(+), 653 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Extract general code from qemuUpdateActivePciHostdevs to virHostdevUpdateActivePciHostdevs. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 9fe4019..b52f7ac 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -41,18 +41,14 @@ #define VIR_FROM_THIS VIR_FROM_QEMU -int -qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, - virDomainDefPtr def) +static int +virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, + virDomainDefPtr def) { virDomainHostdevDefPtr hostdev = NULL; virPCIDevicePtr dev = NULL; size_t i; int ret = -1; - virHostdevManagerPtr mgr = driver->hostdevMgr; - - if (!def->nhostdevs) - return 0; virObjectLock(mgr->activePciHostdevs); virObjectLock(mgr->inactivePciHostdevs); @@ -104,6 +100,18 @@ cleanup: } int +qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, + virDomainDefPtr def) +{ + virHostdevManagerPtr mgr = driver->hostdevMgr; + + if (!def->nhostdevs) + return 0; + + return virHostdevUpdateActivePciHostdevs(mgr, def); +} + +int qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, virDomainDefPtr def) { -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:46PM +0800, Chunyan Liu wrote:
Extract general code from qemuUpdateActivePciHostdevs to virHostdevUpdateActivePciHostdevs.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Extract general code from qemuUpdateActiveUsbHostdevs to virHostdevUpdateActiveUsbHostdevs. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index b52f7ac..b6ee404 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -111,17 +111,13 @@ qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, return virHostdevUpdateActivePciHostdevs(mgr, def); } -int -qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, - virDomainDefPtr def) +static int +virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, + virDomainDefPtr def) { virDomainHostdevDefPtr hostdev = NULL; size_t i; int ret = -1; - virHostdevManagerPtr mgr = driver->hostdevMgr; - - if (!def->nhostdevs) - return 0; virObjectLock(mgr->activeUsbHostdevs); for (i = 0; i < def->nhostdevs; i++) { @@ -158,6 +154,18 @@ cleanup: } int +qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, + virDomainDefPtr def) +{ + virHostdevManagerPtr mgr = driver->hostdevMgr; + + if (!def->nhostdevs) + return 0; + + return virHostdevUpdateActiveUsbHostdevs(mgr, def); +} + +int qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, virDomainDefPtr def) { -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:47PM +0800, Chunyan Liu wrote:
Extract general code from qemuUpdateActiveUsbHostdevs to virHostdevUpdateActiveUsbHostdevs.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Extract general code from qemuUpdateActiveScsiHostdevs to virHostdevUpdateActiveScsiHostdevs Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index b6ee404..24ebb60 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -165,19 +165,15 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, return virHostdevUpdateActiveUsbHostdevs(mgr, def); } -int -qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, - virDomainDefPtr def) +static int +virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, + virDomainDefPtr def) { virDomainHostdevDefPtr hostdev = NULL; size_t i; int ret = -1; virSCSIDevicePtr scsi = NULL; virSCSIDevicePtr tmp = NULL; - virHostdevManagerPtr mgr = driver->hostdevMgr; - - if (!def->nhostdevs) - return 0; virObjectLock(mgr->activeScsiHostdevs); for (i = 0; i < def->nhostdevs; i++) { @@ -217,6 +213,18 @@ cleanup: return ret; } +int +qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, + virDomainDefPtr def) +{ + virHostdevManagerPtr mgr = driver->hostdevMgr; + + if (!def->nhostdevs) + return 0; + + return virHostdevUpdateActiveScsiHostdevs(mgr, def); +} + bool qemuHostdevHostSupportsPassthroughVFIO(void) -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:48PM +0800, Chunyan Liu wrote:
Extract general code from qemuUpdateActiveScsiHostdevs to virHostdevUpdateActiveScsiHostdevs
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 24ebb60..ee3a18d 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -43,6 +43,7 @@ static int virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, virDomainDefPtr def) { virDomainHostdevDefPtr hostdev = NULL; @@ -79,7 +80,7 @@ virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, goto cleanup; } - virPCIDeviceSetUsedBy(dev, QEMU_DRIVER_NAME, def->name); + virPCIDeviceSetUsedBy(dev, drv_name, def->name); /* Setup the original states for the PCI device */ virPCIDeviceSetUnbindFromStub(dev, hostdev->origstates.states.pci.unbind_from_stub); @@ -108,11 +109,12 @@ qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, if (!def->nhostdevs) return 0; - return virHostdevUpdateActivePciHostdevs(mgr, def); + return virHostdevUpdateActivePciHostdevs(mgr, QEMU_DRIVER_NAME, def); } static int virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, virDomainDefPtr def) { virDomainHostdevDefPtr hostdev = NULL; @@ -140,7 +142,7 @@ virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, continue; } - virUSBDeviceSetUsedBy(usb, QEMU_DRIVER_NAME, def->name); + virUSBDeviceSetUsedBy(usb, drv_name, def->name); if (virUSBDeviceListAdd(mgr->activeUsbHostdevs, usb) < 0) { virUSBDeviceFree(usb); @@ -162,11 +164,12 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, if (!def->nhostdevs) return 0; - return virHostdevUpdateActiveUsbHostdevs(mgr, def); + return virHostdevUpdateActiveUsbHostdevs(mgr, QEMU_DRIVER_NAME, def); } static int virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, virDomainDefPtr def) { virDomainHostdevDefPtr hostdev = NULL; @@ -193,13 +196,13 @@ virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, goto cleanup; if ((tmp = virSCSIDeviceListFind(mgr->activeScsiHostdevs, scsi))) { - if (virSCSIDeviceSetUsedBy(tmp, QEMU_DRIVER_NAME, def->name) < 0) { + if (virSCSIDeviceSetUsedBy(tmp, drv_name, def->name) < 0) { virSCSIDeviceFree(scsi); goto cleanup; } virSCSIDeviceFree(scsi); } else { - if (virSCSIDeviceSetUsedBy(scsi, QEMU_DRIVER_NAME, def->name) < 0 || + if (virSCSIDeviceSetUsedBy(scsi, drv_name, def->name) < 0 || virSCSIDeviceListAdd(mgr->activeScsiHostdevs, scsi) < 0) { virSCSIDeviceFree(scsi); goto cleanup; @@ -222,7 +225,7 @@ qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, if (!def->nhostdevs) return 0; - return virHostdevUpdateActiveScsiHostdevs(mgr, def); + return virHostdevUpdateActiveScsiHostdevs(mgr, QEMU_DRIVER_NAME, def); } -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:49PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 3 + src/qemu/qemu_hostdev.c | 151 ----------------------------------------------- src/util/virhostdev.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 12 ++++ 4 files changed, 166 insertions(+), 151 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 70085c7..8aba3cf 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1296,6 +1296,9 @@ virHookPresent; virHostdevManagerGetDefault; virHostdevPreparePCIDevices; virHostdevReAttachPCIDevices; +virHostdevUpdateActivePciHostdevs; +virHostdevUpdateActiveScsiHostdevs; +virHostdevUpdateActiveUsbHostdevs; # util/viridentity.h virIdentityGetAttr; diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index ee3a18d..bb3dc69 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -41,65 +41,6 @@ #define VIR_FROM_THIS VIR_FROM_QEMU -static int -virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, - const char *drv_name, - virDomainDefPtr def) -{ - virDomainHostdevDefPtr hostdev = NULL; - virPCIDevicePtr dev = NULL; - size_t i; - int ret = -1; - - virObjectLock(mgr->activePciHostdevs); - virObjectLock(mgr->inactivePciHostdevs); - - for (i = 0; i < def->nhostdevs; i++) { - hostdev = def->hostdevs[i]; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) - continue; - - dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain, - hostdev->source.subsys.u.pci.addr.bus, - hostdev->source.subsys.u.pci.addr.slot, - hostdev->source.subsys.u.pci.addr.function); - - if (!dev) - goto cleanup; - - virPCIDeviceSetManaged(dev, hostdev->managed); - if (hostdev->source.subsys.u.pci.backend - == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { - if (virPCIDeviceSetStubDriver(dev, "vfio-pci") < 0) - goto cleanup; - } else { - if (virPCIDeviceSetStubDriver(dev, "pci-stub") < 0) - goto cleanup; - - } - virPCIDeviceSetUsedBy(dev, drv_name, def->name); - - /* Setup the original states for the PCI device */ - virPCIDeviceSetUnbindFromStub(dev, hostdev->origstates.states.pci.unbind_from_stub); - virPCIDeviceSetRemoveSlot(dev, hostdev->origstates.states.pci.remove_slot); - virPCIDeviceSetReprobe(dev, hostdev->origstates.states.pci.reprobe); - - if (virPCIDeviceListAdd(mgr->activePciHostdevs, dev) < 0) - goto cleanup; - dev = NULL; - } - - ret = 0; -cleanup: - virPCIDeviceFree(dev); - virObjectUnlock(mgr->activePciHostdevs); - virObjectUnlock(mgr->inactivePciHostdevs); - return ret; -} - int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, virDomainDefPtr def) @@ -112,49 +53,6 @@ qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, return virHostdevUpdateActivePciHostdevs(mgr, QEMU_DRIVER_NAME, def); } -static int -virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, - const char *drv_name, - virDomainDefPtr def) -{ - virDomainHostdevDefPtr hostdev = NULL; - size_t i; - int ret = -1; - - virObjectLock(mgr->activeUsbHostdevs); - for (i = 0; i < def->nhostdevs; i++) { - virUSBDevicePtr usb = NULL; - hostdev = def->hostdevs[i]; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; - - usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - NULL); - if (!usb) { - VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - def->name); - continue; - } - - virUSBDeviceSetUsedBy(usb, drv_name, def->name); - - if (virUSBDeviceListAdd(mgr->activeUsbHostdevs, usb) < 0) { - virUSBDeviceFree(usb); - goto cleanup; - } - } - ret = 0; -cleanup: - virObjectUnlock(mgr->activeUsbHostdevs); - return ret; -} - int qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, virDomainDefPtr def) @@ -167,55 +65,6 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, return virHostdevUpdateActiveUsbHostdevs(mgr, QEMU_DRIVER_NAME, def); } -static int -virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, - const char *drv_name, - virDomainDefPtr def) -{ - virDomainHostdevDefPtr hostdev = NULL; - size_t i; - int ret = -1; - virSCSIDevicePtr scsi = NULL; - virSCSIDevicePtr tmp = NULL; - - virObjectLock(mgr->activeScsiHostdevs); - for (i = 0; i < def->nhostdevs; i++) { - hostdev = def->hostdevs[i]; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || - hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) - continue; - - if (!(scsi = virSCSIDeviceNew(NULL, - hostdev->source.subsys.u.scsi.adapter, - hostdev->source.subsys.u.scsi.bus, - hostdev->source.subsys.u.scsi.target, - hostdev->source.subsys.u.scsi.unit, - hostdev->readonly, - hostdev->shareable))) - goto cleanup; - - if ((tmp = virSCSIDeviceListFind(mgr->activeScsiHostdevs, scsi))) { - if (virSCSIDeviceSetUsedBy(tmp, drv_name, def->name) < 0) { - virSCSIDeviceFree(scsi); - goto cleanup; - } - virSCSIDeviceFree(scsi); - } else { - if (virSCSIDeviceSetUsedBy(scsi, drv_name, def->name) < 0 || - virSCSIDeviceListAdd(mgr->activeScsiHostdevs, scsi) < 0) { - virSCSIDeviceFree(scsi); - goto cleanup; - } - } - } - ret = 0; - -cleanup: - virObjectUnlock(mgr->activeScsiHostdevs); - return ret; -} - int qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, virDomainDefPtr def) diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index dec3c83..47447fa 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -776,3 +776,154 @@ cleanup: virObjectUnlock(hostdev_mgr->activePciHostdevs); virObjectUnlock(hostdev_mgr->inactivePciHostdevs); } + +int +virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, + virDomainDefPtr def) +{ + virDomainHostdevDefPtr hostdev = NULL; + virPCIDevicePtr dev = NULL; + size_t i; + int ret = -1; + + virObjectLock(mgr->activePciHostdevs); + virObjectLock(mgr->inactivePciHostdevs); + + for (i = 0; i < def->nhostdevs; i++) { + hostdev = def->hostdevs[i]; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + continue; + + dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain, + hostdev->source.subsys.u.pci.addr.bus, + hostdev->source.subsys.u.pci.addr.slot, + hostdev->source.subsys.u.pci.addr.function); + + if (!dev) + goto cleanup; + + virPCIDeviceSetManaged(dev, hostdev->managed); + if (hostdev->source.subsys.u.pci.backend + == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { + if (virPCIDeviceSetStubDriver(dev, "vfio-pci") < 0) + goto cleanup; + } else { + if (virPCIDeviceSetStubDriver(dev, "pci-stub") < 0) + goto cleanup; + + } + virPCIDeviceSetUsedBy(dev, drv_name, def->name); + + /* Setup the original states for the PCI device */ + virPCIDeviceSetUnbindFromStub(dev, hostdev->origstates.states.pci.unbind_from_stub); + virPCIDeviceSetRemoveSlot(dev, hostdev->origstates.states.pci.remove_slot); + virPCIDeviceSetReprobe(dev, hostdev->origstates.states.pci.reprobe); + + if (virPCIDeviceListAdd(mgr->activePciHostdevs, dev) < 0) + goto cleanup; + dev = NULL; + } + + ret = 0; +cleanup: + virPCIDeviceFree(dev); + virObjectUnlock(mgr->activePciHostdevs); + virObjectUnlock(mgr->inactivePciHostdevs); + return ret; +} + +int +virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, + virDomainDefPtr def) +{ + virDomainHostdevDefPtr hostdev = NULL; + size_t i; + int ret = -1; + + virObjectLock(mgr->activeUsbHostdevs); + for (i = 0; i < def->nhostdevs; i++) { + virUSBDevicePtr usb = NULL; + hostdev = def->hostdevs[i]; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + continue; + + usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device, + NULL); + if (!usb) { + VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device, + def->name); + continue; + } + + virUSBDeviceSetUsedBy(usb, drv_name, def->name); + + if (virUSBDeviceListAdd(mgr->activeUsbHostdevs, usb) < 0) { + virUSBDeviceFree(usb); + goto cleanup; + } + } + ret = 0; +cleanup: + virObjectUnlock(mgr->activeUsbHostdevs); + return ret; +} + +int +virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, + virDomainDefPtr def) +{ + virDomainHostdevDefPtr hostdev = NULL; + size_t i; + int ret = -1; + virSCSIDevicePtr scsi = NULL; + virSCSIDevicePtr tmp = NULL; + + virObjectLock(mgr->activeScsiHostdevs); + for (i = 0; i < def->nhostdevs; i++) { + hostdev = def->hostdevs[i]; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) + continue; + + if (!(scsi = virSCSIDeviceNew(NULL, + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit, + hostdev->readonly, + hostdev->shareable))) + goto cleanup; + + if ((tmp = virSCSIDeviceListFind(mgr->activeScsiHostdevs, scsi))) { + if (virSCSIDeviceSetUsedBy(tmp, drv_name, def->name) < 0) { + virSCSIDeviceFree(scsi); + goto cleanup; + } + virSCSIDeviceFree(scsi); + } else { + if (virSCSIDeviceSetUsedBy(scsi, drv_name, def->name) < 0 || + virSCSIDeviceListAdd(mgr->activeScsiHostdevs, scsi) < 0) { + virSCSIDeviceFree(scsi); + goto cleanup; + } + } + } + ret = 0; + +cleanup: + virObjectUnlock(mgr->activeScsiHostdevs); + return ret; +} diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index c8b17e6..e6b5e31 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -65,5 +65,17 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, virDomainHostdevDefPtr *hostdevs, int nhostdevs, char *oldStateDir); +int +virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, + virDomainDefPtr def); +int +virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, + virDomainDefPtr def); +int +virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, + virDomainDefPtr def); #endif /* __VIR_HOSTDEV_H__ */ -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:50PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 3 + src/qemu/qemu_hostdev.c | 151 ----------------------------------------------- src/util/virhostdev.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 12 ++++ 4 files changed, 166 insertions(+), 151 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Extract general code from qemuPrepareHostUSBDevices to virHostdevPrepareHostUSBDevices. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index bb3dc69..25a34e8 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -377,19 +377,17 @@ out: return 0; } - -int -qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - unsigned int flags) +static int +virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + unsigned int flags) { size_t i; int ret = -1; virUSBDeviceListPtr list; virUSBDevicePtr tmp; - virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; bool coldBoot = !!(flags & VIR_HOSTDEV_COLD_BOOT); /* To prevent situation where USB device is assigned to two domains @@ -449,6 +447,19 @@ cleanup: return ret; } +int +qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + unsigned int flags) +{ + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + return virHostdevPrepareUSBDevices(hostdev_mgr, name, + hostdevs, nhostdevs, flags); +} + int qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:51PM +0800, Chunyan Liu wrote:
Extract general code from qemuPrepareHostUSBDevices to virHostdevPrepareHostUSBDevices.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 25a34e8..b72e9f9 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -234,9 +234,9 @@ out: static int -qemuPrepareHostdevUSBDevices(virHostdevManagerPtr mgr, - const char *name, - virUSBDeviceListPtr list) +virHostdevMarkUsbHostdevs(virHostdevManagerPtr mgr, + const char *name, + virUSBDeviceListPtr list) { size_t i, j; unsigned int count; @@ -291,9 +291,9 @@ error: static int -qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, - bool mandatory, - virUSBDevicePtr *usb) +virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev, + bool mandatory, + virUSBDevicePtr *usb) { unsigned vendor = hostdev->source.subsys.u.usb.vendor; unsigned product = hostdev->source.subsys.u.usb.product; @@ -415,7 +415,7 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, !coldBoot)) required = false; - if (qemuFindHostdevUSBDevice(hostdev, required, &usb) < 0) + if (virHostdevFindUSBDevice(hostdev, required, &usb) < 0) goto cleanup; if (usb && virUSBDeviceListAdd(list, usb) < 0) { @@ -428,7 +428,7 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, * and add them do driver list. However, if something goes * wrong, perform rollback. */ - if (qemuPrepareHostdevUSBDevices(hostdev_mgr, name, list) < 0) + if (virHostdevMarkUsbHostdevs(hostdev_mgr, name, list) < 0) goto cleanup; /* Loop 2: Temporary list was successfully merged with -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:52PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index b72e9f9..0eb78ac 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -235,6 +235,7 @@ out: static int virHostdevMarkUsbHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, const char *name, virUSBDeviceListPtr list) { @@ -265,7 +266,7 @@ virHostdevMarkUsbHostdevs(virHostdevManagerPtr mgr, goto error; } - virUSBDeviceSetUsedBy(usb, QEMU_DRIVER_NAME, name); + virUSBDeviceSetUsedBy(usb, drv_name, name); VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs", virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb), name); /* @@ -379,6 +380,7 @@ out: static int virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs, @@ -428,7 +430,7 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, * and add them do driver list. However, if something goes * wrong, perform rollback. */ - if (virHostdevMarkUsbHostdevs(hostdev_mgr, name, list) < 0) + if (virHostdevMarkUsbHostdevs(hostdev_mgr, drv_name, name, list) < 0) goto cleanup; /* Loop 2: Temporary list was successfully merged with @@ -456,7 +458,7 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, { virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - return virHostdevPrepareUSBDevices(hostdev_mgr, name, + return virHostdevPrepareUSBDevices(hostdev_mgr, QEMU_DRIVER_NAME, name, hostdevs, nhostdevs, flags); } -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:53PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_hostdev.c | 217 ----------------------------------------------- src/util/virhostdev.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 7 ++ 4 files changed, 224 insertions(+), 217 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8aba3cf..04694d8 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1295,6 +1295,7 @@ virHookPresent; #util/virhostdev.h virHostdevManagerGetDefault; virHostdevPreparePCIDevices; +virHostdevPrepareUSBDevices; virHostdevReAttachPCIDevices; virHostdevUpdateActivePciHostdevs; virHostdevUpdateActiveScsiHostdevs; diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 0eb78ac..35494d8 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -232,223 +232,6 @@ out: return ret; } - -static int -virHostdevMarkUsbHostdevs(virHostdevManagerPtr mgr, - const char *drv_name, - const char *name, - virUSBDeviceListPtr list) -{ - size_t i, j; - unsigned int count; - virUSBDevicePtr tmp; - - virObjectLock(mgr->activeUsbHostdevs); - count = virUSBDeviceListCount(list); - - for (i = 0; i < count; i++) { - virUSBDevicePtr usb = virUSBDeviceListGet(list, i); - if ((tmp = virUSBDeviceListFind(mgr->activeUsbHostdevs, usb))) { - const char *other_drvname; - const char *other_domname; - - virUSBDeviceGetUsedBy(tmp, &other_drvname, &other_domname); - if (other_drvname && other_domname) - virReportError(VIR_ERR_OPERATION_INVALID, - _("USB device %s is in use by " - "driver %s, domain %s"), - virUSBDeviceGetName(tmp), - other_drvname, other_domname); - else - virReportError(VIR_ERR_OPERATION_INVALID, - _("USB device %s is already in use"), - virUSBDeviceGetName(tmp)); - goto error; - } - - virUSBDeviceSetUsedBy(usb, drv_name, name); - VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs", - virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb), name); - /* - * The caller is responsible to steal these usb devices - * from the virUSBDeviceList that passed in on success, - * perform rollback on failure. - */ - if (virUSBDeviceListAdd(mgr->activeUsbHostdevs, usb) < 0) - goto error; - } - - virObjectUnlock(mgr->activeUsbHostdevs); - return 0; - -error: - for (j = 0; j < i; j++) { - tmp = virUSBDeviceListGet(list, i); - virUSBDeviceListSteal(mgr->activeUsbHostdevs, tmp); - } - virObjectUnlock(mgr->activeUsbHostdevs); - return -1; -} - - -static int -virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev, - bool mandatory, - virUSBDevicePtr *usb) -{ - unsigned vendor = hostdev->source.subsys.u.usb.vendor; - unsigned product = hostdev->source.subsys.u.usb.product; - unsigned bus = hostdev->source.subsys.u.usb.bus; - unsigned device = hostdev->source.subsys.u.usb.device; - bool autoAddress = hostdev->source.subsys.u.usb.autoAddress; - int rc; - - *usb = NULL; - - if (vendor && bus) { - rc = virUSBDeviceFind(vendor, product, bus, device, - NULL, - autoAddress ? false : mandatory, - usb); - if (rc < 0) { - return -1; - } else if (!autoAddress) { - goto out; - } else { - VIR_INFO("USB device %x:%x could not be found at previous" - " address (bus:%u device:%u)", - vendor, product, bus, device); - } - } - - /* When vendor is specified, its USB address is either unspecified or the - * device could not be found at the USB device where it had been - * automatically found before. - */ - if (vendor) { - virUSBDeviceListPtr devs; - - rc = virUSBDeviceFindByVendor(vendor, product, NULL, mandatory, &devs); - if (rc < 0) - return -1; - - if (rc == 1) { - *usb = virUSBDeviceListGet(devs, 0); - virUSBDeviceListSteal(devs, *usb); - } - virObjectUnref(devs); - - if (rc == 0) { - goto out; - } else if (rc > 1) { - if (autoAddress) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("Multiple USB devices for %x:%x were found," - " but none of them is at bus:%u device:%u"), - vendor, product, bus, device); - } else { - virReportError(VIR_ERR_OPERATION_FAILED, - _("Multiple USB devices for %x:%x, " - "use <address> to specify one"), - vendor, product); - } - return -1; - } - - hostdev->source.subsys.u.usb.bus = virUSBDeviceGetBus(*usb); - hostdev->source.subsys.u.usb.device = virUSBDeviceGetDevno(*usb); - hostdev->source.subsys.u.usb.autoAddress = true; - - if (autoAddress) { - VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved" - " from bus:%u device:%u)", - vendor, product, - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - bus, device); - } - } else if (!vendor && bus) { - if (virUSBDeviceFindByBus(bus, device, NULL, mandatory, usb) < 0) - return -1; - } - -out: - if (!*usb) - hostdev->missing = true; - return 0; -} - -static int -virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - unsigned int flags) -{ - size_t i; - int ret = -1; - virUSBDeviceListPtr list; - virUSBDevicePtr tmp; - bool coldBoot = !!(flags & VIR_HOSTDEV_COLD_BOOT); - - /* To prevent situation where USB device is assigned to two domains - * we need to keep a list of currently assigned USB devices. - * This is done in several loops which cannot be joined into one big - * loop. See virHostdevPreparePCIDevices() - */ - if (!(list = virUSBDeviceListNew())) - goto cleanup; - - /* Loop 1: build temporary list - */ - for (i = 0; i < nhostdevs; i++) { - virDomainHostdevDefPtr hostdev = hostdevs[i]; - bool required = true; - virUSBDevicePtr usb; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; - - if (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_OPTIONAL || - (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE && - !coldBoot)) - required = false; - - if (virHostdevFindUSBDevice(hostdev, required, &usb) < 0) - goto cleanup; - - if (usb && virUSBDeviceListAdd(list, usb) < 0) { - virUSBDeviceFree(usb); - goto cleanup; - } - } - - /* Mark devices in temporary list as used by @name - * and add them do driver list. However, if something goes - * wrong, perform rollback. - */ - if (virHostdevMarkUsbHostdevs(hostdev_mgr, drv_name, name, list) < 0) - goto cleanup; - - /* Loop 2: Temporary list was successfully merged with - * driver list, so steal all items to avoid freeing them - * in cleanup label. - */ - while (virUSBDeviceListCount(list) > 0) { - tmp = virUSBDeviceListGet(list, 0); - virUSBDeviceListSteal(list, tmp); - } - - ret = 0; - -cleanup: - virObjectUnref(list); - return ret; -} - int qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, const char *name, diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 47447fa..a55480c 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -927,3 +927,219 @@ cleanup: virObjectUnlock(mgr->activeScsiHostdevs); return ret; } + +static int +virHostdevMarkUsbHostdevs(virHostdevManagerPtr mgr, + const char *drv_name, + const char *name, + virUSBDeviceListPtr list) +{ + size_t i, j; + unsigned int count; + virUSBDevicePtr tmp; + + virObjectLock(mgr->activeUsbHostdevs); + count = virUSBDeviceListCount(list); + + for (i = 0; i < count; i++) { + virUSBDevicePtr usb = virUSBDeviceListGet(list, i); + if ((tmp = virUSBDeviceListFind(mgr->activeUsbHostdevs, usb))) { + const char *other_drvname; + const char *other_domname; + + virUSBDeviceGetUsedBy(tmp, &other_drvname, &other_domname); + if (other_drvname && other_domname) + virReportError(VIR_ERR_OPERATION_INVALID, + _("USB device %s is in use by " + "driver %s, domain %s"), + virUSBDeviceGetName(tmp), + other_drvname, other_domname); + else + virReportError(VIR_ERR_OPERATION_INVALID, + _("USB device %s is already in use"), + virUSBDeviceGetName(tmp)); + goto error; + } + + virUSBDeviceSetUsedBy(usb, drv_name, name); + VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs", + virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb), name); + /* + * The caller is responsible to steal these usb devices + * from the virUSBDeviceList that passed in on success, + * perform rollback on failure. + */ + if (virUSBDeviceListAdd(mgr->activeUsbHostdevs, usb) < 0) + goto error; + } + + virObjectUnlock(mgr->activeUsbHostdevs); + return 0; + +error: + for (j = 0; j < i; j++) { + tmp = virUSBDeviceListGet(list, i); + virUSBDeviceListSteal(mgr->activeUsbHostdevs, tmp); + } + virObjectUnlock(mgr->activeUsbHostdevs); + return -1; +} + + +static int +virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev, + bool mandatory, + virUSBDevicePtr *usb) +{ + unsigned vendor = hostdev->source.subsys.u.usb.vendor; + unsigned product = hostdev->source.subsys.u.usb.product; + unsigned bus = hostdev->source.subsys.u.usb.bus; + unsigned device = hostdev->source.subsys.u.usb.device; + bool autoAddress = hostdev->source.subsys.u.usb.autoAddress; + int rc; + + *usb = NULL; + + if (vendor && bus) { + rc = virUSBDeviceFind(vendor, product, bus, device, + NULL, + autoAddress ? false : mandatory, + usb); + if (rc < 0) { + return -1; + } else if (!autoAddress) { + goto out; + } else { + VIR_INFO("USB device %x:%x could not be found at previous" + " address (bus:%u device:%u)", + vendor, product, bus, device); + } + } + + /* When vendor is specified, its USB address is either unspecified or the + * device could not be found at the USB device where it had been + * automatically found before. + */ + if (vendor) { + virUSBDeviceListPtr devs; + + rc = virUSBDeviceFindByVendor(vendor, product, NULL, mandatory, &devs); + if (rc < 0) + return -1; + + if (rc == 1) { + *usb = virUSBDeviceListGet(devs, 0); + virUSBDeviceListSteal(devs, *usb); + } + virObjectUnref(devs); + + if (rc == 0) { + goto out; + } else if (rc > 1) { + if (autoAddress) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("Multiple USB devices for %x:%x were found," + " but none of them is at bus:%u device:%u"), + vendor, product, bus, device); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("Multiple USB devices for %x:%x, " + "use <address> to specify one"), + vendor, product); + } + return -1; + } + + hostdev->source.subsys.u.usb.bus = virUSBDeviceGetBus(*usb); + hostdev->source.subsys.u.usb.device = virUSBDeviceGetDevno(*usb); + hostdev->source.subsys.u.usb.autoAddress = true; + + if (autoAddress) { + VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved" + " from bus:%u device:%u)", + vendor, product, + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device, + bus, device); + } + } else if (!vendor && bus) { + if (virUSBDeviceFindByBus(bus, device, NULL, mandatory, usb) < 0) + return -1; + } + +out: + if (!*usb) + hostdev->missing = true; + return 0; +} + +int +virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + unsigned int flags) +{ + size_t i; + int ret = -1; + virUSBDeviceListPtr list; + virUSBDevicePtr tmp; + bool coldBoot = !!(flags & VIR_HOSTDEV_COLD_BOOT); + + /* To prevent situation where USB device is assigned to two domains + * we need to keep a list of currently assigned USB devices. + * This is done in several loops which cannot be joined into one big + * loop. See virHostdevPreparePCIDevices() + */ + if (!(list = virUSBDeviceListNew())) + goto cleanup; + + /* Loop 1: build temporary list + */ + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + bool required = true; + virUSBDevicePtr usb; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + continue; + + if (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_OPTIONAL || + (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE && + !coldBoot)) + required = false; + + if (virHostdevFindUSBDevice(hostdev, required, &usb) < 0) + goto cleanup; + + if (usb && virUSBDeviceListAdd(list, usb) < 0) { + virUSBDeviceFree(usb); + goto cleanup; + } + } + + /* Mark devices in temporary list as used by @name + * and add them do driver list. However, if something goes + * wrong, perform rollback. + */ + if (virHostdevMarkUsbHostdevs(hostdev_mgr, drv_name, name, list) < 0) + goto cleanup; + + /* Loop 2: Temporary list was successfully merged with + * driver list, so steal all items to avoid freeing them + * in cleanup label. + */ + while (virUSBDeviceListCount(list) > 0) { + tmp = virUSBDeviceListGet(list, 0); + virUSBDeviceListSteal(list, tmp); + } + + ret = 0; + +cleanup: + virObjectUnref(list); + return ret; +} diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index e6b5e31..83ebefc 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -58,6 +58,13 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, virDomainHostdevDefPtr *hostdevs, int nhostdevs, unsigned int flags); +int +virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + unsigned int flags); void virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:54PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_hostdev.c | 217 ----------------------------------------------- src/util/virhostdev.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 7 ++ 4 files changed, 224 insertions(+), 217 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Extract general code from qemuPrepareHostSCSIDevices to virHostdevPrepareHostSCSIDevices. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 63 +++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 35494d8..9ad32e0 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -245,34 +245,16 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, hostdevs, nhostdevs, flags); } - -int -qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) +static int +virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) { size_t i, j; int count; virSCSIDeviceListPtr list; virSCSIDevicePtr tmp; - virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - - /* Loop 1: Add the shared scsi host device to shared device - * table. - */ - for (i = 0; i < nhostdevs; i++) { - virDomainDeviceDef dev; - - dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; - dev.data.hostdev = hostdevs[i]; - - if (qemuAddSharedDevice(driver, &dev, name) < 0) - return -1; - - if (qemuSetUnprivSGIO(&dev) < 0) - return -1; - } /* To prevent situation where SCSI device is assigned to two domains * we need to keep a list of currently assigned SCSI devices. @@ -282,7 +264,7 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, if (!(list = virSCSIDeviceListNew())) goto cleanup; - /* Loop 2: build temporary list */ + /* Loop 1: build temporary list */ for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; virSCSIDevicePtr scsi; @@ -312,7 +294,7 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, } } - /* Loop 3: Mark devices in temporary list as used by @name + /* Loop 2: Mark devices in temporary list as used by @name * and add them to driver list. However, if something goes * wrong, perform rollback. */ @@ -350,7 +332,7 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, virObjectUnlock(hostdev_mgr->activeScsiHostdevs); - /* Loop 4: Temporary list was successfully merged with + /* Loop 3: Temporary list was successfully merged with * driver list, so steal all items to avoid freeing them * when freeing temporary list. */ @@ -373,6 +355,35 @@ cleanup: return -1; } +int +qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + /* Loop 1: Add the shared scsi host device to shared device + * table. + */ + for (i = 0; i < nhostdevs; i++) { + virDomainDeviceDef dev; + + dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; + dev.data.hostdev = hostdevs[i]; + + if (qemuAddSharedDevice(driver, &dev, name) < 0) + return -1; + + if (qemuSetUnprivSGIO(&dev) < 0) + return -1; + } + + return virHostdevPrepareSCSIDevices(hostdev_mgr, name, + hostdevs, nhostdevs); +} + int qemuPrepareHostDevices(virQEMUDriverPtr driver, -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:55PM +0800, Chunyan Liu wrote:
Extract general code from qemuPrepareHostSCSIDevices to virHostdevPrepareHostSCSIDevices.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 63 +++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 26 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 9ad32e0..41ee32f 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -247,6 +247,7 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, static int virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) @@ -317,10 +318,10 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, goto error; } - if (virSCSIDeviceSetUsedBy(tmp, QEMU_DRIVER_NAME, name) < 0) + if (virSCSIDeviceSetUsedBy(tmp, drv_name, name) < 0) goto error; } else { - if (virSCSIDeviceSetUsedBy(scsi, QEMU_DRIVER_NAME, name) < 0) + if (virSCSIDeviceSetUsedBy(scsi, drv_name, name) < 0) goto error; VIR_DEBUG("Adding %s to activeScsiHostdevs", virSCSIDeviceGetName(scsi)); @@ -380,8 +381,8 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, return -1; } - return virHostdevPrepareSCSIDevices(hostdev_mgr, name, - hostdevs, nhostdevs); + return virHostdevPrepareSCSIDevices(hostdev_mgr, QEMU_DRIVER_NAME, + name, hostdevs, nhostdevs); } -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:56PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_hostdev.c | 111 ----------------------------------------------- src/util/virhostdev.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 6 +++ 4 files changed, 118 insertions(+), 111 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 04694d8..f3cd7a0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1295,6 +1295,7 @@ virHookPresent; #util/virhostdev.h virHostdevManagerGetDefault; virHostdevPreparePCIDevices; +virHostdevPrepareSCSIDevices; virHostdevPrepareUSBDevices; virHostdevReAttachPCIDevices; virHostdevUpdateActivePciHostdevs; diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 41ee32f..32825a4 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -245,117 +245,6 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, hostdevs, nhostdevs, flags); } -static int -virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) -{ - size_t i, j; - int count; - virSCSIDeviceListPtr list; - virSCSIDevicePtr tmp; - - /* To prevent situation where SCSI device is assigned to two domains - * we need to keep a list of currently assigned SCSI devices. - * This is done in several loops which cannot be joined into one big - * loop. See virHostdevPreparePCIDevices() - */ - if (!(list = virSCSIDeviceListNew())) - goto cleanup; - - /* Loop 1: build temporary list */ - for (i = 0; i < nhostdevs; i++) { - virDomainHostdevDefPtr hostdev = hostdevs[i]; - virSCSIDevicePtr scsi; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || - hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) - continue; - - if (hostdev->managed) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("SCSI host device doesn't support managed mode")); - goto cleanup; - } - - if (!(scsi = virSCSIDeviceNew(NULL, - hostdev->source.subsys.u.scsi.adapter, - hostdev->source.subsys.u.scsi.bus, - hostdev->source.subsys.u.scsi.target, - hostdev->source.subsys.u.scsi.unit, - hostdev->readonly, - hostdev->shareable))) - goto cleanup; - - if (scsi && virSCSIDeviceListAdd(list, scsi) < 0) { - virSCSIDeviceFree(scsi); - goto cleanup; - } - } - - /* Loop 2: Mark devices in temporary list as used by @name - * and add them to driver list. However, if something goes - * wrong, perform rollback. - */ - virObjectLock(hostdev_mgr->activeScsiHostdevs); - count = virSCSIDeviceListCount(list); - - for (i = 0; i < count; i++) { - virSCSIDevicePtr scsi = virSCSIDeviceListGet(list, i); - if ((tmp = virSCSIDeviceListFind(hostdev_mgr->activeScsiHostdevs, - scsi))) { - bool scsi_shareable = virSCSIDeviceGetShareable(scsi); - bool tmp_shareable = virSCSIDeviceGetShareable(tmp); - - if (!(scsi_shareable && tmp_shareable)) { - virReportError(VIR_ERR_OPERATION_INVALID, - _("SCSI device %s is already in use by " - "other domain(s) as '%s'"), - virSCSIDeviceGetName(tmp), - tmp_shareable ? "shareable" : "non-shareable"); - goto error; - } - - if (virSCSIDeviceSetUsedBy(tmp, drv_name, name) < 0) - goto error; - } else { - if (virSCSIDeviceSetUsedBy(scsi, drv_name, name) < 0) - goto error; - - VIR_DEBUG("Adding %s to activeScsiHostdevs", virSCSIDeviceGetName(scsi)); - - if (virSCSIDeviceListAdd(hostdev_mgr->activeScsiHostdevs, scsi) < 0) - goto error; - } - } - - virObjectUnlock(hostdev_mgr->activeScsiHostdevs); - - /* Loop 3: Temporary list was successfully merged with - * driver list, so steal all items to avoid freeing them - * when freeing temporary list. - */ - while (virSCSIDeviceListCount(list) > 0) { - tmp = virSCSIDeviceListGet(list, 0); - virSCSIDeviceListSteal(list, tmp); - } - - virObjectUnref(list); - return 0; - -error: - for (j = 0; j < i; j++) { - tmp = virSCSIDeviceListGet(list, i); - virSCSIDeviceListSteal(hostdev_mgr->activeScsiHostdevs, tmp); - } - virObjectUnlock(hostdev_mgr->activeScsiHostdevs); -cleanup: - virObjectUnref(list); - return -1; -} - int qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, const char *name, diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index a55480c..87b7368 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -1143,3 +1143,114 @@ cleanup: virObjectUnref(list); return ret; } + +int +virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i, j; + int count; + virSCSIDeviceListPtr list; + virSCSIDevicePtr tmp; + + /* To prevent situation where SCSI device is assigned to two domains + * we need to keep a list of currently assigned SCSI devices. + * This is done in several loops which cannot be joined into one big + * loop. See virHostdevPreparePCIDevices() + */ + if (!(list = virSCSIDeviceListNew())) + goto cleanup; + + /* Loop 1: build temporary list */ + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virSCSIDevicePtr scsi; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) + continue; + + if (hostdev->managed) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("SCSI host device doesn't support managed mode")); + goto cleanup; + } + + if (!(scsi = virSCSIDeviceNew(NULL, + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit, + hostdev->readonly, + hostdev->shareable))) + goto cleanup; + + if (scsi && virSCSIDeviceListAdd(list, scsi) < 0) { + virSCSIDeviceFree(scsi); + goto cleanup; + } + } + + /* Loop 2: Mark devices in temporary list as used by @name + * and add them to driver list. However, if something goes + * wrong, perform rollback. + */ + virObjectLock(hostdev_mgr->activeScsiHostdevs); + count = virSCSIDeviceListCount(list); + + for (i = 0; i < count; i++) { + virSCSIDevicePtr scsi = virSCSIDeviceListGet(list, i); + if ((tmp = virSCSIDeviceListFind(hostdev_mgr->activeScsiHostdevs, + scsi))) { + bool scsi_shareable = virSCSIDeviceGetShareable(scsi); + bool tmp_shareable = virSCSIDeviceGetShareable(tmp); + + if (!(scsi_shareable && tmp_shareable)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("SCSI device %s is already in use by " + "other domain(s) as '%s'"), + virSCSIDeviceGetName(tmp), + tmp_shareable ? "shareable" : "non-shareable"); + goto error; + } + + if (virSCSIDeviceSetUsedBy(tmp, drv_name, name) < 0) + goto error; + } else { + if (virSCSIDeviceSetUsedBy(scsi, drv_name, name) < 0) + goto error; + + VIR_DEBUG("Adding %s to activeScsiHostdevs", virSCSIDeviceGetName(scsi)); + + if (virSCSIDeviceListAdd(hostdev_mgr->activeScsiHostdevs, scsi) < 0) + goto error; + } + } + + virObjectUnlock(hostdev_mgr->activeScsiHostdevs); + + /* Loop 3: Temporary list was successfully merged with + * driver list, so steal all items to avoid freeing them + * when freeing temporary list. + */ + while (virSCSIDeviceListCount(list) > 0) { + tmp = virSCSIDeviceListGet(list, 0); + virSCSIDeviceListSteal(list, tmp); + } + + virObjectUnref(list); + return 0; + +error: + for (j = 0; j < i; j++) { + tmp = virSCSIDeviceListGet(list, i); + virSCSIDeviceListSteal(hostdev_mgr->activeScsiHostdevs, tmp); + } + virObjectUnlock(hostdev_mgr->activeScsiHostdevs); +cleanup: + virObjectUnref(list); + return -1; +} diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index 83ebefc..c149603 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -65,6 +65,12 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, virDomainHostdevDefPtr *hostdevs, int nhostdevs, unsigned int flags); +int +virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs); void virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:57PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_hostdev.c | 111 ----------------------------------------------- src/util/virhostdev.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 6 +++ 4 files changed, 118 insertions(+), 111 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Extract general code from qemuDomainReAttachHostUsbDevices to virHostdevDomainReAttachHostUsbDevices. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 32825a4..3d6396b 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -316,15 +316,13 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, virObjectUnref(cfg); } - -void -qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) +static void +virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) { size_t i; - virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; virObjectLock(hostdev_mgr->activeUsbHostdevs); for (i = 0; i < nhostdevs; i++) { @@ -383,6 +381,17 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, virObjectUnlock(hostdev_mgr->activeUsbHostdevs); } +void +qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + virHostdevReAttachUsbHostdevs(hostdev_mgr, name, hostdevs, nhostdevs); +} + void qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:58PM +0800, Chunyan Liu wrote:
Extract general code from qemuDomainReAttachHostUsbDevices to virHostdevDomainReAttachHostUsbDevices.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 3d6396b..af1fe87 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -318,6 +318,7 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, static void virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) @@ -368,7 +369,7 @@ virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, } virUSBDeviceGetUsedBy(tmp, &usedby_drvname, &usedby_domname); - if (STREQ_NULLABLE(QEMU_DRIVER_NAME, usedby_drvname) && + if (STREQ_NULLABLE(drv_name, usedby_drvname) && STREQ_NULLABLE(name, usedby_domname)) { VIR_DEBUG("Removing %03d.%03d dom=%s from activeUsbHostdevs", hostdev->source.subsys.u.usb.bus, @@ -389,7 +390,8 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, { virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - virHostdevReAttachUsbHostdevs(hostdev_mgr, name, hostdevs, nhostdevs); + virHostdevReAttachUsbHostdevs(hostdev_mgr, QEMU_DRIVER_NAME, + name, hostdevs, nhostdevs); } -- 1.9.0

On Fri, Mar 07, 2014 at 06:52:59PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_hostdev.c | 66 ------------------------------------------------ src/util/virhostdev.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 6 +++++ 4 files changed, 73 insertions(+), 66 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f3cd7a0..ed23337 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1298,6 +1298,7 @@ virHostdevPreparePCIDevices; virHostdevPrepareSCSIDevices; virHostdevPrepareUSBDevices; virHostdevReAttachPCIDevices; +virHostdevReAttachUsbHostdevs; virHostdevUpdateActivePciHostdevs; virHostdevUpdateActiveScsiHostdevs; virHostdevUpdateActiveUsbHostdevs; diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index af1fe87..41cda48 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -316,72 +316,6 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, virObjectUnref(cfg); } -static void -virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) -{ - size_t i; - - virObjectLock(hostdev_mgr->activeUsbHostdevs); - for (i = 0; i < nhostdevs; i++) { - virDomainHostdevDefPtr hostdev = hostdevs[i]; - virUSBDevicePtr usb, tmp; - const char *usedby_drvname; - const char *usedby_domname; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; - if (hostdev->missing) - continue; - - usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - NULL); - - if (!usb) { - VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - name); - continue; - } - - /* Delete only those USB devices which belongs - * to domain @name because qemuProcessStart() might - * have failed because USB device is already taken. - * Therefore we want to steal only those devices from - * the list which were taken by @name */ - - tmp = virUSBDeviceListFind(hostdev_mgr->activeUsbHostdevs, usb); - virUSBDeviceFree(usb); - - if (!tmp) { - VIR_WARN("Unable to find device %03d.%03d " - "in list of active USB devices", - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device); - continue; - } - - virUSBDeviceGetUsedBy(tmp, &usedby_drvname, &usedby_domname); - if (STREQ_NULLABLE(drv_name, usedby_drvname) && - STREQ_NULLABLE(name, usedby_domname)) { - VIR_DEBUG("Removing %03d.%03d dom=%s from activeUsbHostdevs", - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - name); - - virUSBDeviceListDel(hostdev_mgr->activeUsbHostdevs, tmp); - } - } - virObjectUnlock(hostdev_mgr->activeUsbHostdevs); -} - void qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, const char *name, diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 87b7368..e679e20 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -1254,3 +1254,69 @@ cleanup: virObjectUnref(list); return -1; } + +void +virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i; + + virObjectLock(hostdev_mgr->activeUsbHostdevs); + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virUSBDevicePtr usb, tmp; + const char *usedby_drvname; + const char *usedby_domname; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + continue; + if (hostdev->missing) + continue; + + usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device, + NULL); + + if (!usb) { + VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device, + name); + continue; + } + + /* Delete only those USB devices which belongs + * to domain @name because qemuProcessStart() might + * have failed because USB device is already taken. + * Therefore we want to steal only those devices from + * the list which were taken by @name */ + + tmp = virUSBDeviceListFind(hostdev_mgr->activeUsbHostdevs, usb); + virUSBDeviceFree(usb); + + if (!tmp) { + VIR_WARN("Unable to find device %03d.%03d " + "in list of active USB devices", + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device); + continue; + } + + virUSBDeviceGetUsedBy(tmp, &usedby_drvname, &usedby_domname); + if (STREQ_NULLABLE(drv_name, usedby_drvname) && + STREQ_NULLABLE(name, usedby_domname)) { + VIR_DEBUG("Removing %03d.%03d dom=%s from activeUsbHostdevs", + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device, + name); + + virUSBDeviceListDel(hostdev_mgr->activeUsbHostdevs, tmp); + } + } + virObjectUnlock(hostdev_mgr->activeUsbHostdevs); +} diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index c149603..7bd5da1 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -78,6 +78,12 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, virDomainHostdevDefPtr *hostdevs, int nhostdevs, char *oldStateDir); +void +virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs); int virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, const char *drv_name, -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:00PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_hostdev.c | 66 ------------------------------------------------ src/util/virhostdev.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 6 +++++ 4 files changed, 73 insertions(+), 66 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Extract general code from qemuDomainReAttachHostScsiDevices to virHostdevDomainReAttachHostScsiDevices. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 41cda48..5e46a3d 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -328,27 +328,19 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, name, hostdevs, nhostdevs); } - -void -qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) +static void +virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) { size_t i; - virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; virObjectLock(hostdev_mgr->activeScsiHostdevs); for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; virSCSIDevicePtr scsi; virSCSIDevicePtr tmp; - virDomainDeviceDef dev; - - dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; - dev.data.hostdev = hostdev; - - ignore_value(qemuRemoveSharedDevice(driver, &dev, name)); if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) @@ -398,6 +390,28 @@ qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, } void +qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virDomainDeviceDef dev; + + dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; + dev.data.hostdev = hostdev; + + ignore_value(qemuRemoveSharedDevice(driver, &dev, name)); + } + + virHostdevReAttachScsiHostdevs(hostdev_mgr, name, hostdevs, nhostdevs); +} + +void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def) { -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:01PM +0800, Chunyan Liu wrote:
Extract general code from qemuDomainReAttachHostScsiDevices to virHostdevDomainReAttachHostScsiDevices.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 5e46a3d..b4ab1bd 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -330,6 +330,7 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, static void virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) @@ -383,7 +384,7 @@ virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, hostdev->source.subsys.u.scsi.unit, name); - virSCSIDeviceListDel(hostdev_mgr->activeScsiHostdevs, tmp, QEMU_DRIVER_NAME, name); + virSCSIDeviceListDel(hostdev_mgr->activeScsiHostdevs, tmp, drv_name, name); virSCSIDeviceFree(scsi); } virObjectUnlock(hostdev_mgr->activeScsiHostdevs); @@ -408,7 +409,8 @@ qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, ignore_value(qemuRemoveSharedDevice(driver, &dev, name)); } - virHostdevReAttachScsiHostdevs(hostdev_mgr, name, hostdevs, nhostdevs); + virHostdevReAttachScsiHostdevs(hostdev_mgr, QEMU_DRIVER_NAME, + name, hostdevs, nhostdevs); } void -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:02PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_hostdev.c | 62 ------------------------------------------------ src/util/virhostdev.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 6 +++++ 4 files changed, 69 insertions(+), 62 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ed23337..0a4f341 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1298,6 +1298,7 @@ virHostdevPreparePCIDevices; virHostdevPrepareSCSIDevices; virHostdevPrepareUSBDevices; virHostdevReAttachPCIDevices; +virHostdevReAttachScsiHostdevs; virHostdevReAttachUsbHostdevs; virHostdevUpdateActivePciHostdevs; virHostdevUpdateActiveScsiHostdevs; diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index b4ab1bd..c83b95d 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -328,68 +328,6 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, name, hostdevs, nhostdevs); } -static void -virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) -{ - size_t i; - - virObjectLock(hostdev_mgr->activeScsiHostdevs); - for (i = 0; i < nhostdevs; i++) { - virDomainHostdevDefPtr hostdev = hostdevs[i]; - virSCSIDevicePtr scsi; - virSCSIDevicePtr tmp; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || - hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) - continue; - - if (!(scsi = virSCSIDeviceNew(NULL, - hostdev->source.subsys.u.scsi.adapter, - hostdev->source.subsys.u.scsi.bus, - hostdev->source.subsys.u.scsi.target, - hostdev->source.subsys.u.scsi.unit, - hostdev->readonly, - hostdev->shareable))) { - VIR_WARN("Unable to reattach SCSI device %s:%d:%d:%d on domain %s", - hostdev->source.subsys.u.scsi.adapter, - hostdev->source.subsys.u.scsi.bus, - hostdev->source.subsys.u.scsi.target, - hostdev->source.subsys.u.scsi.unit, - name); - continue; - } - - /* Only delete the devices which are marked as being used by @name, - * because qemuProcessStart could fail on the half way. */ - - if (!(tmp = virSCSIDeviceListFind(hostdev_mgr->activeScsiHostdevs, scsi))) { - VIR_WARN("Unable to find device %s:%d:%d:%d " - "in list of active SCSI devices", - hostdev->source.subsys.u.scsi.adapter, - hostdev->source.subsys.u.scsi.bus, - hostdev->source.subsys.u.scsi.target, - hostdev->source.subsys.u.scsi.unit); - virSCSIDeviceFree(scsi); - continue; - } - - VIR_DEBUG("Removing %s:%d:%d:%d dom=%s from activeScsiHostdevs", - hostdev->source.subsys.u.scsi.adapter, - hostdev->source.subsys.u.scsi.bus, - hostdev->source.subsys.u.scsi.target, - hostdev->source.subsys.u.scsi.unit, - name); - - virSCSIDeviceListDel(hostdev_mgr->activeScsiHostdevs, tmp, drv_name, name); - virSCSIDeviceFree(scsi); - } - virObjectUnlock(hostdev_mgr->activeScsiHostdevs); -} - void qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, const char *name, diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index e679e20..d9bfe43 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -1320,3 +1320,65 @@ virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, } virObjectUnlock(hostdev_mgr->activeUsbHostdevs); } + +void +virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i; + + virObjectLock(hostdev_mgr->activeScsiHostdevs); + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virSCSIDevicePtr scsi; + virSCSIDevicePtr tmp; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) + continue; + + if (!(scsi = virSCSIDeviceNew(NULL, + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit, + hostdev->readonly, + hostdev->shareable))) { + VIR_WARN("Unable to reattach SCSI device %s:%d:%d:%d on domain %s", + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit, + name); + continue; + } + + /* Only delete the devices which are marked as being used by @name, + * because qemuProcessStart could fail on the half way. */ + + if (!(tmp = virSCSIDeviceListFind(hostdev_mgr->activeScsiHostdevs, scsi))) { + VIR_WARN("Unable to find device %s:%d:%d:%d " + "in list of active SCSI devices", + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit); + virSCSIDeviceFree(scsi); + continue; + } + + VIR_DEBUG("Removing %s:%d:%d:%d dom=%s from activeScsiHostdevs", + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit, + name); + + virSCSIDeviceListDel(hostdev_mgr->activeScsiHostdevs, tmp, drv_name, name); + virSCSIDeviceFree(scsi); + } + virObjectUnlock(hostdev_mgr->activeScsiHostdevs); +} diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index 7bd5da1..809996c 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -84,6 +84,12 @@ virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs); +void +virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs); int virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, const char *drv_name, -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:03PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_hostdev.c | 62 ------------------------------------------------ src/util/virhostdev.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 6 +++++ 4 files changed, 69 insertions(+), 62 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_driver.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3d25d14..b980725 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11267,6 +11267,27 @@ out: } static int +virHostdevPciNodeDeviceDetach(virHostdevManagerPtr hostdev_mgr, + virPCIDevicePtr pci) +{ + int ret = -1; + + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); + + if (virPCIDeviceDetach(pci, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) { + goto out; + } + + ret = 0; +out: + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); + return ret; +} + +static int qemuNodeDeviceDetachFlags(virNodeDevicePtr dev, const char *driverName, unsigned int flags) @@ -11338,18 +11359,7 @@ qemuNodeDeviceDetachFlags(virNodeDevicePtr dev, goto cleanup; } - virObjectLock(hostdev_mgr->activePciHostdevs); - virObjectLock(hostdev_mgr->inactivePciHostdevs); - - if (virPCIDeviceDetach(pci, hostdev_mgr->activePciHostdevs, - hostdev_mgr->inactivePciHostdevs) < 0) { - goto out; - } - - ret = 0; -out: - virObjectUnlock(hostdev_mgr->inactivePciHostdevs); - virObjectUnlock(hostdev_mgr->activePciHostdevs); + ret = virHostdevPciNodeDeviceDetach(hostdev_mgr, pci); cleanup: virPCIDeviceFree(pci); virNodeDeviceDefFree(def); -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:04PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_driver.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_driver.c | 61 +++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b980725..3abcf5a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11374,34 +11374,11 @@ qemuNodeDeviceDettach(virNodeDevicePtr dev) } static int -qemuNodeDeviceReAttach(virNodeDevicePtr dev) +virHostdevPciNodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr, + virPCIDevicePtr pci) { - virQEMUDriverPtr driver = dev->conn->privateData; - virPCIDevicePtr pci = NULL; virPCIDevicePtr other; - unsigned domain = 0, bus = 0, slot = 0, function = 0; int ret = -1; - virNodeDeviceDefPtr def = NULL; - char *xml = NULL; - virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - - xml = virNodeDeviceGetXMLDesc(dev, 0); - if (!xml) - goto cleanup; - - def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); - if (!def) - goto cleanup; - - if (virNodeDeviceReAttachEnsureACL(dev->conn, def) < 0) - goto cleanup; - - if (qemuNodeDeviceGetPciInfo(def, &domain, &bus, &slot, &function) < 0) - goto cleanup; - - pci = virPCIDeviceNew(domain, bus, slot, function); - if (!pci) - goto cleanup; virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); @@ -11434,6 +11411,40 @@ qemuNodeDeviceReAttach(virNodeDevicePtr dev) out: virObjectUnlock(hostdev_mgr->inactivePciHostdevs); virObjectUnlock(hostdev_mgr->activePciHostdevs); + return ret; +} + +static int +qemuNodeDeviceReAttach(virNodeDevicePtr dev) +{ + virQEMUDriverPtr driver = dev->conn->privateData; + virPCIDevicePtr pci = NULL; + unsigned domain = 0, bus = 0, slot = 0, function = 0; + int ret = -1; + virNodeDeviceDefPtr def = NULL; + char *xml = NULL; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + xml = virNodeDeviceGetXMLDesc(dev, 0); + if (!xml) + goto cleanup; + + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + if (!def) + goto cleanup; + + if (virNodeDeviceReAttachEnsureACL(dev->conn, def) < 0) + goto cleanup; + + if (qemuNodeDeviceGetPciInfo(def, &domain, &bus, &slot, &function) < 0) + goto cleanup; + + pci = virPCIDeviceNew(domain, bus, slot, function); + if (!pci) + goto cleanup; + + ret = virHostdevPciNodeDeviceReAttach(hostdev_mgr, pci); + virPCIDeviceFree(pci); cleanup: virNodeDeviceDefFree(def); -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:05PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_driver.c | 61 +++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 25 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_driver.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3abcf5a..6b6a170 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11453,6 +11453,25 @@ cleanup: } static int +virHostdevPciNodeDeviceReset(virHostdevManagerPtr hostdev_mgr, + virPCIDevicePtr pci) +{ + int ret = -1; + + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); + if (virPCIDeviceReset(pci, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) + goto out; + + ret = 0; +out: + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); + return ret; +} + +static int qemuNodeDeviceReset(virNodeDevicePtr dev) { virQEMUDriverPtr driver = dev->conn->privateData; @@ -11481,16 +11500,8 @@ qemuNodeDeviceReset(virNodeDevicePtr dev) if (!pci) goto cleanup; - virObjectLock(hostdev_mgr->activePciHostdevs); - virObjectLock(hostdev_mgr->inactivePciHostdevs); - if (virPCIDeviceReset(pci, hostdev_mgr->activePciHostdevs, - hostdev_mgr->inactivePciHostdevs) < 0) - goto out; + ret = virHostdevPciNodeDeviceReset(hostdev_mgr, pci); - ret = 0; -out: - virObjectUnlock(hostdev_mgr->inactivePciHostdevs); - virObjectUnlock(hostdev_mgr->activePciHostdevs); virPCIDeviceFree(pci); cleanup: virNodeDeviceDefFree(def); -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:06PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_driver.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 3 ++ src/qemu/qemu_driver.c | 81 ------------------------------------------------ src/util/virhostdev.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 8 +++++ 4 files changed, 92 insertions(+), 81 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0a4f341..5bb529c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1294,6 +1294,9 @@ virHookPresent; #util/virhostdev.h virHostdevManagerGetDefault; +virHostdevPciNodeDeviceDetach; +virHostdevPciNodeDeviceReAttach; +virHostdevPciNodeDeviceReset; virHostdevPreparePCIDevices; virHostdevPrepareSCSIDevices; virHostdevPrepareUSBDevices; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 6b6a170..e0b92d2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11267,27 +11267,6 @@ out: } static int -virHostdevPciNodeDeviceDetach(virHostdevManagerPtr hostdev_mgr, - virPCIDevicePtr pci) -{ - int ret = -1; - - virObjectLock(hostdev_mgr->activePciHostdevs); - virObjectLock(hostdev_mgr->inactivePciHostdevs); - - if (virPCIDeviceDetach(pci, hostdev_mgr->activePciHostdevs, - hostdev_mgr->inactivePciHostdevs) < 0) { - goto out; - } - - ret = 0; -out: - virObjectUnlock(hostdev_mgr->inactivePciHostdevs); - virObjectUnlock(hostdev_mgr->activePciHostdevs); - return ret; -} - -static int qemuNodeDeviceDetachFlags(virNodeDevicePtr dev, const char *driverName, unsigned int flags) @@ -11374,47 +11353,6 @@ qemuNodeDeviceDettach(virNodeDevicePtr dev) } static int -virHostdevPciNodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr, - virPCIDevicePtr pci) -{ - virPCIDevicePtr other; - int ret = -1; - - virObjectLock(hostdev_mgr->activePciHostdevs); - virObjectLock(hostdev_mgr->inactivePciHostdevs); - other = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, pci); - if (other) { - const char *other_drvname = NULL; - const char *other_domname = NULL; - virPCIDeviceGetUsedBy(other, &other_drvname, &other_domname); - - if (other_drvname && other_domname) - virReportError(VIR_ERR_OPERATION_INVALID, - _("PCI device %s is still in use by " - "driver %s, domain %s"), - virPCIDeviceGetName(pci), - other_drvname, other_domname); - else - virReportError(VIR_ERR_OPERATION_INVALID, - _("PCI device %s is still in use"), - virPCIDeviceGetName(pci)); - goto out; - } - - virPCIDeviceReattachInit(pci); - - if (virPCIDeviceReattach(pci, hostdev_mgr->activePciHostdevs, - hostdev_mgr->inactivePciHostdevs) < 0) - goto out; - - ret = 0; -out: - virObjectUnlock(hostdev_mgr->inactivePciHostdevs); - virObjectUnlock(hostdev_mgr->activePciHostdevs); - return ret; -} - -static int qemuNodeDeviceReAttach(virNodeDevicePtr dev) { virQEMUDriverPtr driver = dev->conn->privateData; @@ -11453,25 +11391,6 @@ cleanup: } static int -virHostdevPciNodeDeviceReset(virHostdevManagerPtr hostdev_mgr, - virPCIDevicePtr pci) -{ - int ret = -1; - - virObjectLock(hostdev_mgr->activePciHostdevs); - virObjectLock(hostdev_mgr->inactivePciHostdevs); - if (virPCIDeviceReset(pci, hostdev_mgr->activePciHostdevs, - hostdev_mgr->inactivePciHostdevs) < 0) - goto out; - - ret = 0; -out: - virObjectUnlock(hostdev_mgr->inactivePciHostdevs); - virObjectUnlock(hostdev_mgr->activePciHostdevs); - return ret; -} - -static int qemuNodeDeviceReset(virNodeDevicePtr dev) { virQEMUDriverPtr driver = dev->conn->privateData; diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index d9bfe43..4302385 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -1382,3 +1382,84 @@ virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, } virObjectUnlock(hostdev_mgr->activeScsiHostdevs); } + +int +virHostdevPciNodeDeviceDetach(virHostdevManagerPtr hostdev_mgr, + virPCIDevicePtr pci) +{ + int ret = -1; + + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); + + if (virPCIDeviceDetach(pci, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) { + goto out; + } + + ret = 0; +out: + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); + return ret; +} + +int +virHostdevPciNodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr, + virPCIDevicePtr pci) +{ + virPCIDevicePtr other; + int ret = -1; + + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); + other = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, pci); + if (other) { + const char *other_drvname = NULL; + const char *other_domname = NULL; + virPCIDeviceGetUsedBy(other, &other_drvname, &other_domname); + + if (other_drvname && other_domname) + virReportError(VIR_ERR_OPERATION_INVALID, + _("PCI device %s is still in use by " + "driver %s, domain %s"), + virPCIDeviceGetName(pci), + other_drvname, other_domname); + else + virReportError(VIR_ERR_OPERATION_INVALID, + _("PCI device %s is still in use"), + virPCIDeviceGetName(pci)); + goto out; + } + + virPCIDeviceReattachInit(pci); + + if (virPCIDeviceReattach(pci, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) + goto out; + + ret = 0; +out: + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); + return ret; +} + +int +virHostdevPciNodeDeviceReset(virHostdevManagerPtr hostdev_mgr, + virPCIDevicePtr pci) +{ + int ret = -1; + + virObjectLock(hostdev_mgr->activePciHostdevs); + virObjectLock(hostdev_mgr->inactivePciHostdevs); + if (virPCIDeviceReset(pci, hostdev_mgr->activePciHostdevs, + hostdev_mgr->inactivePciHostdevs) < 0) + goto out; + + ret = 0; +out: + virObjectUnlock(hostdev_mgr->inactivePciHostdevs); + virObjectUnlock(hostdev_mgr->activePciHostdevs); + return ret; +} diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index 809996c..a502cfc 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -103,4 +103,12 @@ virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, const char *drv_name, virDomainDefPtr def); +/* functions used by NodeDevDetach/Reattach/Reset */ +int virHostdevPciNodeDeviceDetach(virHostdevManagerPtr mgr, + virPCIDevicePtr pci); +int virHostdevPciNodeDeviceReAttach(virHostdevManagerPtr mgr, + virPCIDevicePtr pci); +int virHostdevPciNodeDeviceReset(virHostdevManagerPtr mgr, + virPCIDevicePtr pci); + #endif /* __VIR_HOSTDEV_H__ */ -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:07PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 3 ++ src/qemu/qemu_driver.c | 81 ------------------------------------------------ src/util/virhostdev.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 8 +++++ 4 files changed, 92 insertions(+), 81 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virhostdev.c | 44 +++++++++++++++++++++++--------------------- src/util/virhostdev.h | 12 ++++++------ 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 4302385..2c8bdf9 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -457,7 +457,7 @@ virHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, int virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, int nhostdevs, @@ -578,7 +578,7 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, activeDev = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, dev); if (activeDev) - virPCIDeviceSetUsedBy(activeDev, drv_name, name); + virPCIDeviceSetUsedBy(activeDev, drv_name, dom_name); } /* Loop 8: Now set the original states for hostdev def */ @@ -694,7 +694,7 @@ virHostdevReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) void virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs, char *oldStateDir) @@ -733,7 +733,7 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, const char *usedby_domname; virPCIDeviceGetUsedBy(activeDev, &usedby_drvname, &usedby_domname); if (STRNEQ_NULLABLE(drv_name, usedby_drvname) || - STRNEQ_NULLABLE(name, usedby_domname)) { + STRNEQ_NULLABLE(dom_name, usedby_domname)) { virPCIDeviceListDel(pcidevs, dev); continue; } @@ -931,7 +931,7 @@ cleanup: static int virHostdevMarkUsbHostdevs(virHostdevManagerPtr mgr, const char *drv_name, - const char *name, + const char *dom_name, virUSBDeviceListPtr list) { size_t i, j; @@ -961,9 +961,10 @@ virHostdevMarkUsbHostdevs(virHostdevManagerPtr mgr, goto error; } - virUSBDeviceSetUsedBy(usb, drv_name, name); + virUSBDeviceSetUsedBy(usb, drv_name, dom_name); VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs", - virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb), name); + virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb), + dom_name); /* * The caller is responsible to steal these usb devices * from the virUSBDeviceList that passed in on success, @@ -1076,7 +1077,7 @@ out: int virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs, unsigned int flags) @@ -1121,11 +1122,11 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, } } - /* Mark devices in temporary list as used by @name + /* Mark devices in temporary list as used by @dom_name * and add them do driver list. However, if something goes * wrong, perform rollback. */ - if (virHostdevMarkUsbHostdevs(hostdev_mgr, drv_name, name, list) < 0) + if (virHostdevMarkUsbHostdevs(hostdev_mgr, drv_name, dom_name, list) < 0) goto cleanup; /* Loop 2: Temporary list was successfully merged with @@ -1147,7 +1148,7 @@ cleanup: int virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) { @@ -1217,10 +1218,10 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, goto error; } - if (virSCSIDeviceSetUsedBy(tmp, drv_name, name) < 0) + if (virSCSIDeviceSetUsedBy(tmp, drv_name, dom_name) < 0) goto error; } else { - if (virSCSIDeviceSetUsedBy(scsi, drv_name, name) < 0) + if (virSCSIDeviceSetUsedBy(scsi, drv_name, dom_name) < 0) goto error; VIR_DEBUG("Adding %s to activeScsiHostdevs", virSCSIDeviceGetName(scsi)); @@ -1258,7 +1259,7 @@ cleanup: void virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) { @@ -1286,7 +1287,7 @@ virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device, - name); + dom_name); continue; } @@ -1309,11 +1310,11 @@ virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, virUSBDeviceGetUsedBy(tmp, &usedby_drvname, &usedby_domname); if (STREQ_NULLABLE(drv_name, usedby_drvname) && - STREQ_NULLABLE(name, usedby_domname)) { + STREQ_NULLABLE(dom_name, usedby_domname)) { VIR_DEBUG("Removing %03d.%03d dom=%s from activeUsbHostdevs", hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device, - name); + dom_name); virUSBDeviceListDel(hostdev_mgr->activeUsbHostdevs, tmp); } @@ -1324,7 +1325,7 @@ virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, void virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) { @@ -1352,7 +1353,7 @@ virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, hostdev->source.subsys.u.scsi.bus, hostdev->source.subsys.u.scsi.target, hostdev->source.subsys.u.scsi.unit, - name); + dom_name); continue; } @@ -1375,9 +1376,10 @@ virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, hostdev->source.subsys.u.scsi.bus, hostdev->source.subsys.u.scsi.target, hostdev->source.subsys.u.scsi.unit, - name); + dom_name); - virSCSIDeviceListDel(hostdev_mgr->activeScsiHostdevs, tmp, drv_name, name); + virSCSIDeviceListDel(hostdev_mgr->activeScsiHostdevs, tmp, + drv_name, dom_name); virSCSIDeviceFree(scsi); } virObjectUnlock(hostdev_mgr->activeScsiHostdevs); diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index a502cfc..d28fb15 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -53,7 +53,7 @@ virHostdevManagerPtr virHostdevManagerGetDefault(void); int virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, int nhostdevs, @@ -61,33 +61,33 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, int virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs, unsigned int flags); int virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs); void virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs, char *oldStateDir); void virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs); void virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, const char *drv_name, - const char *name, + const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs); int -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:08PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virhostdev.c | 44 +++++++++++++++++++++++--------------------- src/util/virhostdev.h | 12 ++++++------ 2 files changed, 29 insertions(+), 27 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 8 ++++---- src/qemu/qemu_hostdev.c | 16 +++++++-------- src/util/virhostdev.c | 52 ++++++++++++++++++++++++------------------------ src/util/virhostdev.h | 40 ++++++++++++++++++------------------- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5bb529c..e7d9d56 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1297,10 +1297,10 @@ virHostdevManagerGetDefault; virHostdevPciNodeDeviceDetach; virHostdevPciNodeDeviceReAttach; virHostdevPciNodeDeviceReset; -virHostdevPreparePCIDevices; -virHostdevPrepareSCSIDevices; -virHostdevPrepareUSBDevices; -virHostdevReAttachPCIDevices; +virHostdevPreparePciHostdevs; +virHostdevPrepareScsiHostdevs; +virHostdevPrepareUsbHostdevs; +virHostdevReAttachPciHostdevs; virHostdevReAttachScsiHostdevs; virHostdevReAttachUsbHostdevs; virHostdevUpdateActivePciHostdevs; diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index c83b95d..6648b71 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -225,8 +225,8 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps)) goto out; - ret = virHostdevPreparePCIDevices(hostdev_mgr, QEMU_DRIVER_NAME, - name, uuid, hostdevs, + ret = virHostdevPreparePciHostdevs(hostdev_mgr, QEMU_DRIVER_NAME, + name, uuid, hostdevs, nhostdevs, flags); out: return ret; @@ -241,8 +241,8 @@ qemuPrepareHostUSBDevices(virQEMUDriverPtr driver, { virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - return virHostdevPrepareUSBDevices(hostdev_mgr, QEMU_DRIVER_NAME, name, - hostdevs, nhostdevs, flags); + return virHostdevPrepareUsbHostdevs(hostdev_mgr, QEMU_DRIVER_NAME, name, + hostdevs, nhostdevs, flags); } int @@ -270,8 +270,8 @@ qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, return -1; } - return virHostdevPrepareSCSIDevices(hostdev_mgr, QEMU_DRIVER_NAME, - name, hostdevs, nhostdevs); + return virHostdevPrepareScsiHostdevs(hostdev_mgr, QEMU_DRIVER_NAME, + name, hostdevs, nhostdevs); } @@ -310,8 +310,8 @@ qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, char *oldStateDir = cfg->stateDir; virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - virHostdevReAttachPCIDevices(hostdev_mgr, QEMU_DRIVER_NAME, name, - hostdevs, nhostdevs, oldStateDir); + virHostdevReAttachPciHostdevs(hostdev_mgr, QEMU_DRIVER_NAME, name, + hostdevs, nhostdevs, oldStateDir); virObjectUnref(cfg); } diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 2c8bdf9..ab36e1f 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -455,13 +455,13 @@ virHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev, } int -virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *dom_name, - const unsigned char *uuid, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - unsigned int flags) +virHostdevPreparePciHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *dom_name, + const unsigned char *uuid, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + unsigned int flags) { virPCIDeviceListPtr pcidevs = NULL; int last_processed_hostdev_vf = -1; @@ -692,12 +692,12 @@ virHostdevReattachPciDevice(virPCIDevicePtr dev, virHostdevManagerPtr mgr) * For upgrade purpose: see virHostdevNetConfigRestore */ void -virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *dom_name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - char *oldStateDir) +virHostdevReAttachPciHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + char *oldStateDir) { virPCIDeviceListPtr pcidevs; size_t i; @@ -1075,12 +1075,12 @@ out: } int -virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *dom_name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - unsigned int flags) +virHostdevPrepareUsbHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + unsigned int flags) { size_t i; int ret = -1; @@ -1091,7 +1091,7 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, /* To prevent situation where USB device is assigned to two domains * we need to keep a list of currently assigned USB devices. * This is done in several loops which cannot be joined into one big - * loop. See virHostdevPreparePCIDevices() + * loop. See virHostdevPreparePciHostdevs() */ if (!(list = virUSBDeviceListNew())) goto cleanup; @@ -1146,11 +1146,11 @@ cleanup: } int -virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *dom_name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs) +virHostdevPrepareScsiHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) { size_t i, j; int count; @@ -1160,7 +1160,7 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, /* To prevent situation where SCSI device is assigned to two domains * we need to keep a list of currently assigned SCSI devices. * This is done in several loops which cannot be joined into one big - * loop. See virHostdevPreparePCIDevices() + * loop. See virHostdevPreparePciHostdevs() */ if (!(list = virSCSIDeviceListNew())) goto cleanup; diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index d28fb15..3fd38b5 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -51,33 +51,33 @@ struct _virHostdevManager { virHostdevManagerPtr virHostdevManagerGetDefault(void); int -virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *dom_name, - const unsigned char *uuid, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - unsigned int flags); -int -virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr, - const char *drv_name, - const char *dom_name, - virDomainHostdevDefPtr *hostdevs, - int nhostdevs, - unsigned int flags); -int -virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, +virHostdevPreparePciHostdevs(virHostdevManagerPtr hostdev_mgr, const char *drv_name, const char *dom_name, + const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, - int nhostdevs); -void -virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, + int nhostdevs, + unsigned int flags); +int +virHostdevPrepareUsbHostdevs(virHostdevManagerPtr hostdev_mgr, const char *drv_name, const char *dom_name, virDomainHostdevDefPtr *hostdevs, int nhostdevs, - char *oldStateDir); + unsigned int flags); +int +virHostdevPrepareScsiHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs); +void +virHostdevReAttachPciHostdevs(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, + char *oldStateDir); void virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, const char *drv_name, -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:09PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 8 ++++---- src/qemu/qemu_hostdev.c | 16 +++++++-------- src/util/virhostdev.c | 52 ++++++++++++++++++++++++------------------------ src/util/virhostdev.h | 40 ++++++++++++++++++------------------- 4 files changed, 58 insertions(+), 58 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5bb529c..e7d9d56 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1297,10 +1297,10 @@ virHostdevManagerGetDefault; virHostdevPciNodeDeviceDetach; virHostdevPciNodeDeviceReAttach; virHostdevPciNodeDeviceReset; -virHostdevPreparePCIDevices; -virHostdevPrepareSCSIDevices; -virHostdevPrepareUSBDevices; -virHostdevReAttachPCIDevices; +virHostdevPreparePciHostdevs; +virHostdevPrepareScsiHostdevs; +virHostdevPrepareUsbHostdevs; +virHostdevReAttachPciHostdevs; virHostdevReAttachScsiHostdevs; virHostdevReAttachUsbHostdevs; virHostdevUpdateActivePciHostdevs;
IMHO this is fixing the wrong side of the inconsistency. PCI, USB and SCSI are all abbreviations, so using capitalization is correct. We should instead fix the Pci, Usb and Scsi names. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

2014-03-12 23:12 GMT+08:00 Daniel P. Berrange <berrange@redhat.com>:
On Fri, Mar 07, 2014 at 06:53:09PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 8 ++++---- src/qemu/qemu_hostdev.c | 16 +++++++-------- src/util/virhostdev.c | 52 ++++++++++++++++++++++++------------------------ src/util/virhostdev.h | 40 ++++++++++++++++++------------------- 4 files changed, 58 insertions(+), 58 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5bb529c..e7d9d56 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1297,10 +1297,10 @@ virHostdevManagerGetDefault; virHostdevPciNodeDeviceDetach; virHostdevPciNodeDeviceReAttach; virHostdevPciNodeDeviceReset; -virHostdevPreparePCIDevices; -virHostdevPrepareSCSIDevices; -virHostdevPrepareUSBDevices; -virHostdevReAttachPCIDevices; +virHostdevPreparePciHostdevs; +virHostdevPrepareScsiHostdevs; +virHostdevPrepareUsbHostdevs; +virHostdevReAttachPciHostdevs; virHostdevReAttachScsiHostdevs; virHostdevReAttachUsbHostdevs; virHostdevUpdateActivePciHostdevs;
IMHO this is fixing the wrong side of the inconsistency.
PCI, USB and SCSI are all abbreviations, so using capitalization is correct. We should instead fix the Pci, Usb and Scsi names.
Thanks. I'll update.
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/:| |: http://libvirt.org -o- http://virt-manager.org:| |: http://autobuild.org -o- http://search.cpan.org/~danberr/:| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc:|

Changes parameter from vm def to specific hostdevs info and name info, so that it could be used more widely, e.g, could be used without full vm def info. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 9 ++++++--- src/util/virhostdev.c | 34 ++++++++++++++++++++-------------- src/util/virhostdev.h | 12 +++++++++--- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 6648b71..88907b1 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -50,7 +50,8 @@ qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, if (!def->nhostdevs) return 0; - return virHostdevUpdateActivePciHostdevs(mgr, QEMU_DRIVER_NAME, def); + return virHostdevUpdateActivePciHostdevs(mgr, def->hostdevs, def->nhostdevs, + QEMU_DRIVER_NAME, def->name); } int @@ -62,7 +63,8 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, if (!def->nhostdevs) return 0; - return virHostdevUpdateActiveUsbHostdevs(mgr, QEMU_DRIVER_NAME, def); + return virHostdevUpdateActiveUsbHostdevs(mgr, def->hostdevs, def->nhostdevs, + QEMU_DRIVER_NAME, def->name); } int @@ -74,7 +76,8 @@ qemuUpdateActiveScsiHostdevs(virQEMUDriverPtr driver, if (!def->nhostdevs) return 0; - return virHostdevUpdateActiveScsiHostdevs(mgr, QEMU_DRIVER_NAME, def); + return virHostdevUpdateActiveScsiHostdevs(mgr, def->hostdevs, def->nhostdevs, + QEMU_DRIVER_NAME, def->name); } diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index ab36e1f..5fddd8a 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -779,8 +779,10 @@ cleanup: int virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, const char *drv_name, - virDomainDefPtr def) + const char *dom_name) { virDomainHostdevDefPtr hostdev = NULL; virPCIDevicePtr dev = NULL; @@ -790,8 +792,8 @@ virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, virObjectLock(mgr->activePciHostdevs); virObjectLock(mgr->inactivePciHostdevs); - for (i = 0; i < def->nhostdevs; i++) { - hostdev = def->hostdevs[i]; + for (i = 0; i < nhostdevs; i++) { + hostdev = hostdevs[i]; if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) continue; @@ -816,7 +818,7 @@ virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, goto cleanup; } - virPCIDeviceSetUsedBy(dev, drv_name, def->name); + virPCIDeviceSetUsedBy(dev, drv_name, dom_name); /* Setup the original states for the PCI device */ virPCIDeviceSetUnbindFromStub(dev, hostdev->origstates.states.pci.unbind_from_stub); @@ -838,17 +840,19 @@ cleanup: int virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, const char *drv_name, - virDomainDefPtr def) + const char *dom_name) { virDomainHostdevDefPtr hostdev = NULL; size_t i; int ret = -1; virObjectLock(mgr->activeUsbHostdevs); - for (i = 0; i < def->nhostdevs; i++) { + for (i = 0; i < nhostdevs; i++) { virUSBDevicePtr usb = NULL; - hostdev = def->hostdevs[i]; + hostdev = hostdevs[i]; if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) continue; @@ -862,11 +866,11 @@ virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device, - def->name); + dom_name); continue; } - virUSBDeviceSetUsedBy(usb, drv_name, def->name); + virUSBDeviceSetUsedBy(usb, drv_name, dom_name); if (virUSBDeviceListAdd(mgr->activeUsbHostdevs, usb) < 0) { virUSBDeviceFree(usb); @@ -881,8 +885,10 @@ cleanup: int virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, const char *drv_name, - virDomainDefPtr def) + const char *dom_name) { virDomainHostdevDefPtr hostdev = NULL; size_t i; @@ -891,8 +897,8 @@ virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, virSCSIDevicePtr tmp = NULL; virObjectLock(mgr->activeScsiHostdevs); - for (i = 0; i < def->nhostdevs; i++) { - hostdev = def->hostdevs[i]; + for (i = 0; i < nhostdevs; i++) { + hostdev = hostdevs[i]; if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) @@ -908,13 +914,13 @@ virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, goto cleanup; if ((tmp = virSCSIDeviceListFind(mgr->activeScsiHostdevs, scsi))) { - if (virSCSIDeviceSetUsedBy(tmp, drv_name, def->name) < 0) { + if (virSCSIDeviceSetUsedBy(tmp, drv_name, dom_name) < 0) { virSCSIDeviceFree(scsi); goto cleanup; } virSCSIDeviceFree(scsi); } else { - if (virSCSIDeviceSetUsedBy(scsi, drv_name, def->name) < 0 || + if (virSCSIDeviceSetUsedBy(scsi, drv_name, dom_name) < 0 || virSCSIDeviceListAdd(mgr->activeScsiHostdevs, scsi) < 0) { virSCSIDeviceFree(scsi); goto cleanup; diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index 3fd38b5..8680e5d 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -92,16 +92,22 @@ virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, int nhostdevs); int virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, const char *drv_name, - virDomainDefPtr def); + const char *dom_name); int virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, const char *drv_name, - virDomainDefPtr def); + const char *dom_name); int virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs, const char *drv_name, - virDomainDefPtr def); + const char *dom_name); /* functions used by NodeDevDetach/Reattach/Reset */ int virHostdevPciNodeDeviceDetach(virHostdevManagerPtr mgr, -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:10PM +0800, Chunyan Liu wrote:
Changes parameter from vm def to specific hostdevs info and name info, so that it could be used more widely, e.g, could be used without full vm def info.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/qemu/qemu_hostdev.c | 9 ++++++--- src/util/virhostdev.c | 34 ++++++++++++++++++++-------------- src/util/virhostdev.h | 12 +++++++++--- 3 files changed, 35 insertions(+), 20 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 4 ++ src/util/virhostdev.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 20 +++++++++ 3 files changed, 127 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e7d9d56..4b42cbb 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1297,15 +1297,19 @@ virHostdevManagerGetDefault; virHostdevPciNodeDeviceDetach; virHostdevPciNodeDeviceReAttach; virHostdevPciNodeDeviceReset; +virHostdevPrepareDomainHostdevs; virHostdevPreparePciHostdevs; virHostdevPrepareScsiHostdevs; virHostdevPrepareUsbHostdevs; +virHostdevReAttachDomainHostdevs; virHostdevReAttachPciHostdevs; virHostdevReAttachScsiHostdevs; virHostdevReAttachUsbHostdevs; virHostdevUpdateActivePciHostdevs; virHostdevUpdateActiveScsiHostdevs; virHostdevUpdateActiveUsbHostdevs; +virHostdevUpdateDomainActiveHostdevs; + # util/viridentity.h virIdentityGetAttr; diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 5fddd8a..577de48 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -1471,3 +1471,106 @@ out: virObjectUnlock(hostdev_mgr->activePciHostdevs); return ret; } + +int +virHostdevPrepareDomainHostdevs(virHostdevManagerPtr mgr, + const char *driver, + virDomainDefPtr def, + unsigned int flags) +{ + if (!def->nhostdevs) + return 0; + + if (mgr == NULL) + return -1; + + if (flags & VIR_HOSTDEV_SP_PCI) { + if (virHostdevPreparePciHostdevs(mgr, driver, + def->name, def->uuid, + def->hostdevs, + def->nhostdevs, + flags) < 0) + return -1; + } + + if (flags & VIR_HOSTDEV_SP_USB) { + if (virHostdevPrepareUsbHostdevs(mgr, driver, def->name, + def->hostdevs, def->nhostdevs, + flags) < 0) + return -1; + } + + if (flags & VIR_HOSTDEV_SP_SCSI) { + if (virHostdevPrepareScsiHostdevs(mgr, driver, def->name, + def->hostdevs, def->nhostdevs) < 0) + return -1; + } + + return 0; +} + +/* @oldStateDir + * For upgrade purpose: see virHostdevReAttachPciHostdevs + */ +void +virHostdevReAttachDomainHostdevs(virHostdevManagerPtr mgr, + const char *driver, + virDomainDefPtr def, + unsigned int flags, + char *oldStateDir) +{ + if (!def->nhostdevs || !mgr) + return; + + if (flags & VIR_HOSTDEV_SP_PCI) { + virHostdevReAttachPciHostdevs(mgr, driver, def->name, + def->hostdevs, def->nhostdevs, + oldStateDir); + } + + if (flags & VIR_HOSTDEV_SP_USB) { + virHostdevReAttachUsbHostdevs(mgr, driver, def->name, + def->hostdevs, def->nhostdevs); + } + + if (flags & VIR_HOSTDEV_SP_SCSI) { + virHostdevReAttachScsiHostdevs(mgr, driver, def->name, + def->hostdevs, def->nhostdevs); + } +} + +int +virHostdevUpdateDomainActiveHostdevs(virHostdevManagerPtr mgr, + const char *driver, + virDomainDefPtr def, + unsigned int flags) +{ + if (!def->nhostdevs) + return 0; + + if (flags & VIR_HOSTDEV_SP_PCI) { + if (virHostdevUpdateActivePciHostdevs(mgr, + def->hostdevs, + def->nhostdevs, + driver, def->name) < 0) + return -1; + } + + if (flags & VIR_HOSTDEV_SP_USB) { + if (virHostdevUpdateActiveUsbHostdevs(mgr, + def->hostdevs, + def->nhostdevs, + driver, def->name) < 0) + return -1; + } + + if (flags & VIR_HOSTDEV_SP_SCSI) { + if (virHostdevUpdateActiveScsiHostdevs(mgr, + def->hostdevs, + def->nhostdevs, + driver, def->name) < 0) + return -1; + } + + return 0; +} diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index 8680e5d..820b408 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -35,6 +35,10 @@ typedef enum { VIR_HOSTDEV_STRICT_ACS_CHECK = (1 << 0), /* strict acs check */ VIR_HOSTDEV_COLD_BOOT = (1 << 1), /* cold boot */ + + VIR_HOSTDEV_SP_PCI = (1 << 8), /* support pci passthrough */ + VIR_HOSTDEV_SP_USB = (1 << 9), /* support usb passthrough */ + VIR_HOSTDEV_SP_SCSI = (1 << 10), /* support scsi passthrough */ } virHostdevFlag; @@ -108,6 +112,22 @@ virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, int nhostdevs, const char *drv_name, const char *dom_name); +int +virHostdevUpdateDomainActiveHostdevs(virHostdevManagerPtr mgr, + const char *driver, + virDomainDefPtr def, + unsigned int flags); +int +virHostdevPrepareDomainHostdevs(virHostdevManagerPtr mgr, + const char *driver, + virDomainDefPtr def, + unsigned int flags); +void +virHostdevReAttachDomainHostdevs(virHostdevManagerPtr mgr, + const char *driver, + virDomainDefPtr def, + unsigned int flags, + char *oldStateDir); /* functions used by NodeDevDetach/Reattach/Reset */ int virHostdevPciNodeDeviceDetach(virHostdevManagerPtr mgr, -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:11PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libvirt_private.syms | 4 ++ src/util/virhostdev.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virhostdev.h | 20 +++++++++ 3 files changed, 127 insertions(+)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Check NULL parameter inputs Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virhostdev.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 577de48..5f61bfc 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -468,6 +468,11 @@ virHostdevPreparePciHostdevs(virHostdevManagerPtr hostdev_mgr, size_t i; int ret = -1; + if (!nhostdevs) + return 0; + if (hostdev_mgr == NULL) + return -1; + virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); @@ -702,6 +707,11 @@ virHostdevReAttachPciHostdevs(virHostdevManagerPtr hostdev_mgr, virPCIDeviceListPtr pcidevs; size_t i; + if (!nhostdevs) + return; + if (hostdev_mgr == NULL) + return; + virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); @@ -789,6 +799,11 @@ virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, size_t i; int ret = -1; + if (!nhostdevs) + return 0; + if (mgr == NULL) + return -1; + virObjectLock(mgr->activePciHostdevs); virObjectLock(mgr->inactivePciHostdevs); @@ -849,6 +864,11 @@ virHostdevUpdateActiveUsbHostdevs(virHostdevManagerPtr mgr, size_t i; int ret = -1; + if (!nhostdevs) + return 0; + if (mgr == NULL) + return -1; + virObjectLock(mgr->activeUsbHostdevs); for (i = 0; i < nhostdevs; i++) { virUSBDevicePtr usb = NULL; @@ -896,6 +916,11 @@ virHostdevUpdateActiveScsiHostdevs(virHostdevManagerPtr mgr, virSCSIDevicePtr scsi = NULL; virSCSIDevicePtr tmp = NULL; + if (!nhostdevs) + return 0; + if (mgr == NULL) + return -1; + virObjectLock(mgr->activeScsiHostdevs); for (i = 0; i < nhostdevs; i++) { hostdev = hostdevs[i]; @@ -1094,6 +1119,11 @@ virHostdevPrepareUsbHostdevs(virHostdevManagerPtr hostdev_mgr, virUSBDevicePtr tmp; bool coldBoot = !!(flags & VIR_HOSTDEV_COLD_BOOT); + if (!nhostdevs) + return 0; + if (hostdev_mgr == NULL) + return -1; + /* To prevent situation where USB device is assigned to two domains * we need to keep a list of currently assigned USB devices. * This is done in several loops which cannot be joined into one big @@ -1163,6 +1193,11 @@ virHostdevPrepareScsiHostdevs(virHostdevManagerPtr hostdev_mgr, virSCSIDeviceListPtr list; virSCSIDevicePtr tmp; + if (!nhostdevs) + return 0; + if (hostdev_mgr == NULL) + return -1; + /* To prevent situation where SCSI device is assigned to two domains * we need to keep a list of currently assigned SCSI devices. * This is done in several loops which cannot be joined into one big @@ -1271,6 +1306,11 @@ virHostdevReAttachUsbHostdevs(virHostdevManagerPtr hostdev_mgr, { size_t i; + if (!nhostdevs) + return; + if (hostdev_mgr == NULL) + return; + virObjectLock(hostdev_mgr->activeUsbHostdevs); for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; @@ -1337,6 +1377,11 @@ virHostdevReAttachScsiHostdevs(virHostdevManagerPtr hostdev_mgr, { size_t i; + if (!nhostdevs) + return; + if (hostdev_mgr == NULL) + return; + virObjectLock(hostdev_mgr->activeScsiHostdevs); for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; @@ -1397,6 +1442,9 @@ virHostdevPciNodeDeviceDetach(virHostdevManagerPtr hostdev_mgr, { int ret = -1; + if (hostdev_mgr == NULL || pci == NULL) + return -1; + virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); @@ -1419,6 +1467,9 @@ virHostdevPciNodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr, virPCIDevicePtr other; int ret = -1; + if (hostdev_mgr == NULL || pci == NULL) + return -1; + virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); other = virPCIDeviceListFind(hostdev_mgr->activePciHostdevs, pci); @@ -1459,6 +1510,9 @@ virHostdevPciNodeDeviceReset(virHostdevManagerPtr hostdev_mgr, { int ret = -1; + if (hostdev_mgr == NULL || pci == NULL) + return -1; + virObjectLock(hostdev_mgr->activePciHostdevs); virObjectLock(hostdev_mgr->inactivePciHostdevs); if (virPCIDeviceReset(pci, hostdev_mgr->activePciHostdevs, @@ -1548,6 +1602,9 @@ virHostdevUpdateDomainActiveHostdevs(virHostdevManagerPtr mgr, if (!def->nhostdevs) return 0; + if (mgr == NULL) + return -1; + if (flags & VIR_HOSTDEV_SP_PCI) { if (virHostdevUpdateActivePciHostdevs(mgr, def->hostdevs, -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:12PM +0800, Chunyan Liu wrote:
Check NULL parameter inputs
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virhostdev.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 577de48..5f61bfc 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -468,6 +468,11 @@ virHostdevPreparePciHostdevs(virHostdevManagerPtr hostdev_mgr, size_t i; int ret = -1;
+ if (!nhostdevs) + return 0;
This is reasonable because it is an expected case.
+ if (hostdev_mgr == NULL) + return -1;
This is something that should never happen except by programmer error, since this is allocated right at libvirtd startup and then never changed thereafter. It is preferrable to use ATTRIBUTE_NONNULL() in the header file for these kind of things. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

2014-03-12 23:11 GMT+08:00 Daniel P. Berrange <berrange@redhat.com>:
On Fri, Mar 07, 2014 at 06:53:12PM +0800, Chunyan Liu wrote:
Check NULL parameter inputs
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/util/virhostdev.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 577de48..5f61bfc 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -468,6 +468,11 @@ virHostdevPreparePciHostdevs(virHostdevManagerPtr hostdev_mgr, size_t i; int ret = -1;
+ if (!nhostdevs) + return 0;
This is reasonable because it is an expected case.
+ if (hostdev_mgr == NULL) + return -1;
This is something that should never happen except by programmer error, since this is allocated right at libvirtd startup and then never changed thereafter.
It is preferrable to use ATTRIBUTE_NONNULL() in the header file for these kind of things.
Will update.
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/:| |: http://libvirt.org -o- http://virt-manager.org:| |: http://autobuild.org -o- http://search.cpan.org/~danberr/:| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc:|

Add unit test for hostdev common library. Current tests are based on virpcimock. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- .gitignore | 1 + tests/Makefile.am | 5 + tests/virhostdevtest.c | 507 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 513 insertions(+) create mode 100644 tests/virhostdevtest.c diff --git a/.gitignore b/.gitignore index cb60734..56d9414 100644 --- a/.gitignore +++ b/.gitignore @@ -203,6 +203,7 @@ /tests/virendiantest /tests/virfiletest /tests/virhashtest +/tests/virhostdevtest /tests/viridentitytest /tests/virkeycodetest /tests/virkeyfiletest diff --git a/tests/Makefile.am b/tests/Makefile.am index cd91734..c601030 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -150,6 +150,7 @@ test_programs = virshtest sockettest \ virkmodtest \ vircapstest \ domainconftest \ + virhostdevtest \ $(NULL) if WITH_REMOTE @@ -812,6 +813,10 @@ vircgroupmock_la_CFLAGS = $(AM_CFLAGS) vircgroupmock_la_LDFLAGS = -module -avoid-version \ -rpath /evil/libtool/hack/to/force/shared/lib/creation +virhostdevtest_SOURCES = \ + virhostdevtest.c testutils.h testutils.c +virhostdevtest_LDADD = $(LDADDS) + virpcitest_SOURCES = \ virpcitest.c testutils.h testutils.c virpcitest_LDADD = $(LDADDS) diff --git a/tests/virhostdevtest.c b/tests/virhostdevtest.c new file mode 100644 index 0000000..f6d7e1d --- /dev/null +++ b/tests/virhostdevtest.c @@ -0,0 +1,507 @@ +/* + * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Chunyan Liu <cyliu@suse.com> + */ + +#include <config.h> + +#include "testutils.h" + +#ifdef __linux__ + +# include <stdlib.h> +# include <stdio.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <sys/ioctl.h> +# include <fcntl.h> +# include "virlog.h" +# include "virhostdev.h" + +# define VIR_FROM_THIS VIR_FROM_NONE + +# define CHECK_LIST_COUNT(list, cnt) \ + if ((count = virPCIDeviceListCount(list)) != cnt) { \ + virReportError(VIR_ERR_INTERNAL_ERROR, \ + "Unexpected count of items in " #list ": %d, " \ + "expecting %zu", count, (size_t) cnt); \ + goto cleanup; \ + } + +# define TEST_STATE_DIR abs_builddir "/hostdevmgr" +static const char *drv_name = "test_driver"; +static const char *dom_name = "test_domain"; +static const unsigned char *uuid = + (unsigned char *)("f92360b0-2541-8791-fb32-d1f838811541"); +static int nhostdevs = 3; +static virDomainHostdevDefPtr hostdevs[] = {NULL, NULL, NULL}; +static virPCIDevicePtr dev[] = {NULL, NULL, NULL}; +static virHostdevManagerPtr mgr = NULL; + +static void +myCleanup(void) +{ + size_t i; + for (i = 0; i < nhostdevs; i++) { + virPCIDeviceFree(dev[i]); + virDomainHostdevDefFree(hostdevs[i]); + } + + if (mgr) { + virObjectUnref(mgr->activePciHostdevs); + virObjectUnref(mgr->inactivePciHostdevs); + virObjectUnref(mgr->activeUsbHostdevs); + VIR_FREE(mgr->stateDir); + VIR_FREE(mgr); + } +} + +static int +myInit(void) +{ + size_t i; + + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevSubsys subsys; + hostdevs[i] = virDomainHostdevDefAlloc(); + if (!hostdevs[i]) + goto cleanup; + hostdevs[i]->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; + subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI; + subsys.u.pci.addr.domain = 0; + subsys.u.pci.addr.bus = 0; + subsys.u.pci.addr.slot = i + 1; + subsys.u.pci.addr.function = 0; + subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM; + hostdevs[i]->source.subsys = subsys; + } + + for (i = 0; i < nhostdevs; i++) { + if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0)) || + virPCIDeviceSetStubDriver(dev[i], "pci-stub") < 0) + goto cleanup; + } + + if (VIR_ALLOC(mgr) < 0) + goto cleanup; + if ((mgr->activePciHostdevs = virPCIDeviceListNew()) == NULL) + goto cleanup; + if ((mgr->activeUsbHostdevs = virUSBDeviceListNew()) == NULL) + goto cleanup; + if ((mgr->inactivePciHostdevs = virPCIDeviceListNew()) == NULL) + goto cleanup; + if ((mgr->activeScsiHostdevs = virSCSIDeviceListNew()) == NULL) + goto cleanup; + if (VIR_STRDUP(mgr->stateDir, TEST_STATE_DIR) < 0) + goto cleanup; + if (virFileMakePath(mgr->stateDir) < 0) + goto cleanup; + + return 0; + +cleanup: + myCleanup(); + return -1; +} + +# if HAVE_LINUX_KVM_H +# include <linux/kvm.h> +static bool +virHostdevHostSupportsPassthroughKVM(void) +{ + int kvmfd = -1; + bool ret = false; + + if ((kvmfd = open("/dev/kvm", O_RDONLY)) < 0) + goto cleanup; + +# ifdef KVM_CAP_IOMMU + if ((ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_IOMMU)) <= 0) + goto cleanup; + + ret = true; +# endif + +cleanup: + VIR_FORCE_CLOSE(kvmfd); + + return ret; +} +# else +static bool +virHostdevHostSupportsPassthroughKVM(void) +{ + return false; +} +# endif + +static int +testVirHostdevPreparePciHostdevs_unmanaged(const void *oaque ATTRIBUTE_UNUSED) +{ + int ret = -1; + size_t i; + int count, count1, count2; + + for (i = 0; i < nhostdevs; i++) + hostdevs[i]->managed = false; + + /* Test invalid args */ + VIR_DEBUG("Test hostdev mgr=NULL\n"); + if (!virHostdevPreparePciHostdevs(NULL, drv_name, dom_name, uuid, + hostdevs, nhostdevs, 0)) + goto cleanup; + + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); + count2 = virPCIDeviceListCount(mgr->inactivePciHostdevs); + + /* Test normal functionality */ + VIR_DEBUG("Test 0 hostdevs\n"); + if (virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, + NULL, 0, 0) < 0) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + + /* Test unmanaged hostdevs */ + VIR_DEBUG("Test >=1 unmanaged hostdevs\n"); + if (virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, + hostdevs, nhostdevs, 0) < 0) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 + 3); + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2 - 3); + + /* Test conflict */ + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); + count2 = virPCIDeviceListCount(mgr->inactivePciHostdevs); + VIR_DEBUG("Test: prepare same hostdevs for same driver/domain again\n"); + if (!virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, + &hostdevs[0], 1, 0)) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2); + + VIR_DEBUG("Test: prepare same hostdevs for same driver, diff domain again\n"); + if (!virHostdevPreparePciHostdevs(mgr, drv_name, "test_domain1", uuid, + &hostdevs[1], 1, 0)) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2); + + VIR_DEBUG("Test: prepare same hostdevs for diff driver/domain again\n"); + if (!virHostdevPreparePciHostdevs(mgr, "test_driver1", dom_name, uuid, + &hostdevs[2], 1, 0)) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2); + + ret = 0; + +cleanup: + return ret; + +} + +static int +testVirHostdevReAttachPciHostdevs_unmanaged(const void *oaque ATTRIBUTE_UNUSED) +{ + int ret = -1; + size_t i; + int count, count1, count2; + + for (i = 0; i < nhostdevs; i++) { + if (hostdevs[i]->managed != false) { + VIR_DEBUG("invalid test\n"); + return -1; + } + } + + VIR_DEBUG("Test hostdev mgr=NULL\n"); + virHostdevReAttachPciHostdevs(NULL, drv_name, dom_name, + hostdevs, nhostdevs, NULL); + + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); + count2 = virPCIDeviceListCount(mgr->inactivePciHostdevs); + + VIR_DEBUG("Test 0 hostdevs\n"); + virHostdevReAttachPciHostdevs(mgr, drv_name, dom_name, NULL, 0, NULL); + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + + VIR_DEBUG("Test >=1 unmanaged hostdevs\n"); + virHostdevReAttachPciHostdevs(mgr, drv_name, dom_name, + hostdevs, nhostdevs, NULL); + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 - 3); + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2 + 3); + + ret = 0; + +cleanup: + return ret; + +} + +static int +testVirHostdevPreparePciHostdevs_managed(const void *oaque ATTRIBUTE_UNUSED) +{ + int ret = -1; + size_t i; + int count, count1; + + for (i = 0; i < nhostdevs; i++) + hostdevs[i]->managed = true; + + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); + + /* Test normal functionality */ + VIR_DEBUG("Test >=1 hostdevs\n"); + if (virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, + hostdevs, nhostdevs, 0) < 0) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 + 3); + + /* Test conflict */ + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); + VIR_DEBUG("Test: prepare same hostdevs for same driver/domain again\n"); + if (!virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, + &hostdevs[0], 1, 0)) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + + VIR_DEBUG("Test: prepare same hostdevs for same driver, diff domain again\n"); + if (!virHostdevPreparePciHostdevs(mgr, drv_name, "test_domain1", uuid, + &hostdevs[1], 1, 0)) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + + VIR_DEBUG("Test: prepare same hostdevs for diff driver/domain again\n"); + if (!virHostdevPreparePciHostdevs(mgr, "test_driver1", dom_name, uuid, + &hostdevs[2], 1, 0)) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + + ret = 0; + +cleanup: + return ret; + +} + +static int +testVirHostdevReAttachPciHostdevs_managed(const void *oaque ATTRIBUTE_UNUSED) +{ + int ret = -1; + size_t i; + int count, count1; + + for (i = 0; i < nhostdevs; i++) { + if (hostdevs[i]->managed != true) { + VIR_DEBUG("invalid test\n"); + return -1; + } + } + + VIR_DEBUG("Test hostdev mgr=NULL\n"); + virHostdevReAttachPciHostdevs(NULL, drv_name, dom_name, + hostdevs, nhostdevs, NULL); + + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); + + VIR_DEBUG("Test 0 hostdevs\n"); + virHostdevReAttachPciHostdevs(mgr, drv_name, dom_name, NULL, 0, NULL); + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + + VIR_DEBUG("Test >=1 hostdevs\n"); + virHostdevReAttachPciHostdevs(mgr, drv_name, dom_name, + hostdevs, nhostdevs, NULL); + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 - 3); + + ret = 0; + +cleanup: + return ret; + +} + +static int +testVirHostdevDetachPciNodeDevice(const void *oaque ATTRIBUTE_UNUSED) +{ + int ret = -1; + size_t i; + int count, count1; + + if (!virHostdevPciNodeDeviceDetach(NULL, dev[0])) + goto cleanup; + + if (!virHostdevPciNodeDeviceDetach(mgr, NULL)) + goto cleanup; + + for (i = 0; i < nhostdevs; i++) { + count1 = virPCIDeviceListCount(mgr->inactivePciHostdevs); + if (virHostdevPciNodeDeviceDetach(mgr, dev[i]) < 0) + goto cleanup; + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count1 + 1); + } + + ret = 0; + +cleanup: + return ret; +} +static int +testVirHostdevResetPciNodeDevice(const void *oaque ATTRIBUTE_UNUSED) +{ + int ret = -1; + size_t i; + + if (!virHostdevPciNodeDeviceReset(NULL, dev[0])) + goto cleanup; + + if (!virHostdevPciNodeDeviceReAttach(mgr, NULL)) + goto cleanup; + + for (i = 0; i < nhostdevs; i++) { + if (virHostdevPciNodeDeviceReset(mgr, dev[i]) < 0) + goto cleanup; + } + + ret = 0; + +cleanup: + return ret; + +} + +static int +testVirHostdevReAttachPciNodeDevice(const void *oaque ATTRIBUTE_UNUSED) +{ + int ret = -1; + size_t i; + int count, count1; + + if (!virHostdevPciNodeDeviceReAttach(NULL, dev[0])) + goto cleanup; + + if (!virHostdevPciNodeDeviceReAttach(mgr, NULL)) + goto cleanup; + + for (i = 0; i < nhostdevs; i++) { + count1 = virPCIDeviceListCount(mgr->inactivePciHostdevs); + if (virHostdevPciNodeDeviceReAttach(mgr, dev[i]) < 0) + goto cleanup; + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count1 - 1); + } + + ret = 0; + +cleanup: + return ret; + +} + +static int +testVirHostdevUpdateActivePciHostdevs(const void *oaque ATTRIBUTE_UNUSED) +{ + int ret = -1; + int count, count1; + + VIR_DEBUG("Test hostdev mgr=NULL\n"); + if (!virHostdevUpdateActivePciHostdevs(NULL, hostdevs, nhostdevs, + drv_name, dom_name)) + goto cleanup; + + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); + + VIR_DEBUG("Test 0 hostdevs\n"); + if (virHostdevUpdateActivePciHostdevs(mgr, NULL, 0, + drv_name, dom_name) < 0) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); + + VIR_DEBUG("Test >=1 hostdevs\n"); + if (virHostdevUpdateActivePciHostdevs(mgr, hostdevs, nhostdevs, + drv_name, dom_name) < 0) + goto cleanup; + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 + 3); + + ret = 0; + +cleanup: + return ret; +} + +# define FAKESYSFSDIRTEMPLATE abs_builddir "/fakesysfsdir-XXXXXX" + +static int +mymain(void) +{ + int ret = 0; + char *fakesysfsdir; + + if (VIR_STRDUP_QUIET(fakesysfsdir, FAKESYSFSDIRTEMPLATE) < 0) { + fprintf(stderr, "Out of memory\n"); + abort(); + } + + if (!mkdtemp(fakesysfsdir)) { + fprintf(stderr, "Cannot create fakesysfsdir"); + abort(); + } + + setenv("LIBVIRT_FAKE_SYSFS_DIR", fakesysfsdir, 1); + +# define DO_TEST(fnc) \ + do { \ + VIR_DEBUG("\nTesting: %s", #fnc); \ + if (virtTestRun(#fnc, fnc, NULL) < 0) \ + ret = -1; \ + } while (0) + + if (myInit() < 0) + fprintf(stderr, "Init data structures failed."); + + DO_TEST(testVirHostdevDetachPciNodeDevice); + if (virHostdevHostSupportsPassthroughKVM()) { + /* following tests would check KVM support */ + DO_TEST(testVirHostdevPreparePciHostdevs_unmanaged); + DO_TEST(testVirHostdevReAttachPciHostdevs_unmanaged); + } + DO_TEST(testVirHostdevResetPciNodeDevice); + DO_TEST(testVirHostdevReAttachPciNodeDevice); + if (virHostdevHostSupportsPassthroughKVM()) { + /* following tests would check KVM support */ + DO_TEST(testVirHostdevPreparePciHostdevs_managed); + DO_TEST(testVirHostdevReAttachPciHostdevs_managed); + } + DO_TEST(testVirHostdevUpdateActivePciHostdevs); + + myCleanup(); + + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) + virFileDeleteTree(fakesysfsdir); + + VIR_FREE(fakesysfsdir); + + return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virpcimock.so") +#else +int +main(void) +{ + return EXIT_AM_SKIP; +} +#endif -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:13PM +0800, Chunyan Liu wrote:
Add unit test for hostdev common library. Current tests are based on virpcimock.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- .gitignore | 1 + tests/Makefile.am | 5 + tests/virhostdevtest.c | 507 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 513 insertions(+) create mode 100644 tests/virhostdevtest.c
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/lxc/lxc_hostdev.c | 305 ++------------------------------------------------ 1 file changed, 10 insertions(+), 295 deletions(-) diff --git a/src/lxc/lxc_hostdev.c b/src/lxc/lxc_hostdev.c index 635f2e5..07480dc 100644 --- a/src/lxc/lxc_hostdev.c +++ b/src/lxc/lxc_hostdev.c @@ -35,259 +35,28 @@ int virLXCUpdateActiveUsbHostdevs(virLXCDriverPtr driver, virDomainDefPtr def) { - virDomainHostdevDefPtr hostdev = NULL; - size_t i; virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; if (!def->nhostdevs) return 0; - for (i = 0; i < def->nhostdevs; i++) { - virUSBDevicePtr usb = NULL; - hostdev = def->hostdevs[i]; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; - - usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - NULL); - if (!usb) { - VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - def->name); - continue; - } - - virUSBDeviceSetUsedBy(usb, LXC_DRIVER_NAME, def->name); - - virObjectLock(hostdev_mgr->activeUsbHostdevs); - if (virUSBDeviceListAdd(hostdev_mgr->activeUsbHostdevs, usb) < 0) { - virObjectUnlock(hostdev_mgr->activeUsbHostdevs); - virUSBDeviceFree(usb); - return -1; - } - virObjectUnlock(hostdev_mgr->activeUsbHostdevs); - } - - return 0; -} - - -int -virLXCPrepareHostdevUSBDevices(virLXCDriverPtr driver, - const char *name, - virUSBDeviceList *list) -{ - size_t i, j; - unsigned int count; - virUSBDevicePtr tmp; - virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - - count = virUSBDeviceListCount(list); - - virObjectLock(hostdev_mgr->activeUsbHostdevs); - for (i = 0; i < count; i++) { - virUSBDevicePtr usb = virUSBDeviceListGet(list, i); - if ((tmp = virUSBDeviceListFind(hostdev_mgr->activeUsbHostdevs, usb))) { - const char *other_drvname; - const char *other_domname; - - virUSBDeviceGetUsedBy(tmp, &other_drvname, &other_domname); - if (other_drvname && other_domname) - virReportError(VIR_ERR_OPERATION_INVALID, - _("USB device %s is in use by " - "driver %s, domain %s"), - virUSBDeviceGetName(tmp), - other_drvname, other_domname); - else - virReportError(VIR_ERR_OPERATION_INVALID, - _("USB device %s is already in use"), - virUSBDeviceGetName(tmp)); - goto error; - } - - virUSBDeviceSetUsedBy(usb, LXC_DRIVER_NAME, name); - VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs", - virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb), name); - /* - * The caller is responsible to steal these usb devices - * from the virUSBDeviceList that passed in on success, - * perform rollback on failure. - */ - if (virUSBDeviceListAdd(hostdev_mgr->activeUsbHostdevs, usb) < 0) - goto error; - } - virObjectUnlock(hostdev_mgr->activeUsbHostdevs); - return 0; - -error: - for (j = 0; j < i; j++) { - tmp = virUSBDeviceListGet(list, i); - virUSBDeviceListSteal(hostdev_mgr->activeUsbHostdevs, tmp); - } - virObjectUnlock(hostdev_mgr->activeUsbHostdevs); - return -1; -} - -int -virLXCFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, - bool mandatory, - virUSBDevicePtr *usb) -{ - unsigned vendor = hostdev->source.subsys.u.usb.vendor; - unsigned product = hostdev->source.subsys.u.usb.product; - unsigned bus = hostdev->source.subsys.u.usb.bus; - unsigned device = hostdev->source.subsys.u.usb.device; - bool autoAddress = hostdev->source.subsys.u.usb.autoAddress; - int rc; - - *usb = NULL; - - if (vendor && bus) { - rc = virUSBDeviceFind(vendor, product, bus, device, - NULL, - autoAddress ? false : mandatory, - usb); - if (rc < 0) { - return -1; - } else if (!autoAddress) { - goto out; - } else { - VIR_INFO("USB device %x:%x could not be found at previous" - " address (bus:%u device:%u)", - vendor, product, bus, device); - } - } - - /* When vendor is specified, its USB address is either unspecified or the - * device could not be found at the USB device where it had been - * automatically found before. - */ - if (vendor) { - virUSBDeviceList *devs; - - rc = virUSBDeviceFindByVendor(vendor, product, - NULL, - mandatory, &devs); - if (rc < 0) - return -1; - - if (rc == 1) { - *usb = virUSBDeviceListGet(devs, 0); - virUSBDeviceListSteal(devs, *usb); - } - virObjectUnref(devs); - - if (rc == 0) { - goto out; - } else if (rc > 1) { - if (autoAddress) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("Multiple USB devices for %x:%x were found," - " but none of them is at bus:%u device:%u"), - vendor, product, bus, device); - } else { - virReportError(VIR_ERR_OPERATION_FAILED, - _("Multiple USB devices for %x:%x, " - "use <address> to specify one"), - vendor, product); - } - return -1; - } - - hostdev->source.subsys.u.usb.bus = virUSBDeviceGetBus(*usb); - hostdev->source.subsys.u.usb.device = virUSBDeviceGetDevno(*usb); - hostdev->source.subsys.u.usb.autoAddress = true; - - if (autoAddress) { - VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved" - " from bus:%u device:%u)", - vendor, product, - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - bus, device); - } - } else if (!vendor && bus) { - if (virUSBDeviceFindByBus(bus, device, - NULL, - mandatory, usb) < 0) - return -1; - } - -out: - if (!*usb) - hostdev->missing = true; - return 0; + return virHostdevUpdateActiveUsbHostdevs(hostdev_mgr, + def->hostdevs, def->nhostdevs, + LXC_DRIVER_NAME, def->name); } static int virLXCPrepareHostUSBDevices(virLXCDriverPtr driver, virDomainDefPtr def) { - size_t i; - int ret = -1; - virUSBDeviceList *list; - virUSBDevicePtr tmp; virDomainHostdevDefPtr *hostdevs = def->hostdevs; int nhostdevs = def->nhostdevs; + const char *dom_name = def->name; + unsigned int flags = 0; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - /* To prevent situation where USB device is assigned to two domains - * we need to keep a list of currently assigned USB devices. - * This is done in several loops which cannot be joined into one big - * loop. See virLXCPrepareHostdevPCIDevices() - */ - if (!(list = virUSBDeviceListNew())) - goto cleanup; - - /* Loop 1: build temporary list - */ - for (i = 0; i < nhostdevs; i++) { - virDomainHostdevDefPtr hostdev = hostdevs[i]; - bool required = true; - virUSBDevicePtr usb; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; - - if (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_OPTIONAL) - required = false; - - if (virLXCFindHostdevUSBDevice(hostdev, required, &usb) < 0) - goto cleanup; - - if (usb && virUSBDeviceListAdd(list, usb) < 0) { - virUSBDeviceFree(usb); - goto cleanup; - } - } - - /* Mark devices in temporary list as used by @name - * and add them do driver list. However, if something goes - * wrong, perform rollback. - */ - if (virLXCPrepareHostdevUSBDevices(driver, def->name, list) < 0) - goto cleanup; - - /* Loop 2: Temporary list was successfully merged with - * driver list, so steal all items to avoid freeing them - * in cleanup label. - */ - while (virUSBDeviceListCount(list) > 0) { - tmp = virUSBDeviceListGet(list, 0); - virUSBDeviceListSteal(list, tmp); - } - - ret = 0; - -cleanup: - virObjectUnref(list); - return ret; + return virHostdevPrepareUsbHostdevs(hostdev_mgr, LXC_DRIVER_NAME, dom_name, + hostdevs, nhostdevs, flags); } @@ -352,64 +121,10 @@ virLXCDomainReAttachHostUsbDevices(virLXCDriverPtr driver, virDomainHostdevDefPtr *hostdevs, int nhostdevs) { - size_t i; virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; - virObjectLock(hostdev_mgr->activeUsbHostdevs); - for (i = 0; i < nhostdevs; i++) { - virDomainHostdevDefPtr hostdev = hostdevs[i]; - virUSBDevicePtr usb, tmp; - const char *usedby_domname = NULL; - const char *usedby_drvname = NULL; - - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; - if (hostdev->missing) - continue; - - usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - NULL); - - if (!usb) { - VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - name); - continue; - } - - /* Delete only those USB devices which belongs - * to domain @name because virLXCProcessStart() might - * have failed because USB device is already taken. - * Therefore we want to steal only those devices from - * the list which were taken by @name */ - - tmp = virUSBDeviceListFind(hostdev_mgr->activeUsbHostdevs, usb); - virUSBDeviceFree(usb); - - if (!tmp) { - VIR_WARN("Unable to find device %03d.%03d " - "in list of active USB devices", - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device); - continue; - } - - virUSBDeviceGetUsedBy(tmp, &usedby_drvname, &usedby_domname); - if (STREQ_NULLABLE(LXC_DRIVER_NAME, usedby_drvname) && - STREQ_NULLABLE(name, usedby_domname)) { - VIR_DEBUG("Removing %03d.%03d dom=%s from activeUsbHostdevs", - hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - name); - - virUSBDeviceListDel(hostdev_mgr->activeUsbHostdevs, tmp); - } - } - virObjectUnlock(hostdev_mgr->activeUsbHostdevs); + virHostdevReAttachUsbHostdevs(hostdev_mgr, LXC_DRIVER_NAME, + name, hostdevs, nhostdevs); } void virLXCDomainReAttachHostDevices(virLXCDriverPtr driver, -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:14PM +0800, Chunyan Liu wrote:
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/lxc/lxc_hostdev.c | 305 ++------------------------------------------------ 1 file changed, 10 insertions(+), 295 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Add VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN. For legacy xen, it will use "pciback" as stub driver. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- docs/schemas/domaincommon.rng | 1 + src/conf/domain_conf.c | 3 ++- src/conf/domain_conf.h | 1 + src/libxl/libxl_domain.c | 9 +++++++++ src/qemu/qemu_command.c | 3 +-- src/qemu/qemu_hostdev.c | 1 + src/qemu/qemu_hotplug.c | 4 +--- src/util/virhostdev.c | 10 ++++++++++ 8 files changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 601e7ac..bcd8142 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3421,6 +3421,7 @@ <choice> <value>kvm</value> <value>vfio</value> + <value>xen</value> </choice> </attribute> <empty/> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1d5cc14..6d778a5 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -627,7 +627,8 @@ VIR_ENUM_IMPL(virDomainHostdevSubsysPciBackend, VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST, "default", "kvm", - "vfio") + "vfio", + "xen") VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST, "storage", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 2467f65..2840539 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -415,6 +415,7 @@ typedef enum { VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, /* detect automaticaly, prefer VFIO */ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM, /* force legacy kvm style */ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO, /* force vfio */ + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN, /* force legacy xen style, use pciback */ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST } virDomainHostdevSubsysPciBackendType; diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index fdc4661..274fb6c 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -478,6 +478,15 @@ libxlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, STRNEQ(def->os.type, "hvm")) dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; + if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + virDomainHostdevDefPtr hostdev = dev->data.hostdev; + + if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && + hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) + hostdev->source.subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN; + } + return 0; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 611d21d..0c3a024 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5547,8 +5547,7 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def, virBufferAddLit(&buf, "vfio-pci"); break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST: + default: virReportError(VIR_ERR_INTERNAL_ERROR, _("invalid PCI passthrough type '%s'"), virDomainHostdevSubsysPciBackendTypeToString(backend)); diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 88907b1..f966ca2 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -205,6 +205,7 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs, break; + case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN: case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST: break; } diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 420cb28..216727c 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1192,9 +1192,7 @@ qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver, virProcessSetMaxMemLock(vm->pid, memKB * 1024); break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM: - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST: + default: break; } diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 5f61bfc..c112f95 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -173,6 +173,12 @@ virHostdevGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs) virObjectUnref(list); return NULL; } + } else if (hostdev->source.subsys.u.pci.backend + == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN) { + if (virPCIDeviceSetStubDriver(dev, "pciback") < 0) { + virObjectUnref(list); + return NULL; + } } else { if (virPCIDeviceSetStubDriver(dev, "pci-stub") < 0) { virObjectUnref(list); @@ -828,6 +834,10 @@ virHostdevUpdateActivePciHostdevs(virHostdevManagerPtr mgr, == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { if (virPCIDeviceSetStubDriver(dev, "vfio-pci") < 0) goto cleanup; + } else if (hostdev->source.subsys.u.pci.backend + == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN) { + if (virPCIDeviceSetStubDriver(dev, "pciback") < 0) + goto cleanup; } else { if (virPCIDeviceSetStubDriver(dev, "pci-stub") < 0) goto cleanup; -- 1.9.0

On Fri, Mar 07, 2014 at 06:53:15PM +0800, Chunyan Liu wrote:
Add VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN. For legacy xen, it will use "pciback" as stub driver.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- docs/schemas/domaincommon.rng | 1 + src/conf/domain_conf.c | 3 ++- src/conf/domain_conf.h | 1 + src/libxl/libxl_domain.c | 9 +++++++++ src/qemu/qemu_command.c | 3 +-- src/qemu/qemu_hostdev.c | 1 + src/qemu/qemu_hotplug.c | 4 +--- src/util/virhostdev.c | 10 ++++++++++ 8 files changed, 26 insertions(+), 6 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Add pci passthrough to libxl driver, support attach-device, detach-device and start a vm with pci hostdev specified. Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libxl/libxl_conf.c | 63 +++++++ src/libxl/libxl_conf.h | 7 +- src/libxl/libxl_driver.c | 454 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 518 insertions(+), 6 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index ade0a08..8ba3ce3 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1147,6 +1147,66 @@ libxlDriverConfigGet(libxlDriverPrivatePtr driver) return cfg; } +int +libxlMakePci(virDomainHostdevDefPtr hostdev, libxl_device_pci *pcidev) +{ + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + return -1; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + return -1; + + pcidev->domain = hostdev->source.subsys.u.pci.addr.domain; + pcidev->bus = hostdev->source.subsys.u.pci.addr.bus; + pcidev->dev = hostdev->source.subsys.u.pci.addr.slot; + pcidev->func = hostdev->source.subsys.u.pci.addr.function; + + return 0; +} + +static int +libxlMakePciList(virDomainDefPtr def, libxl_domain_config *d_config) +{ + virDomainHostdevDefPtr *l_hostdevs = def->hostdevs; + size_t nhostdevs = def->nhostdevs; + size_t npcidevs = 0; + libxl_device_pci *x_pcidevs; + size_t i, j; + + if (nhostdevs == 0) + return 0; + + if (VIR_ALLOC_N(x_pcidevs, nhostdevs) < 0) + return -1; + + for (i = 0, j = 0; i < nhostdevs; i++) { + if (l_hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (l_hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + continue; + + libxl_device_pci_init(&x_pcidevs[j]); + + if (libxlMakePci(l_hostdevs[i], &x_pcidevs[j]) < 0) + goto error; + + npcidevs++; + j++; + } + + VIR_SHRINK_N(x_pcidevs, nhostdevs, nhostdevs - npcidevs); + d_config->pcidevs = x_pcidevs; + d_config->num_pcidevs = npcidevs; + + return 0; + +error: + for (i = 0; i < npcidevs; i++) + libxl_device_pci_dispose(&x_pcidevs[i]); + + VIR_FREE(x_pcidevs); + return -1; +} + virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx) { @@ -1195,6 +1255,9 @@ libxlBuildDomainConfig(libxlDriverPrivatePtr driver, if (libxlMakeVfbList(driver, def, d_config) < 0) return -1; + if (libxlMakePciList(def, d_config) < 0) + return -1; + d_config->on_reboot = def->onReboot; d_config->on_poweroff = def->onPoweroff; d_config->on_crash = def->onCrash; diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index f089a92..4f6f7ce 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -37,8 +37,9 @@ # include "virportallocator.h" # include "virobject.h" # include "virchrdev.h" +# include "virhostdev.h" - +# define LIBXL_DRIVER_NAME "xenlight" # define LIBXL_VNC_PORT_MIN 5900 # define LIBXL_VNC_PORT_MAX 65535 @@ -90,6 +91,7 @@ struct _libxlDriverConfig { struct _libxlDriverPrivate { virMutex lock; + virHostdevManagerPtr hostdevMgr; /* Require lock to get reference on 'config', * then lockless thereafter */ libxlDriverConfigPtr config; @@ -150,6 +152,9 @@ libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb); int +libxlMakePci(virDomainHostdevDefPtr hostdev, libxl_device_pci *pcidev); + +int libxlBuildDomainConfig(libxlDriverPrivatePtr driver, virDomainObjPtr vm, libxl_domain_config *d_config); diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index a79efcb..88a0a90 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -52,6 +52,7 @@ #include "virsysinfo.h" #include "viraccessapicheck.h" #include "viratomic.h" +#include "virhostdev.h" #define VIR_FROM_THIS VIR_FROM_LIBXL @@ -309,6 +310,10 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, int vnc_port; char *file; size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + virHostdevReAttachDomainHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def, VIR_HOSTDEV_SP_PCI, NULL); vm->def->id = -1; @@ -699,6 +704,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, #ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS libxl_domain_restore_params params; #endif + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; if (libxlDomainObjPrivateInitCtx(vm) < 0) return ret; @@ -761,6 +767,10 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, goto endjob; } + if (virHostdevPrepareDomainHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def, VIR_HOSTDEV_SP_PCI) < 0) + goto endjob; + /* Unlock virDomainObj while creating the domain */ virObjectUnlock(vm); if (restore_fd < 0) { @@ -867,6 +877,7 @@ libxlReconnectDomain(virDomainObjPtr vm, libxl_dominfo d_info; int len; uint8_t *data = NULL; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; virObjectLock(vm); @@ -890,6 +901,12 @@ libxlReconnectDomain(virDomainObjPtr vm, /* Update domid in case it changed (e.g. reboot) while we were gone? */ vm->def->id = d_info.domid; + + /* Update hostdev state */ + if (virHostdevUpdateDomainActiveHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def, VIR_HOSTDEV_SP_PCI) < 0) + goto out; + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN); if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) @@ -922,6 +939,7 @@ libxlStateCleanup(void) if (!libxl_driver) return -1; + virObjectUnref(libxl_driver->hostdevMgr); virObjectUnref(libxl_driver->config); virObjectUnref(libxl_driver->xmlopt); virObjectUnref(libxl_driver->domains); @@ -1001,6 +1019,9 @@ libxlStateInitialize(bool privileged, if (!(libxl_driver->domains = virDomainObjListNew())) goto error; + if (!(libxl_driver->hostdevMgr = virHostdevManagerGetDefault())) + goto error; + if (!(cfg = libxlDriverConfigNew())) goto error; @@ -3274,6 +3295,95 @@ cleanup: } static int +libxlDomainAttachHostPciDevice(libxlDriverPrivatePtr driver, + libxlDomainObjPrivatePtr priv, + virDomainObjPtr vm, + virDomainHostdevDefPtr hostdev) +{ + libxl_device_pci pcidev; + virDomainHostdevDefPtr found; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + return -1; + + if (virDomainHostdevFind(vm->def, hostdev, &found) >= 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("target pci device %.4x:%.2x:%.2x.%.1x already exists"), + hostdev->source.subsys.u.pci.addr.domain, + hostdev->source.subsys.u.pci.addr.bus, + hostdev->source.subsys.u.pci.addr.slot, + hostdev->source.subsys.u.pci.addr.function); + return -1; + } + + if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0) + return -1; + + if (virHostdevPreparePciHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def->name, vm->def->uuid, + &hostdev, 1, 0) < 0) + goto cleanup; + + if (libxlMakePci(hostdev, &pcidev) < 0) + goto reattach_hostdev; + + if (libxl_device_pci_add(priv->ctx, vm->def->id, &pcidev, 0) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to attach pci device %.4x:%.2x:%.2x.%.1x"), + hostdev->source.subsys.u.pci.addr.domain, + hostdev->source.subsys.u.pci.addr.bus, + hostdev->source.subsys.u.pci.addr.slot, + hostdev->source.subsys.u.pci.addr.function); + goto reattach_hostdev; + } + + vm->def->hostdevs[vm->def->nhostdevs++] = hostdev; + return 0; + +reattach_hostdev: + virHostdevReAttachPciHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def->name, &hostdev, 1, NULL); + +cleanup: + return -1; +} + +static int +libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver, + libxlDomainObjPrivatePtr priv, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) +{ + virDomainHostdevDefPtr hostdev = dev->data.hostdev; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("hostdev mode '%s' not supported"), + virDomainHostdevModeTypeToString(hostdev->mode)); + return -1; + } + + switch (hostdev->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: + if (libxlDomainAttachHostPciDevice(driver, priv, vm, hostdev) < 0) + goto error; + break; + + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("hostdev subsys type '%s' not supported"), + virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type)); + goto error; + } + + return 0; + +error: + return -1; +} + +static int libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { @@ -3328,7 +3438,9 @@ cleanup: } static int -libxlDomainAttachDeviceLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, +libxlDomainAttachDeviceLive(libxlDriverPrivatePtr driver, + libxlDomainObjPrivatePtr priv, + virDomainObjPtr vm, virDomainDeviceDefPtr dev) { int ret = -1; @@ -3340,6 +3452,12 @@ libxlDomainAttachDeviceLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, dev->data.disk = NULL; break; + case VIR_DOMAIN_DEVICE_HOSTDEV: + ret = libxlDomainAttachHostDevice(driver, priv, vm, dev); + if (!ret) + dev->data.hostdev = NULL; + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("device type '%s' cannot be attached"), @@ -3354,6 +3472,8 @@ static int libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { virDomainDiskDefPtr disk; + virDomainHostdevDefPtr hostdev; + virDomainHostdevDefPtr found; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -3368,6 +3488,25 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) /* vmdef has the pointer. Generic codes for vmdef will do all jobs */ dev->data.disk = NULL; break; + case VIR_DOMAIN_DEVICE_HOSTDEV: + hostdev = dev->data.hostdev; + + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + return -1; + + if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("target pci device %.4x:%.2x:%.2x.%.1x\ + already exists"), + hostdev->source.subsys.u.pci.addr.domain, + hostdev->source.subsys.u.pci.addr.bus, + hostdev->source.subsys.u.pci.addr.slot, + hostdev->source.subsys.u.pci.addr.function); + return -1; + } + + virDomainHostdevInsert(vmdef, hostdev); + break; default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -3378,7 +3517,128 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) } static int -libxlDomainDetachDeviceLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, +libxlComparePCIDevice(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr device ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info1, + void *opaque) +{ + virDomainDeviceInfoPtr info2 = opaque; + + if (info1->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI || + info2->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + return 0; + + if (info1->addr.pci.domain == info2->addr.pci.domain && + info1->addr.pci.bus == info2->addr.pci.bus && + info1->addr.pci.slot == info2->addr.pci.slot && + info1->addr.pci.function != info2->addr.pci.function) + return -1; + return 0; +} + +static bool +libxlIsMultiFunctionDevice(virDomainDefPtr def, + virDomainDeviceInfoPtr dev) +{ + if (virDomainDeviceInfoIterate(def, libxlComparePCIDevice, dev) < 0) + return true; + return false; +} + +static int +libxlDomainDetachHostPciDevice(libxlDriverPrivatePtr driver, + libxlDomainObjPrivatePtr priv, + virDomainObjPtr vm, + virDomainHostdevDefPtr hostdev) +{ + virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys; + libxl_device_pci pcidev; + virDomainHostdevDefPtr detach; + int idx; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + if (subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + return -1; + + idx = virDomainHostdevFind(vm->def, hostdev, &detach); + if (idx < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("host pci device %.4x:%.2x:%.2x.%.1x not found"), + subsys->u.pci.addr.domain, subsys->u.pci.addr.bus, + subsys->u.pci.addr.slot, subsys->u.pci.addr.function); + return -1; + } + + if (libxlIsMultiFunctionDevice(vm->def, detach->info)) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("cannot hot unplug multifunction PCI device: %.4x:%.2x:%.2x.%.1x"), + subsys->u.pci.addr.domain, subsys->u.pci.addr.bus, + subsys->u.pci.addr.slot, subsys->u.pci.addr.function); + goto cleanup; + } + + + libxl_device_pci_init(&pcidev); + + if (libxlMakePci(detach, &pcidev) < 0) + goto cleanup; + + if (libxl_device_pci_remove(priv->ctx, vm->def->id, &pcidev, 0) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to detach pci device\ + %.4x:%.2x:%.2x.%.1x"), + subsys->u.pci.addr.domain, subsys->u.pci.addr.bus, + subsys->u.pci.addr.slot, subsys->u.pci.addr.function); + goto cleanup; + } + + libxl_device_pci_dispose(&pcidev); + + virDomainHostdevRemove(vm->def, idx); + + virHostdevReAttachPciHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def->name, &hostdev, 1, NULL); + + return 0; + +cleanup: + virDomainHostdevDefFree(detach); + return -1; +} + +static int +libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver, + libxlDomainObjPrivatePtr priv, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) +{ + virDomainHostdevDefPtr hostdev = dev->data.hostdev; + virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("hostdev mode '%s' not supported"), + virDomainHostdevModeTypeToString(hostdev->mode)); + return -1; + } + + switch (subsys->type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: + return libxlDomainDetachHostPciDevice(driver, priv, vm, hostdev); + + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected hostdev type %d"), subsys->type); + break; + } + + return -1; +} + +static int +libxlDomainDetachDeviceLive(libxlDriverPrivatePtr driver, + libxlDomainObjPrivatePtr priv, + virDomainObjPtr vm, virDomainDeviceDefPtr dev) { int ret = -1; @@ -3388,6 +3648,10 @@ libxlDomainDetachDeviceLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, ret = libxlDomainDetachDeviceDiskLive(priv, vm, dev); break; + case VIR_DOMAIN_DEVICE_HOSTDEV: + ret = libxlDomainDetachHostDevice(driver, priv, vm, dev); + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("device type '%s' cannot be detached"), @@ -3398,6 +3662,7 @@ libxlDomainDetachDeviceLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm, return ret; } + static int libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { @@ -3575,7 +3840,7 @@ libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, VIR_DOMAIN_XML_INACTIVE))) goto endjob; - if ((ret = libxlDomainAttachDeviceLive(priv, vm, dev)) < 0) + if ((ret = libxlDomainAttachDeviceLive(driver, priv, vm, dev)) < 0) goto endjob; /* @@ -3686,7 +3951,7 @@ libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, VIR_DOMAIN_XML_INACTIVE))) goto endjob; - if ((ret = libxlDomainDetachDeviceLive(priv, vm, dev)) < 0) + if ((ret = libxlDomainDetachDeviceLive(driver, priv, vm, dev)) < 0) goto endjob; /* @@ -4590,10 +4855,185 @@ libxlConnectSupportsFeature(virConnectPtr conn, int feature) } } +static int +libxlNodeDeviceGetPciInfo(virNodeDeviceDefPtr def, + unsigned *domain, + unsigned *bus, + unsigned *slot, + unsigned *function) +{ + virNodeDevCapsDefPtr cap; + int ret = -1; + + cap = def->caps; + while (cap) { + if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) { + *domain = cap->data.pci_dev.domain; + *bus = cap->data.pci_dev.bus; + *slot = cap->data.pci_dev.slot; + *function = cap->data.pci_dev.function; + break; + } + + cap = cap->next; + } + + if (!cap) { + virReportError(VIR_ERR_INVALID_ARG, + _("device %s is not a PCI device"), def->name); + goto out; + } + + ret = 0; +out: + return ret; +} + +static int +libxlNodeDeviceDetachFlags(virNodeDevicePtr dev, + const char *driverName, + unsigned int flags) +{ + virPCIDevicePtr pci = NULL; + unsigned domain = 0, bus = 0, slot = 0, function = 0; + int ret = -1; + virNodeDeviceDefPtr def = NULL; + char *xml = NULL; + libxlDriverPrivatePtr driver = dev->conn->privateData; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + virCheckFlags(0, -1); + + xml = virNodeDeviceGetXMLDesc(dev, 0); + if (!xml) + goto cleanup; + + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + if (!def) + goto cleanup; + + if (virNodeDeviceDetachFlagsEnsureACL(dev->conn, def) < 0) + goto cleanup; + + if (libxlNodeDeviceGetPciInfo(def, &domain, &bus, &slot, &function) < 0) + goto cleanup; + + pci = virPCIDeviceNew(domain, bus, slot, function); + if (!pci) + goto cleanup; + + if (!driverName || STREQ(driverName, "xen")) { + if (virPCIDeviceSetStubDriver(pci, "pciback") < 0) + goto cleanup; + } else { + virReportError(VIR_ERR_INVALID_ARG, + _("unsupported driver name '%s'"), driverName); + goto cleanup; + } + + if (virHostdevPciNodeDeviceDetach(hostdev_mgr, pci) < 0) + goto cleanup; + + ret = 0; +cleanup: + virPCIDeviceFree(pci); + virNodeDeviceDefFree(def); + VIR_FREE(xml); + return ret; +} + +static int +libxlNodeDeviceDettach(virNodeDevicePtr dev) +{ + return libxlNodeDeviceDetachFlags(dev, NULL, 0); +} + +static int +libxlNodeDeviceReAttach(virNodeDevicePtr dev) +{ + virPCIDevicePtr pci = NULL; + unsigned domain = 0, bus = 0, slot = 0, function = 0; + int ret = -1; + virNodeDeviceDefPtr def = NULL; + char *xml = NULL; + libxlDriverPrivatePtr driver = dev->conn->privateData; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + xml = virNodeDeviceGetXMLDesc(dev, 0); + if (!xml) + goto cleanup; + + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + if (!def) + goto cleanup; + + if (virNodeDeviceReAttachEnsureACL(dev->conn, def) < 0) + goto cleanup; + + if (libxlNodeDeviceGetPciInfo(def, &domain, &bus, &slot, &function) < 0) + goto cleanup; + + pci = virPCIDeviceNew(domain, bus, slot, function); + if (!pci) + goto cleanup; + + if (virHostdevPciNodeDeviceReAttach(hostdev_mgr, pci) < 0) + goto out; + + ret = 0; +out: + virPCIDeviceFree(pci); +cleanup: + virNodeDeviceDefFree(def); + VIR_FREE(xml); + return ret; +} + +static int +libxlNodeDeviceReset(virNodeDevicePtr dev) +{ + virPCIDevicePtr pci; + unsigned domain = 0, bus = 0, slot = 0, function = 0; + int ret = -1; + virNodeDeviceDefPtr def = NULL; + char *xml = NULL; + libxlDriverPrivatePtr driver = dev->conn->privateData; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + xml = virNodeDeviceGetXMLDesc(dev, 0); + if (!xml) + goto cleanup; + + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + if (!def) + goto cleanup; + + if (virNodeDeviceResetEnsureACL(dev->conn, def) < 0) + goto cleanup; + + if (libxlNodeDeviceGetPciInfo(def, &domain, &bus, &slot, &function) < 0) + goto cleanup; + + pci = virPCIDeviceNew(domain, bus, slot, function); + if (!pci) + goto cleanup; + + if (virHostdevPciNodeDeviceReset(hostdev_mgr, pci) < 0) + goto out; + + ret = 0; +out: + virPCIDeviceFree(pci); +cleanup: + virNodeDeviceDefFree(def); + VIR_FREE(xml); + return ret; +} + static virDriver libxlDriver = { .no = VIR_DRV_LIBXL, - .name = "xenlight", + .name = LIBXL_DRIVER_NAME, .connectOpen = libxlConnectOpen, /* 0.9.0 */ .connectClose = libxlConnectClose, /* 0.9.0 */ .connectGetType = libxlConnectGetType, /* 0.9.0 */ @@ -4676,6 +5116,10 @@ static virDriver libxlDriver = { .connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */ .connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */ .connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */ + .nodeDeviceDettach = libxlNodeDeviceDettach, /* 1.2.3 */ + .nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */ + .nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */ + .nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */ }; static virStateDriver libxlStateDriver = { -- 1.9.0

Chunyan Liu wrote:
Add pci passthrough to libxl driver, support attach-device, detach-device and start a vm with pci hostdev specified.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libxl/libxl_conf.c | 63 +++++++ src/libxl/libxl_conf.h | 7 +- src/libxl/libxl_driver.c | 454 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 518 insertions(+), 6 deletions(-)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index ade0a08..8ba3ce3 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1147,6 +1147,66 @@ libxlDriverConfigGet(libxlDriverPrivatePtr driver) return cfg; }
+int +libxlMakePci(virDomainHostdevDefPtr hostdev, libxl_device_pci *pcidev) +{ + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + return -1; + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + return -1;
Sorry, I should have mentioned this in my v13 review, but we should report an error here, similar to libxlMake{Disk,Nic}.
+ + pcidev->domain = hostdev->source.subsys.u.pci.addr.domain; + pcidev->bus = hostdev->source.subsys.u.pci.addr.bus; + pcidev->dev = hostdev->source.subsys.u.pci.addr.slot; + pcidev->func = hostdev->source.subsys.u.pci.addr.function; + + return 0; +} + +static int +libxlMakePciList(virDomainDefPtr def, libxl_domain_config *d_config) +{ + virDomainHostdevDefPtr *l_hostdevs = def->hostdevs; + size_t nhostdevs = def->nhostdevs; + size_t npcidevs = 0; + libxl_device_pci *x_pcidevs; + size_t i, j; + + if (nhostdevs == 0) + return 0; + + if (VIR_ALLOC_N(x_pcidevs, nhostdevs) < 0) + return -1; + + for (i = 0, j = 0; i < nhostdevs; i++) { + if (l_hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (l_hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + continue; + + libxl_device_pci_init(&x_pcidevs[j]); + + if (libxlMakePci(l_hostdevs[i], &x_pcidevs[j]) < 0) + goto error; + + npcidevs++; + j++; + } + + VIR_SHRINK_N(x_pcidevs, nhostdevs, nhostdevs - npcidevs); + d_config->pcidevs = x_pcidevs; + d_config->num_pcidevs = npcidevs; + + return 0; + +error: + for (i = 0; i < npcidevs; i++) + libxl_device_pci_dispose(&x_pcidevs[i]); + + VIR_FREE(x_pcidevs); + return -1; +} + virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx) { @@ -1195,6 +1255,9 @@ libxlBuildDomainConfig(libxlDriverPrivatePtr driver, if (libxlMakeVfbList(driver, def, d_config) < 0) return -1;
+ if (libxlMakePciList(def, d_config) < 0) + return -1; + d_config->on_reboot = def->onReboot; d_config->on_poweroff = def->onPoweroff; d_config->on_crash = def->onCrash; diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index f089a92..4f6f7ce 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -37,8 +37,9 @@ # include "virportallocator.h" # include "virobject.h" # include "virchrdev.h" +# include "virhostdev.h"
- +# define LIBXL_DRIVER_NAME "xenlight" # define LIBXL_VNC_PORT_MIN 5900 # define LIBXL_VNC_PORT_MAX 65535
@@ -90,6 +91,7 @@ struct _libxlDriverConfig { struct _libxlDriverPrivate { virMutex lock;
+ virHostdevManagerPtr hostdevMgr; /* Require lock to get reference on 'config', * then lockless thereafter */ libxlDriverConfigPtr config; @@ -150,6 +152,9 @@ libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb);
int +libxlMakePci(virDomainHostdevDefPtr hostdev, libxl_device_pci *pcidev); + +int libxlBuildDomainConfig(libxlDriverPrivatePtr driver, virDomainObjPtr vm, libxl_domain_config *d_config);
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index a79efcb..88a0a90 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -52,6 +52,7 @@ #include "virsysinfo.h" #include "viraccessapicheck.h" #include "viratomic.h" +#include "virhostdev.h"
#define VIR_FROM_THIS VIR_FROM_LIBXL
@@ -309,6 +310,10 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, int vnc_port; char *file; size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + virHostdevReAttachDomainHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def, VIR_HOSTDEV_SP_PCI, NULL);
vm->def->id = -1;
@@ -699,6 +704,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, #ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS libxl_domain_restore_params params; #endif + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
if (libxlDomainObjPrivateInitCtx(vm) < 0) return ret; @@ -761,6 +767,10 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, goto endjob; }
+ if (virHostdevPrepareDomainHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def, VIR_HOSTDEV_SP_PCI) < 0) + goto endjob; + /* Unlock virDomainObj while creating the domain */ virObjectUnlock(vm); if (restore_fd < 0) { @@ -867,6 +877,7 @@ libxlReconnectDomain(virDomainObjPtr vm, libxl_dominfo d_info; int len; uint8_t *data = NULL; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
virObjectLock(vm);
@@ -890,6 +901,12 @@ libxlReconnectDomain(virDomainObjPtr vm,
/* Update domid in case it changed (e.g. reboot) while we were gone? */ vm->def->id = d_info.domid; + + /* Update hostdev state */ + if (virHostdevUpdateDomainActiveHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def, VIR_HOSTDEV_SP_PCI) < 0) + goto out; + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN);
if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) @@ -922,6 +939,7 @@ libxlStateCleanup(void) if (!libxl_driver) return -1;
+ virObjectUnref(libxl_driver->hostdevMgr); virObjectUnref(libxl_driver->config); virObjectUnref(libxl_driver->xmlopt); virObjectUnref(libxl_driver->domains); @@ -1001,6 +1019,9 @@ libxlStateInitialize(bool privileged, if (!(libxl_driver->domains = virDomainObjListNew())) goto error;
+ if (!(libxl_driver->hostdevMgr = virHostdevManagerGetDefault())) + goto error; + if (!(cfg = libxlDriverConfigNew())) goto error;
@@ -3274,6 +3295,95 @@ cleanup: }
static int +libxlDomainAttachHostPciDevice(libxlDriverPrivatePtr driver, + libxlDomainObjPrivatePtr priv, + virDomainObjPtr vm, + virDomainHostdevDefPtr hostdev) +{ + libxl_device_pci pcidev; + virDomainHostdevDefPtr found; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + return -1; + + if (virDomainHostdevFind(vm->def, hostdev, &found) >= 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("target pci device %.4x:%.2x:%.2x.%.1x already exists"), + hostdev->source.subsys.u.pci.addr.domain, + hostdev->source.subsys.u.pci.addr.bus, + hostdev->source.subsys.u.pci.addr.slot, + hostdev->source.subsys.u.pci.addr.function); + return -1; + } + + if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0) + return -1; + + if (virHostdevPreparePciHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def->name, vm->def->uuid, + &hostdev, 1, 0) < 0) + goto cleanup; + + if (libxlMakePci(hostdev, &pcidev) < 0) + goto reattach_hostdev; + + if (libxl_device_pci_add(priv->ctx, vm->def->id, &pcidev, 0) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to attach pci device %.4x:%.2x:%.2x.%.1x"), + hostdev->source.subsys.u.pci.addr.domain, + hostdev->source.subsys.u.pci.addr.bus, + hostdev->source.subsys.u.pci.addr.slot, + hostdev->source.subsys.u.pci.addr.function); + goto reattach_hostdev; + } + + vm->def->hostdevs[vm->def->nhostdevs++] = hostdev; + return 0; + +reattach_hostdev: + virHostdevReAttachPciHostdevs(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def->name, &hostdev, 1, NULL); + +cleanup: + return -1;
Looks like you missed my comments from v13 https://www.redhat.com/archives/libvir-list/2014-March/msg00170.html
+} + +static int +libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver, + libxlDomainObjPrivatePtr priv, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) +{ + virDomainHostdevDefPtr hostdev = dev->data.hostdev; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("hostdev mode '%s' not supported"), + virDomainHostdevModeTypeToString(hostdev->mode)); + return -1; + } + + switch (hostdev->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: + if (libxlDomainAttachHostPciDevice(driver, priv, vm, hostdev) < 0) + goto error; + break; + + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("hostdev subsys type '%s' not supported"), + virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type)); + goto error; + } + + return 0; + +error: + return -1;
Ah, same here, and I probably throughout the rest of the patch - although I didn't check. I guess you missed my message :). Regards, Jim

On Fri, Mar 07, 2014 at 06:53:16PM +0800, Chunyan Liu wrote:
Add pci passthrough to libxl driver, support attach-device, detach-device and start a vm with pci hostdev specified.
Signed-off-by: Chunyan Liu <cyliu@suse.com> --- src/libxl/libxl_conf.c | 63 +++++++ src/libxl/libxl_conf.h | 7 +- src/libxl/libxl_driver.c | 454 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 518 insertions(+), 6 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

The whole patch series could be get from here: https://github.com/chunyanliu/libvirt/commits/hostdev_passthrough -Chunyan
On 3/7/2014 at 06:52 PM, in message <1394189596-22994-1-git-send-email-cyliu@suse.com>, Chunyan Liu <cyliu@suse.com> wrote: These patches implements a separate module for hostdev passthrough so that it could be shared by different drivers and can maintain a global state of a host device.
Patch 1: fix memory leak in virscsi.c Patch 2: improve virHostdevManager to use virOject wrapper and keep reference
Patches 3~7: switch existing qemu and lxc driver to use virHostdevManager's lists, so that to maintain a global state of every host device.
Patches 8~45 are to extract general code from qemu_hostdev.c piece by piece, make them reusable common APIs.
Patches 46: unit test for the virhostdev common library Patches 47: add a hostdev backend type for xen Patches 48: add pci passthrough to libxl driver based on the common library Patches 49: change lxc to use common library APIs
--- changes to v13: * change virHostdevManager, use virObject and keep reference, solve 'free' problem * add .hostdevMgr to qemu/lxc/libxl driver, get virHostdevManager in StateInitialize for once and keep reference, instead of getting it every time virHostdevManager is used. * fix v13 3/49 "qemu-reuse-hostdev-interfaces-to-avoid-duplicate.patch": update qemuPrepareHostUSBDevices parameters to specify hostdevs and nhostdevs, so that could be reused in qemu_hotplug. * rebase left patches
Chunyan Liu (49): virscsi: fix memory leak virhostdev: use virObject to virHostdevManager to keep reference update qemuPrepareHostUSBDevices parameters to keep consistency qemu: reuse hostdev interfaces to avoid duplicate qemu: remove functions used internally only from qemu_hostdev.h qemu: use general virhostdev lists instead of its own lxc: use general virhostdev lists instead of its own qemu_hostdev: move cfg->relaxedACS as a flag qemu_hostdev: move ColdBoot as a flag qemu_hostdev: move netconfig file location to virhostdev stateDir extract general code from qemuPrepareHostdevPCIDevices rename qemu*NetConfigRestore/Replace to virHostdevNetConfigRestore/Replace rename qemuGet*PciHostDeviceList to virHostdevGet*PciHostDeviceList pass driver name as a parameter to virHostdevPrepareHostdevPCIDevices extract general code from qemuDomainReAttachHostdevDevices pass driver name as a parameter to virHostdevReAttachPCIDevices rename qemuReAttachPciDevice to virHostdevReAttachPciDevice move virHostdevPrepare(ReAttach)PCIDevices to virhostdev.c extract general code from qemuUpdateActivePciHostdevs extract general code from qemuUpdateActiveUsbHostdevs extract general code from qemuUpdateActiveScsiHostdevs pass driver_name as parameter of virHostdevUpdate*Hostdevs functions move virHostdevUpdate* functions to virhostdev.c extract general code from qemuPrepareHostUSBDevices rename qemu*USBDevices to virHostdev*USBDevices pass driver name to virHostdevPrepareUSBDevices move virHostdevPrepareHostUSBDevices to virhostdev.c extract general code from qemuPrepareHostSCSIDevices pass driver name as parameter to virHostdevPrepareSCSIDevices move virHostdevPrepareHostSCSIDevices to virhostdev.c extract general code from qemuDomainReAttachHostUsbDevices pass driver name as paramter to virHostdevReAttachUsbHostdevs move virHostdevReAttachUsbHostdevs to virhostdev.c extract general code from qemuDomainReAttachHostScsiDevices pass driver name as parameter to virHostdevReAttachScciHostdevs move virHostdevReAttachHostScsiDevices to virhostdev.c extract general code of NodeDeviceDetach extract general code of NodeDeviceReAttach extract general code of NodeDeviceReset move virHostdevNodeDevice* to virhostdev.c improve parameter name to let it more meaningful rename some function names to keep consistency improve virHostdevUpdate* parameters to make it more widely used add 3 wrapper functions for prepare/reattach/update domain hostdevs add parameter checks to common interfaces add unit test for new virhostdev common library change lxc_hostdev.c to use virhostdev common library APIs add hostdev pci backend type for xen add pci passthrough to libxl driver
.gitignore | 1 + docs/schemas/domaincommon.rng | 1 + src/conf/domain_conf.c | 3 +- src/conf/domain_conf.h | 1 + src/libvirt_private.syms | 15 + src/libxl/libxl_conf.c | 63 ++ src/libxl/libxl_conf.h | 7 +- src/libxl/libxl_domain.c | 9 + src/libxl/libxl_driver.c | 454 +++++++++++- src/lxc/lxc_conf.h | 5 +- src/lxc/lxc_driver.c | 12 +- src/lxc/lxc_hostdev.c | 307 +------- src/qemu/qemu_command.c | 3 +- src/qemu/qemu_conf.h | 9 +- src/qemu/qemu_driver.c | 76 +- src/qemu/qemu_hostdev.c | 1203 ++----------------------------- src/qemu/qemu_hostdev.h | 29 +- src/qemu/qemu_hotplug.c | 78 +- src/qemu/qemu_process.c | 8 +- src/util/virhostdev.c | 1565 ++++++++++++++++++++++++++++++++++++++++- src/util/virhostdev.h | 96 +++ src/util/virscsi.c | 13 +- tests/Makefile.am | 5 + tests/virhostdevtest.c | 507 +++++++++++++ 24 files changed, 2832 insertions(+), 1638 deletions(-) create mode 100644 tests/virhostdevtest.c

On Fri, Mar 07, 2014 at 06:52:27PM +0800, Chunyan Liu wrote:
These patches implements a separate module for hostdev passthrough so that it could be shared by different drivers and can maintain a global state of a host device.
Patch 1: fix memory leak in virscsi.c Patch 2: improve virHostdevManager to use virOject wrapper and keep reference
Patches 3~7: switch existing qemu and lxc driver to use virHostdevManager's lists, so that to maintain a global state of every host device.
Patches 8~45 are to extract general code from qemu_hostdev.c piece by piece, make them reusable common APIs.
Patches 46: unit test for the virhostdev common library Patches 47: add a hostdev backend type for xen Patches 48: add pci passthrough to libxl driver based on the common library Patches 49: change lxc to use common library APIs
I have now pushed all the patches together with the fixes for them I suggested in various comments. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (5)
-
Chun Yan Liu
-
Chunyan Liu
-
Daniel P. Berrange
-
Jim Fehlig
-
John Ferlan