From: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list