From 0809508ed2da6d13cba8a2e1c54602f2652b4c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 15 Feb 2017 01:04:10 +0400 Subject: [PATCH] nodedev: add paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new top-level 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 --- 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 +++++++++++ ...rial_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 f8d0e12340..ecdd1dbcb4 100644 --- a/docs/formatnode.html.in +++ b/docs/formatnode.html.in @@ -37,6 +37,12 @@
If this element is present, it names the parent device (that is, a controller to which this node belongs).
+
devnode
+
This node appears for each associated /dev + special file. A mandatory attribute type specify + the kind of file path, which may be either dev for + the main name, or link for additional symlinks. +
capability
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 b100a6e16d..62e29b6cc1 100644 --- a/docs/schemas/nodedev.rng +++ b/docs/schemas/nodedev.rng @@ -15,6 +15,22 @@ + + + + dev + + + + + + + + link + + + + diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index f37a48c404..91a76586c0 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, "%s\n", def->name); virBufferEscapeString(&buf, "%s\n", def->sysfs_path); + if (def->devnode) + virBufferEscapeString(&buf, "%s\n", + def->devnode); + if (def->devlinks) { + for (i = 0; def->devlinks[i]; i++) + virBufferEscapeString(&buf, "%s\n", + def->devlinks[i]); + } if (def->parent) virBufferEscapeString(&buf, "%s\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 1634483339..f46e9841ae 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -38,6 +38,16 @@ # define CREATE_DEVICE 1 # define EXISTING_DEVICE 0 +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 */ @@ -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 4b813127cb..d7658410a9 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -917,6 +917,34 @@ udevProcessSCSIGeneric(struct udev_device *dev, return 0; } +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 d9d61da44a..d225dca8fa 100644 --- a/tests/nodedevschemadata/storage_serial_3600c0ff000d7a2a5d463ff4902000000.xml +++ b/tests/nodedevschemadata/storage_serial_3600c0ff000d7a2a5d463ff4902000000.xml @@ -1,5 +1,9 @@ storage_serial_3600c0ff000d7a2a5d463ff4902000000 + /dev/sdb + /dev/disk/by-id/usb-SanDisk_Ultra_Fit_4C530001051009112405-0:0 + /dev/disk/by-path/pci-0000:00:14.0-usb-0:1:1.0-scsi-0:0:0:0 + /dev/disk/by-uuid/661A1A460111DA18 pci_10df_fe00_scsi_host_scsi_device_lun8 /dev/sdj diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index eb32dd31d2..ec96943cb1 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");