Rather than requiring that hostdev sources be specified
using the PCI/USB addresses, allow them to be specified
using the node device name.
The patch includes documentation and test updates, but
does not implement support in any driver.
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
---
ChangeLog | 12 +++++
docs/formatdomain.html | 26 +++++++---
docs/formatdomain.html.in | 29 +++++++---
docs/schemas/domain.rng | 10 ++++
src/domain_conf.c | 53 +++++++++++++++++++-
src/domain_conf.h | 2 +
.../qemuxml2argv-hostdev-nodedev-name.xml | 27 ++++++++++
tests/qemuxml2argvtest.c | 5 ++
tests/qemuxml2xmltest.c | 1 +
9 files changed, 146 insertions(+), 19 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-nodedev-name.xml
diff --git a/ChangeLog b/ChangeLog
index 4f2c125..4bd87a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+Tue Feb 24 22:27:12 GMT 2009 Mark McLoughlin <markmc(a)redhat.com>
+
+ * src/domain_conf.[ch]: Allow supplying a node
+ device name as hostdev source
+
+ * docs/formatdomain.html, docs/schemas/domain.rng:
+ documentation updates
+
+ * tests/qemuxml2argvdata/qemuxml2argv-hostdev-nodedev-name.xml,
+ tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c: test
+ updates
+
Tue Feb 24 22:09:40 GMT 2009 Mark McLoughlin <markmc(a)redhat.com>
* src/virsh.c: add new commands for each of the new
diff --git a/docs/formatdomain.html b/docs/formatdomain.html
index 17dc0cd..11ea697 100644
--- a/docs/formatdomain.html
+++ b/docs/formatdomain.html
@@ -473,6 +473,15 @@
</p>
<pre>
...
+ <hostdev mode='subsystem' type='nodedev'>
+ <source>
+ <nodedev name='pci_8086_109a'/>
+ </source>
+ </hostdev>
+ ...</pre>
+ <p>or:</p>
+ <pre>
+ ...
<hostdev mode='subsystem' type='usb'>
<source>
<vendor id='0x1234'/>
@@ -490,15 +499,16 @@
</hostdev>
...</pre>
<dl><dt><code>hostdev</code></dt><dd>The
<code>hostdev</code> element is the main container for describing
- host devices. For usb device passthrough <code>mode</code> is always
- "subsystem" and <code>type</code> is "usb" for an
USB device and "pci"
- for a PCI device..
+ host devices. For USB or PCI device passthrough <code>mode</code> is
always
+ "subsystem" and <code>type</code> is either "usb",
"pci" or "nodedev".
</dd><dt><code>source</code></dt><dd>The source
element describes the device as seen from the host.
- The USB device can either be addressed by vendor / product id using the
- <code>vendor</code> and <code>product</code> elements or by
the device's
- address on the hosts using the <code>address</code> element.
- PCI devices on the other hand can only be described by their
-
<code>address</code></dd><dt><code>vendor</code>,
<code>product</code></dt><dd>The <code>vendor</code>
and <code>product</code> elements each have an
+ With <code>type</code> "nodedev", USB and PCI devices can be
described
+ using their node device name as listed by <code>virsh
nodedev-list</code>.
+ Alternatively, USB devices can either be addressed by vendor / product id
+ using the <code>vendor</code> and <code>product</code>
elements or by the
+ device's address on the hosts using the <code>address</code>
element.
+ PCI devices can be described by their
<code>address</code>.</dd><dt><code>nodedev</code></dt><dd>The
<code>nodedev</code> element describes a USB or PCI device using
+ its node device name as listed by <code>virsh
nodedev-list</code>.</dd><dt><code>vendor</code>,
<code>product</code></dt><dd>The <code>vendor</code>
and <code>product</code> elements each have an
<code>id</code> attribute that specifies the USB vendor and product
id.
The ids can be given in decimal, hexadecimal (starting with 0x) or
octal (starting with 0)
form.</dd><dt><code>address</code></dt><dd>The
<code>address</code> element for USB devices has a
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index ee32354..a661b02 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -385,6 +385,15 @@
<pre>
...
+ <hostdev mode='subsystem' type='nodedev'>
+ <source>
+ <nodedev name='pci_8086_109a'/>
+ </source>
+ </hostdev>
+ ...</pre>
+ <p>or:</p>
+ <pre>
+ ...
<hostdev mode='subsystem' type='usb'>
<source>
<vendor id='0x1234'/>
@@ -401,20 +410,22 @@
</source>
</hostdev>
...</pre>
-
<dl>
<dt><code>hostdev</code></dt>
<dd>The <code>hostdev</code> element is the main container for
describing
- host devices. For usb device passthrough <code>mode</code> is always
- "subsystem" and <code>type</code> is "usb" for an
USB device and "pci"
- for a PCI device..
+ host devices. For USB or PCI device passthrough <code>mode</code> is
always
+ "subsystem" and <code>type</code> is either "usb",
"pci" or "nodedev".
<dt><code>source</code></dt>
<dd>The source element describes the device as seen from the host.
- The USB device can either be addressed by vendor / product id using the
- <code>vendor</code> and <code>product</code> elements or by
the device's
- address on the hosts using the <code>address</code> element.
- PCI devices on the other hand can only be described by their
- <code>address</code></dd>
+ With <code>type</code> "nodedev", USB and PCI devices can be
described
+ using their node device name as listed by <code>virsh
nodedev-list</code>.
+ Alternatively, USB devices can either be addressed by vendor / product id
+ using the <code>vendor</code> and <code>product</code>
elements or by the
+ device's address on the hosts using the <code>address</code>
element.
+ PCI devices can be described by their <code>address</code>.</dd>
+ <dt><code>nodedev</code></dt>
+ <dd>The <code>nodedev</code> element describes a USB or PCI
device using
+ its node device name as listed by <code>virsh
nodedev-list</code>.</dd>
<dt><code>vendor</code>,
<code>product</code></dt>
<dd>The <code>vendor</code> and <code>product</code>
elements each have an
<code>id</code> attribute that specifies the USB vendor and product
id.
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 04f6e78..3dfbddb 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -909,6 +909,7 @@
<choice>
<value>usb</value>
<value>pci</value>
+ <value>nodedev</value>
</choice>
</attribute>
</optional>
@@ -918,6 +919,7 @@
<ref name="usbproduct"/>
<ref name="usbaddress"/>
<ref name="pciaddress"/>
+ <ref name="nodedev"/>
</choice>
</element>
</group>
@@ -966,6 +968,14 @@
</attribute>
</element>
</define>
+
+ <define name="nodedev">
+ <element name="nodedev">
+ <attribute name="name">
+ <ref name="genericName"/>
+ </attribute>
+ </element>
+ </define>
<!--
Devices attached to a domain.
-->
diff --git a/src/domain_conf.c b/src/domain_conf.c
index 622665c..1ad52f1 100644
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -149,7 +149,8 @@ VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
"usb",
- "pci")
+ "pci",
+ "nodedev")
VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_CRASHED+1,
"nostate",
@@ -349,6 +350,10 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def)
if (!def)
return;
+ if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_NODEDEV)
+ VIR_FREE(def->source.subsys.u.nodedev_name);
+
VIR_FREE(def->target);
VIR_FREE(def);
}
@@ -1721,6 +1726,38 @@ out:
return ret;
}
+static int
+virDomainHostdevSubsysNodedevDefParseXML(virConnectPtr conn,
+ const xmlNodePtr node,
+ virDomainHostdevDefPtr def) {
+
+ int ret = -1;
+ xmlNodePtr cur;
+
+ cur = node->children;
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ if (xmlStrEqual(cur->name, BAD_CAST "nodedev")) {
+ def->source.subsys.u.nodedev_name = virXMLPropString(cur,
"name");
+ if (!def->source.subsys.u.nodedev_name) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing node device name"));
+ goto out;
+ }
+ } else {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unknown nodedev source type
'%s'"),
+ cur->name);
+ goto out;
+ }
+ }
+ cur = cur->next;
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
static virDomainHostdevDefPtr
virDomainHostdevDefParseXML(virConnectPtr conn,
@@ -1776,6 +1813,11 @@ virDomainHostdevDefParseXML(virConnectPtr conn,
if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def) < 0)
goto error;
}
+ if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_NODEDEV)
{
+ if (virDomainHostdevSubsysNodedevDefParseXML(conn, cur, def) <
0)
+ goto error;
+ }
} else {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("unknown node %s"), cur->name);
@@ -3178,7 +3220,10 @@ virDomainHostdevDefFormat(virConnectPtr conn,
}
type = virDomainHostdevSubsysTypeToString(def->source.subsys.type);
- if (!type || (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB
&& def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) ) {
+ if (!type ||
+ (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
+ def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
+ def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_NODEDEV) ) {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("unexpected hostdev type %d"),
def->source.subsys.type);
@@ -3207,6 +3252,10 @@ virDomainHostdevDefFormat(virConnectPtr conn,
def->source.subsys.u.pci.slot,
def->source.subsys.u.pci.function);
}
+ if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_NODEDEV) {
+ virBufferVSprintf(buf, " <nodedev name='%s'/>\n",
+ def->source.subsys.u.nodedev_name);
+ }
virBufferAddLit(buf, " </source>\n");
virBufferAddLit(buf, " </hostdev>\n");
diff --git a/src/domain_conf.h b/src/domain_conf.h
index b6f6b43..bde3417 100644
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -297,6 +297,7 @@ enum virDomainHostdevMode {
enum virDomainHostdevSubsysType {
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB,
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI,
+ VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_NODEDEV,
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST
};
@@ -322,6 +323,7 @@ struct _virDomainHostdevDef {
unsigned slot;
unsigned function;
} pci;
+ char *nodedev_name;
} u;
} subsys;
struct {
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-nodedev-name.xml
b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-nodedev-name.xml
new file mode 100644
index 0000000..96c6112
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-nodedev-name.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ </disk>
+ <hostdev mode='subsystem' type='nodedev'>
+ <source>
+ <nodedev name='pci_8086_109a'/>
+ </source>
+ </hostdev>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 90b4740..9490d0b 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -245,6 +245,11 @@ mymain(int argc, char **argv)
DO_TEST("hostdev-pci-address", 0);
+ /* Cannot resolve node device names here
+ *
+ * DO_TEST("hostdev-nodedev-name", 0);
+ */
+
DO_TEST_FULL("restore-v1", QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO,
"stdio");
DO_TEST_FULL("restore-v2", QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC,
"stdio");
DO_TEST_FULL("restore-v2", QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC,
"exec:cat");
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index ab9943d..5ccace8 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -130,6 +130,7 @@ mymain(int argc, char **argv)
DO_TEST("hostdev-usb-product");
DO_TEST("hostdev-usb-address");
DO_TEST("hostdev-pci-address");
+ DO_TEST("hostdev-nodedev-name");
virCapabilitiesFree(driver.caps);
--
1.6.0.6