This adds a new <hostdev managed='(yes|no)'> property
indicating whether or not we should automatically
dettach/reset.
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
---
docs/schemas/domain.rng | 6 +++
src/domain_conf.c | 12 +++++-
src/domain_conf.h | 1 +
src/qemu_conf.c | 42 ++++++++++++++++++++
.../qemuxml2argv-hostdev-pci-address.xml | 2 +-
.../qemuxml2argv-hostdev-usb-address.xml | 2 +-
.../qemuxml2argv-hostdev-usb-product.xml | 2 +-
7 files changed, 62 insertions(+), 5 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 04f6e78..8bd3ffb 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -911,6 +911,12 @@
<value>pci</value>
</choice>
</attribute>
+ <attribute name='managed'>
+ <choice>
+ <value>yes</value>
+ <value>no</value>
+ </choice>
+ </attribute>
</optional>
<group>
<element name='source'>
diff --git a/src/domain_conf.c b/src/domain_conf.c
index 622665c..23618b9 100644
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -1729,7 +1729,7 @@ virDomainHostdevDefParseXML(virConnectPtr conn,
xmlNodePtr cur;
virDomainHostdevDefPtr def;
- char *mode, *type = NULL;
+ char *mode, *type = NULL, *managed = NULL;
if (VIR_ALLOC(def) < 0) {
virReportOOMError(conn);
@@ -1761,6 +1761,13 @@ virDomainHostdevDefParseXML(virConnectPtr conn,
goto error;
}
+ managed = virXMLPropString(node, "managed");
+ if (managed != NULL) {
+ if (STREQ(managed, "yes"))
+ def->managed = 1;
+ VIR_FREE(managed);
+ }
+
cur = node->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE) {
@@ -3185,7 +3192,8 @@ virDomainHostdevDefFormat(virConnectPtr conn,
return -1;
}
- virBufferVSprintf(buf, " <hostdev mode='%s'
type='%s'>\n", mode, type);
+ virBufferVSprintf(buf, " <hostdev mode='%s' type='%s'
managed='%s'>\n",
+ mode, type, def->managed ? "yes" : "no");
virBufferAddLit(buf, " <source>\n");
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
diff --git a/src/domain_conf.h b/src/domain_conf.h
index b6f6b43..d370b5d 100644
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -305,6 +305,7 @@ typedef struct _virDomainHostdevDef virDomainHostdevDef;
typedef virDomainHostdevDef *virDomainHostdevDefPtr;
struct _virDomainHostdevDef {
int mode; /* enum virDomainHostdevMode */
+ unsigned int managed : 1;
union {
struct {
int type; /* enum virDomainHostdevBusType */
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 6f58ee8..fad3eeb 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -47,6 +47,7 @@
#include "datatypes.h"
#include "xml.h"
#include "nodeinfo.h"
+#include "pci.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -1394,10 +1395,51 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT("-pcidevice");
ADD_ARG_LIT(pcidev);
VIR_FREE(pcidev);
+
+ if (hostdev->managed) {
+ pciDevice *dev = pciGetDevice(conn,
+ 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)
+ goto error;
+
+ if (pciDettachDevice(conn, dev) < 0) {
+ pciFreeDevice(conn, dev);
+ goto error;
+ }
+
+ pciFreeDevice(conn, dev);
+ }
}
}
+ /* Now that all the PCI hostdevs have be dettached, we can reset them */
+ for (i = 0 ; i < vm->def->nhostdevs ; i++) {
+ virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
+ pciDevice *dev;
+
+ if (!hostdev->managed ||
+ hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+ hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ continue;
+
+ dev = pciGetDevice(conn,
+ 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)
+ goto error;
+
+ if (pciResetDevice(conn, dev) < 0)
+ goto error;
+
+ pciFreeDevice(conn, dev);
+ }
+
if (migrateFrom) {
ADD_ARG_LIT("-incoming");
ADD_ARG_LIT(migrateFrom);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address.xml
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address.xml
index af2f400..9a6207e 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address.xml
@@ -18,7 +18,7 @@
<source dev='/dev/HostVG/QEMUGuest2'/>
<target dev='hda' bus='ide'/>
</disk>
- <hostdev mode='subsystem' type='pci'>
+ <hostdev mode='subsystem' type='pci' managed='no'>
<source>
<address domain='0x0000' bus='0x06' slot='0x12'
function='0x5'/>
</source>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-address.xml
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-address.xml
index 0c044e1..61bb2a2 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-address.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-address.xml
@@ -18,7 +18,7 @@
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
</disk>
- <hostdev mode='subsystem' type='usb'>
+ <hostdev mode='subsystem' type='usb' managed='no'>
<source>
<address bus='14' device='6'/>
</source>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-product.xml
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-product.xml
index aecad4c..b861665 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-product.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-usb-product.xml
@@ -18,7 +18,7 @@
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
</disk>
- <hostdev mode='subsystem' type='usb'>
+ <hostdev mode='subsystem' type='usb' managed='no'>
<source>
<vendor id='0x0204'/>
<product id='0x6025'/>
--
1.6.0.6