From: Marc-André Lureau <marcandre.lureau(a)redhat.com>
Add new <devnode> top-level <device> element, that list the associated
/dev files. Distinguish the main /dev name from symlinks with a 'type'
attribute of value 'dev' or 'symlink'.
Update a test to check XML schema, and actually add it to the test list
since it was missing.
Signed-off-by: Marc-André Lureau <marcandre.lureau(a)redhat.com>
---
docs/formatnode.html.in | 6 +++
docs/schemas/nodedev.rng | 16 +++++++
src/conf/node_device_conf.c | 54 +++++++++++++++++++++-
src/conf/node_device_conf.h | 12 +++++
src/node_device/node_device_udev.c | 31 +++++++++++++
...ge_serial_3600c0ff000d7a2a5d463ff4902000000.xml | 4 ++
tests/nodedevxml2xmltest.c | 1 +
7 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/docs/formatnode.html.in b/docs/formatnode.html.in
index f8d0e1234..ecdd1dbcb 100644
--- a/docs/formatnode.html.in
+++ b/docs/formatnode.html.in
@@ -37,6 +37,12 @@
<dd>If this element is present, it names the parent device (that
is, a controller to which this node belongs).
</dd>
+ <dt><code>devnode</code></dt>
+ <dd>This node appears for each associated <code>/dev</code>
+ special file. A mandatory attribute <code>type</code> specify
+ the kind of file path, which may be either <code>dev</code> for
+ the main name, or <code>link</code> for additional symlinks.
+ </dd>
<dt><code>capability</code></dt>
<dd>This node appears for each capability that libvirt
associates with a node. A mandatory
diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng
index b100a6e16..62e29b6cc 100644
--- a/docs/schemas/nodedev.rng
+++ b/docs/schemas/nodedev.rng
@@ -16,6 +16,22 @@
<element name="path"><text/></element>
</optional>
<optional>
+ <element name="devnode">
+ <attribute name='type'>
+ <value>dev</value>
+ </attribute>
+ <text/>
+ </element>
+ </optional>
+ <zeroOrMore>
+ <element name="devnode">
+ <attribute name='type'>
+ <value>link</value>
+ </attribute>
+ <text/>
+ </element>
+ </zeroOrMore>
+ <optional>
<ref name="parent"/>
</optional>
diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index 6163fd5ed..49ecc8897 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -40,6 +40,10 @@
#define VIR_FROM_THIS VIR_FROM_NODEDEV
+VIR_ENUM_IMPL(virNodeDevDevnode, VIR_NODE_DEV_DEVNODE_LAST,
+ "dev",
+ "link")
+
VIR_ENUM_IMPL(virNodeDevCap, VIR_NODE_DEV_CAP_LAST,
"system",
"pci",
@@ -252,6 +256,8 @@ void virNodeDeviceDefFree(virNodeDeviceDefPtr def)
VIR_FREE(def->driver);
VIR_FREE(def->sysfs_path);
VIR_FREE(def->parent_sysfs_path);
+ VIR_FREE(def->devnode);
+ virStringListFree(def->devlinks);
caps = def->caps;
while (caps) {
@@ -387,6 +393,14 @@ char *virNodeDeviceDefFormat(const virNodeDeviceDef *def)
virBufferAdjustIndent(&buf, 2);
virBufferEscapeString(&buf, "<name>%s</name>\n",
def->name);
virBufferEscapeString(&buf, "<path>%s</path>\n",
def->sysfs_path);
+ if (def->devnode)
+ virBufferEscapeString(&buf, "<devnode
type='dev'>%s</devnode>\n",
+ def->devnode);
+ if (def->devlinks) {
+ for (i = 0; def->devlinks[i]; i++)
+ virBufferEscapeString(&buf, "<devnode
type='link'>%s</devnode>\n",
+ def->devlinks[i]);
+ }
if (def->parent)
virBufferEscapeString(&buf, "<parent>%s</parent>\n",
def->parent);
if (def->driver) {
@@ -1703,7 +1717,7 @@ virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt,
virNodeDeviceDefPtr def;
virNodeDevCapsDefPtr *next_cap;
xmlNodePtr *nodes;
- int n;
+ int n, m;
size_t i;
if (VIR_ALLOC(def) < 0)
@@ -1722,6 +1736,44 @@ virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt,
goto error;
}
+ /* Parse devnodes */
+ nodes = NULL;
+ if ((n = virXPathNodeSet("./devnode", ctxt, &nodes)) < 0)
+ goto error;
+
+ if (VIR_ALLOC_N(def->devlinks, n + 1) < 0)
+ goto error;
+
+ for (i = 0, m = 0; i < n; i++) {
+ xmlNodePtr node = nodes[i];
+ char *tmp = virXMLPropString(node, "type");
+ virNodeDevDevnodeType type;
+
+ if (!tmp) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing devnode type"));
+ goto error;
+ }
+
+ if ((type = virNodeDevDevnodeTypeFromString(tmp)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown devnode type '%s'"), tmp);
+ VIR_FREE(tmp);
+ goto error;
+ }
+
+ switch (type) {
+ case VIR_NODE_DEV_DEVNODE_DEV:
+ def->devnode = (char*)xmlNodeGetContent(node);
+ break;
+ case VIR_NODE_DEV_DEVNODE_LINK:
+ def->devlinks[m++] = (char*)xmlNodeGetContent(node);
+ break;
+ case VIR_NODE_DEV_DEVNODE_LAST:
+ break;
+ }
+ }
+
/* Extract device parent, if any */
def->parent = virXPathString("string(./parent[1])", ctxt);
def->parent_wwnn = virXPathString("string(./parent[1]/@wwnn)", ctxt);
diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
index 163448333..f46e9841a 100644
--- a/src/conf/node_device_conf.h
+++ b/src/conf/node_device_conf.h
@@ -40,6 +40,16 @@
typedef enum {
/* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */
+ VIR_NODE_DEV_DEVNODE_DEV,
+ VIR_NODE_DEV_DEVNODE_LINK,
+
+ VIR_NODE_DEV_DEVNODE_LAST
+} virNodeDevDevnodeType;
+
+VIR_ENUM_DECL(virNodeDevDevnode)
+
+typedef enum {
+ /* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */
VIR_NODE_DEV_CAP_SYSTEM, /* System capability */
VIR_NODE_DEV_CAP_PCI_DEV, /* PCI device */
VIR_NODE_DEV_CAP_USB_DEV, /* USB device */
@@ -204,6 +214,8 @@ struct _virNodeDeviceDef {
char *parent_wwpn; /* optional parent wwpn */
char *parent_fabric_wwn; /* optional parent fabric_wwn */
char *driver; /* optional driver name */
+ char *devnode; /* /dev path */
+ char **devlinks; /* /dev links */
virNodeDevCapsDefPtr caps; /* optional device capabilities */
};
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 4b813127c..d7658410a 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -918,6 +918,34 @@ udevProcessSCSIGeneric(struct udev_device *dev,
}
static int
+udevGetDeviceNodes(struct udev_device *device,
+ virNodeDeviceDefPtr def)
+{
+ const char *devnode = NULL;
+ struct udev_list_entry *list_entry = NULL;
+ int n = 0;
+
+ devnode = udev_device_get_devnode(device);
+
+ if (VIR_STRDUP(def->devnode, devnode) < 0)
+ return -1;
+
+ udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device))
+ n++;
+
+ if (VIR_ALLOC_N(def->devlinks, n + 1) < 0)
+ return -1;
+
+ n = 0;
+ udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
+ if (VIR_STRDUP(def->devlinks[n++], udev_list_entry_get_name(list_entry)) <
0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
udevGetDeviceType(struct udev_device *device,
virNodeDevCapType *type)
{
@@ -1125,6 +1153,9 @@ static int udevAddOneDevice(struct udev_device *device)
if (udevGetDeviceType(device, &def->caps->data.type) != 0)
goto cleanup;
+ if (udevGetDeviceNodes(device, def) != 0)
+ goto cleanup;
+
if (udevGetDeviceDetails(device, def) != 0)
goto cleanup;
diff --git a/tests/nodedevschemadata/storage_serial_3600c0ff000d7a2a5d463ff4902000000.xml
b/tests/nodedevschemadata/storage_serial_3600c0ff000d7a2a5d463ff4902000000.xml
index d9d61da44..d225dca8f 100644
--- a/tests/nodedevschemadata/storage_serial_3600c0ff000d7a2a5d463ff4902000000.xml
+++ b/tests/nodedevschemadata/storage_serial_3600c0ff000d7a2a5d463ff4902000000.xml
@@ -1,5 +1,9 @@
<device>
<name>storage_serial_3600c0ff000d7a2a5d463ff4902000000</name>
+ <devnode type='dev'>/dev/sdb</devnode>
+ <devnode
type='link'>/dev/disk/by-id/usb-SanDisk_Ultra_Fit_4C530001051009112405-0:0</devnode>
+ <devnode
type='link'>/dev/disk/by-path/pci-0000:00:14.0-usb-0:1:1.0-scsi-0:0:0:0</devnode>
+ <devnode type='link'>/dev/disk/by-uuid/661A1A460111DA18</devnode>
<parent>pci_10df_fe00_scsi_host_scsi_device_lun8</parent>
<capability type='storage'>
<block>/dev/sdj</block>
diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c
index eb32dd31d..ec96943cb 100644
--- a/tests/nodedevxml2xmltest.c
+++ b/tests/nodedevxml2xmltest.c
@@ -87,6 +87,7 @@ mymain(void)
DO_TEST("pci_8086_27c5_scsi_host_scsi_host");
DO_TEST("pci_8086_27c5_scsi_host");
DO_TEST("storage_serial_SATA_HTS721010G9SA00_MPCZ12Y0GNGWSE");
+ DO_TEST("storage_serial_3600c0ff000d7a2a5d463ff4902000000");
DO_TEST("usb_device_1d6b_1_0000_00_1d_0_if0");
DO_TEST("usb_device_1d6b_1_0000_00_1d_0");
DO_TEST("pci_8086_4238_pcie_wireless");
--
2.11.0.295.gd7dffce1c.dirty