The QEMU driver file is far too large. Move all the hostdev
helper code out into a separate file. No functional change.
* src/qemu/qemu_hostdev.c, src/qemu/qemu_hostdev.h,
src/Makefile.am: Add hostdev helper file
* src/qemu/qemu_driver.c: Delete hostdev code
---
src/Makefile.am | 1 +
src/qemu/qemu_driver.c | 266 +-------------------------------------------
src/qemu/qemu_hostdev.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_hostdev.h | 45 ++++++++
4 files changed, 337 insertions(+), 264 deletions(-)
create mode 100644 src/qemu/qemu_hostdev.c
create mode 100644 src/qemu/qemu_hostdev.h
diff --git a/src/Makefile.am b/src/Makefile.am
index da3bd6f..d30774b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -272,6 +272,7 @@ QEMU_DRIVER_SOURCES = \
qemu/qemu_domain.c qemu/qemu_domain.h \
qemu/qemu_audit.c qemu/qemu_audit.h \
qemu/qemu_cgroup.c qemu/qemu_cgroup.c \
+ qemu/qemu_hostdev.c qemu/qemu_hostdev.h \
qemu/qemu_conf.c qemu/qemu_conf.h \
qemu/qemu_monitor.c qemu/qemu_monitor.h \
qemu/qemu_monitor_text.c \
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 585b259..5d8aef3 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -56,6 +56,7 @@
#include "qemu_capabilities.h"
#include "qemu_command.h"
#include "qemu_cgroup.h"
+#include "qemu_hostdev.h"
#include "qemu_monitor.h"
#include "qemu_bridge_filter.h"
#include "qemu_audit.h"
@@ -144,9 +145,6 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom);
static int qemuDetectVcpuPIDs(struct qemud_driver *driver,
virDomainObjPtr vm);
-static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
- virDomainDefPtr def);
-
static int qemudVMFiltersInstantiate(virConnectPtr conn,
virDomainDefPtr def);
@@ -2758,192 +2756,6 @@ cleanup:
}
-static pciDeviceList *
-qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs)
-{
- pciDeviceList *list;
- int i;
-
- if (!(list = pciDeviceListNew()))
- return NULL;
-
- for (i = 0 ; i < nhostdevs ; i++) {
- virDomainHostdevDefPtr hostdev = hostdevs[i];
- pciDevice *dev;
-
- if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
- continue;
- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
- continue;
-
- dev = pciGetDevice(hostdev->source.subsys.u.pci.domain,
- hostdev->source.subsys.u.pci.bus,
- hostdev->source.subsys.u.pci.slot,
- hostdev->source.subsys.u.pci.function);
- if (!dev) {
- pciDeviceListFree(list);
- return NULL;
- }
-
- if (pciDeviceListAdd(list, dev) < 0) {
- pciFreeDevice(dev);
- pciDeviceListFree(list);
- return NULL;
- }
-
- pciDeviceSetManaged(dev, hostdev->managed);
- }
-
- return list;
-}
-
-static int
-qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
- virDomainDefPtr def)
-{
- pciDeviceList *pcidevs;
- int i;
- int ret = -1;
-
- if (!def->nhostdevs)
- return 0;
-
- if (!(pcidevs = qemuGetPciHostDeviceList(def->hostdevs, def->nhostdevs)))
- return -1;
-
- for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
- pciDevice *dev = pciDeviceListGet(pcidevs, i);
- pciDeviceListSteal(pcidevs, dev);
- if (pciDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
- pciFreeDevice(dev);
- goto cleanup;
- }
- }
-
- ret = 0;
-
-cleanup:
- pciDeviceListFree(pcidevs);
- return ret;
-}
-
-
-static int
-qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
- virDomainHostdevDefPtr *hostdevs,
- int nhostdevs)
-{
- pciDeviceList *pcidevs;
- int i;
- int ret = -1;
-
- if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs)))
- return -1;
-
- /* We have to use 3 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.
- */
-
- /* XXX 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 < pciDeviceListCount(pcidevs); i++) {
- pciDevice *dev = pciDeviceListGet(pcidevs, i);
- if (!pciDeviceIsAssignable(dev, !driver->relaxedACS))
- goto cleanup;
-
- if (pciDeviceGetManaged(dev) &&
- pciDettachDevice(dev, driver->activePciHostdevs) < 0)
- goto cleanup;
- }
-
- /* Now that all the PCI hostdevs have be dettached, we can safely
- * reset them */
- for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
- pciDevice *dev = pciDeviceListGet(pcidevs, i);
- if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0)
- goto cleanup;
- }
-
- /* Now mark all the devices as active */
- for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
- pciDevice *dev = pciDeviceListGet(pcidevs, i);
- pciDeviceListSteal(pcidevs, dev);
- if (pciDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
- pciFreeDevice(dev);
- goto cleanup;
- }
- }
-
- ret = 0;
-
-cleanup:
- pciDeviceListFree(pcidevs);
- return ret;
-}
-
-static int
-qemuPrepareHostPCIDevices(struct qemud_driver *driver,
- virDomainDefPtr def)
-{
- return qemuPrepareHostdevPCIDevices(driver, def->hostdevs, def->nhostdevs);
-}
-
-
-static int
-qemuPrepareHostUSBDevices(struct qemud_driver *driver ATTRIBUTE_UNUSED,
- virDomainDefPtr def)
-{
- int i;
- for (i = 0 ; i < def->nhostdevs ; i++) {
- virDomainHostdevDefPtr 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;
-
- /* Resolve a vendor/product to bus/device */
- if (hostdev->source.subsys.u.usb.vendor) {
- usbDevice *usb
- = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
- hostdev->source.subsys.u.usb.product);
-
- if (!usb)
- return -1;
-
- hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
- hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);
-
- usbFreeDevice(usb);
- }
- }
-
- return 0;
-}
-
-static int
-qemuPrepareHostDevices(struct qemud_driver *driver,
- virDomainDefPtr def)
-{
- if (!def->nhostdevs)
- return 0;
-
- if (qemuPrepareHostPCIDevices(driver, def) < 0)
- return -1;
-
- if (qemuPrepareHostUSBDevices(driver, def) < 0)
- return -1;
-
- return 0;
-}
-
-
static int
qemuPrepareChardevDevice(virDomainDefPtr def ATTRIBUTE_UNUSED,
virDomainChrDefPtr dev,
@@ -2966,80 +2778,6 @@ qemuPrepareChardevDevice(virDomainDefPtr def ATTRIBUTE_UNUSED,
}
-static void
-qemudReattachPciDevice(pciDevice *dev, struct qemud_driver *driver)
-{
- int retries = 100;
-
- while (pciWaitForDeviceCleanup(dev, "kvm_assigned_device")
- && retries) {
- usleep(100*1000);
- retries--;
- }
-
- if (pciDeviceGetManaged(dev)) {
- if (pciReAttachDevice(dev, driver->activePciHostdevs) < 0) {
- virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to re-attach PCI device: %s"),
- err ? err->message : _("unknown error"));
- virResetError(err);
- }
- }
-}
-
-static void
-qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
- virDomainHostdevDefPtr *hostdevs,
- int nhostdevs)
-{
- pciDeviceList *pcidevs;
- int i;
-
- if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs))) {
- virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to allocate pciDeviceList: %s"),
- err ? err->message : _("unknown error"));
- virResetError(err);
- return;
- }
-
- /* Again 3 loops; mark all devices as inactive before reset
- * them and reset all the devices before re-attach */
-
- for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
- pciDevice *dev = pciDeviceListGet(pcidevs, i);
- pciDeviceListDel(driver->activePciHostdevs, dev);
- }
-
- for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
- pciDevice *dev = pciDeviceListGet(pcidevs, i);
- if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0) {
- virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to reset PCI device: %s"),
- err ? err->message : _("unknown error"));
- virResetError(err);
- }
- }
-
- for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
- pciDevice *dev = pciDeviceListGet(pcidevs, i);
- qemudReattachPciDevice(dev, driver);
- }
-
- pciDeviceListFree(pcidevs);
-}
-
-static void
-qemuDomainReAttachHostDevices(struct qemud_driver *driver,
- virDomainDefPtr def)
-{
- if (!def->nhostdevs)
- return;
-
- qemuDomainReAttachHostdevDevices(driver, def->hostdevs, def->nhostdevs);
-}
-
-
struct qemudHookData {
virConnectPtr conn;
virDomainObjPtr vm;
@@ -8767,7 +8505,7 @@ static int qemudDomainDetachHostPciDevice(struct qemud_driver
*driver,
pciDeviceListDel(driver->activePciHostdevs, pci);
if (pciResetDevice(pci, driver->activePciHostdevs, NULL) < 0)
ret = -1;
- qemudReattachPciDevice(pci, driver);
+ qemuReattachPciDevice(pci, driver);
pciFreeDevice(pci);
}
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
new file mode 100644
index 0000000..f4b2108
--- /dev/null
+++ b/src/qemu/qemu_hostdev.c
@@ -0,0 +1,289 @@
+/*
+ * qemu_hostdev.c: QEMU hostdev management
+ *
+ * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include "qemu_hostdev.h"
+#include "logging.h"
+#include "virterror_internal.h"
+#include "memory.h"
+#include "pci.h"
+#include "hostusb.h"
+
+static pciDeviceList *
+qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs)
+{
+ pciDeviceList *list;
+ int i;
+
+ if (!(list = pciDeviceListNew()))
+ return NULL;
+
+ for (i = 0 ; i < nhostdevs ; i++) {
+ virDomainHostdevDefPtr hostdev = hostdevs[i];
+ pciDevice *dev;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ continue;
+
+ dev = pciGetDevice(hostdev->source.subsys.u.pci.domain,
+ hostdev->source.subsys.u.pci.bus,
+ hostdev->source.subsys.u.pci.slot,
+ hostdev->source.subsys.u.pci.function);
+ if (!dev) {
+ pciDeviceListFree(list);
+ return NULL;
+ }
+
+ if (pciDeviceListAdd(list, dev) < 0) {
+ pciFreeDevice(dev);
+ pciDeviceListFree(list);
+ return NULL;
+ }
+
+ pciDeviceSetManaged(dev, hostdev->managed);
+ }
+
+ return list;
+}
+
+
+int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
+ virDomainDefPtr def)
+{
+ pciDeviceList *pcidevs;
+ int i;
+ int ret = -1;
+
+ if (!def->nhostdevs)
+ return 0;
+
+ if (!(pcidevs = qemuGetPciHostDeviceList(def->hostdevs, def->nhostdevs)))
+ return -1;
+
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ pciDeviceListSteal(pcidevs, dev);
+ if (pciDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
+ pciFreeDevice(dev);
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ pciDeviceListFree(pcidevs);
+ return ret;
+}
+
+
+
+int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs)
+{
+ pciDeviceList *pcidevs;
+ int i;
+ int ret = -1;
+
+ if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs)))
+ return -1;
+
+ /* We have to use 3 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.
+ */
+
+ /* XXX 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 < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ if (!pciDeviceIsAssignable(dev, !driver->relaxedACS))
+ goto cleanup;
+
+ if (pciDeviceGetManaged(dev) &&
+ pciDettachDevice(dev, driver->activePciHostdevs) < 0)
+ goto cleanup;
+ }
+
+ /* Now that all the PCI hostdevs have be dettached, we can safely
+ * reset them */
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0)
+ goto cleanup;
+ }
+
+ /* Now mark all the devices as active */
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ pciDeviceListSteal(pcidevs, dev);
+ if (pciDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
+ pciFreeDevice(dev);
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ pciDeviceListFree(pcidevs);
+ return ret;
+}
+
+static int
+qemuPrepareHostPCIDevices(struct qemud_driver *driver,
+ virDomainDefPtr def)
+{
+ return qemuPrepareHostdevPCIDevices(driver, def->hostdevs, def->nhostdevs);
+}
+
+
+static int
+qemuPrepareHostUSBDevices(struct qemud_driver *driver ATTRIBUTE_UNUSED,
+ virDomainDefPtr def)
+{
+ int i;
+ for (i = 0 ; i < def->nhostdevs ; i++) {
+ virDomainHostdevDefPtr 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;
+
+ /* Resolve a vendor/product to bus/device */
+ if (hostdev->source.subsys.u.usb.vendor) {
+ usbDevice *usb
+ = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
+ hostdev->source.subsys.u.usb.product);
+
+ if (!usb)
+ return -1;
+
+ hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
+ hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);
+
+ usbFreeDevice(usb);
+ }
+ }
+
+ return 0;
+}
+
+
+int qemuPrepareHostDevices(struct qemud_driver *driver,
+ virDomainDefPtr def)
+{
+ if (!def->nhostdevs)
+ return 0;
+
+ if (qemuPrepareHostPCIDevices(driver, def) < 0)
+ return -1;
+
+ if (qemuPrepareHostUSBDevices(driver, def) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+void qemuReattachPciDevice(pciDevice *dev, struct qemud_driver *driver)
+{
+ int retries = 100;
+
+ while (pciWaitForDeviceCleanup(dev, "kvm_assigned_device")
+ && retries) {
+ usleep(100*1000);
+ retries--;
+ }
+
+ if (pciDeviceGetManaged(dev)) {
+ if (pciReAttachDevice(dev, driver->activePciHostdevs) < 0) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to re-attach PCI device: %s"),
+ err ? err->message : _("unknown error"));
+ virResetError(err);
+ }
+ }
+}
+
+
+void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs)
+{
+ pciDeviceList *pcidevs;
+ int i;
+
+ if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs))) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to allocate pciDeviceList: %s"),
+ err ? err->message : _("unknown error"));
+ virResetError(err);
+ return;
+ }
+
+ /* Again 3 loops; mark all devices as inactive before reset
+ * them and reset all the devices before re-attach */
+
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ pciDeviceListDel(driver->activePciHostdevs, dev);
+ }
+
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to reset PCI device: %s"),
+ err ? err->message : _("unknown error"));
+ virResetError(err);
+ }
+ }
+
+ for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
+ pciDevice *dev = pciDeviceListGet(pcidevs, i);
+ qemuReattachPciDevice(dev, driver);
+ }
+
+ pciDeviceListFree(pcidevs);
+}
+
+
+void qemuDomainReAttachHostDevices(struct qemud_driver *driver,
+ virDomainDefPtr def)
+{
+ if (!def->nhostdevs)
+ return;
+
+ qemuDomainReAttachHostdevDevices(driver, def->hostdevs, def->nhostdevs);
+}
diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h
new file mode 100644
index 0000000..96181b5
--- /dev/null
+++ b/src/qemu/qemu_hostdev.h
@@ -0,0 +1,45 @@
+/*
+ * qemu_hostdev.h: QEMU hostdev management
+ *
+ * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#ifndef __QEMU_HOSTDEV_H__
+# define __QEMU_HOSTDEV_H__
+
+#include "qemu_conf.h"
+#include "domain_conf.h"
+
+int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
+ virDomainDefPtr def);
+int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs);
+int qemuPrepareHostDevices(struct qemud_driver *driver,
+ virDomainDefPtr def);
+void qemuReattachPciDevice(pciDevice *dev, struct qemud_driver *driver);
+void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs);
+void qemuDomainReAttachHostDevices(struct qemud_driver *driver,
+ virDomainDefPtr def);
+
+
+#endif /* __QEMU_HOSTDEV_H__ */
--
1.7.2.3