[libvirt] [PATCH 2/5] nodedev: add <devnode> paths

marcandre.lureau at redhat.com marcandre.lureau at redhat.com
Tue Feb 14 21:04:10 UTC 2017


From: Marc-André Lureau <marcandre.lureau at 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 at 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




More information about the libvir-list mailing list