[libvirt] PATCH: Include OS driver name in device information

This patch extends the node device XML from $ virsh nodedev-dumpxml pci_8086_27d6 <device> <name>pci_8086_27d6</name> <parent>computer</parent> <capability type='pci'> <domain>0</domain> <bus>0</bus> <slot>28</slot> <function>3</function> <product id='0x27d6'>82801G (ICH7 Family) PCI Express Port 4</product> <vendor id='0x8086'>Intel Corporation</vendor> </capability> </device> To, also include the operating system driver name. $ virsh nodedev-dumpxml pci_8086_27d6 <device> <name>pci_8086_27d6</name> <parent>computer</parent> <driver> <name>pcieport-driver</name> </driver> <capability type='pci'> <domain>0</domain> <bus>0</bus> <slot>28</slot> <function>3</function> <product id='0x27d6'>82801G (ICH7 Family) PCI Express Port 4</product> <vendor id='0x8086'>Intel Corporation</vendor> </capability> </device> We're not defining any particular semantics for the driver name, it is just a opaque string following rules of the OS in question. Daniel diff -r ec78a5d6c00c src/node_device.c --- a/src/node_device.c Thu May 28 14:42:24 2009 +0100 +++ b/src/node_device.c Thu May 28 16:00:12 2009 +0100 @@ -46,6 +46,60 @@ static int dev_has_cap(const virNodeDevi return 0; } +#ifdef __linux__ +static int update_driver_name(virConnectPtr conn, + virNodeDeviceObjPtr dev) +{ + char *driver_link = NULL; + char devpath[PATH_MAX]; + char *p; + int ret = -1; + int n; + + VIR_FREE(dev->def->driver); + + if (virAsprintf(&driver_link, "%s/driver", dev->devicePath) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + /* Some devices don't have an explicit driver, so just return + without a name */ + if (access(driver_link, R_OK) < 0) { + ret = 0; + goto cleanup; + } + + if ((n = readlink(driver_link, devpath, sizeof devpath)) < 0) { + virReportSystemError(conn, errno, + _("cannot resolve driver link %s"), driver_link); + goto cleanup; + } + devpath[n] = '\0'; + + p = strrchr(devpath, '/'); + if (p) { + dev->def->driver = strdup(p+1); + if (!dev->def->driver) { + virReportOOMError(conn); + goto cleanup; + } + } + ret = 0; + +cleanup: + VIR_FREE(driver_link); + return ret; +} +#else +/* XXX: Implement me for non-linux */ +static int update_driver_name(virConnectPtr conn ATTRIBUTE_UNUSED, + virNodeDeviceObjPtr dev ATTRIBUTE_UNUSED) +{ + return 0; +} +#endif + void nodeDeviceLock(virDeviceMonitorStatePtr driver) { @@ -150,6 +204,7 @@ static char *nodeDeviceDumpXML(virNodeDe goto cleanup; } + update_driver_name(dev->conn, obj); ret = virNodeDeviceDefFormat(dev->conn, obj->def); cleanup: diff -r ec78a5d6c00c src/node_device_conf.c --- a/src/node_device_conf.c Thu May 28 14:42:24 2009 +0100 +++ b/src/node_device_conf.c Thu May 28 16:00:12 2009 +0100 @@ -78,6 +78,7 @@ void virNodeDeviceDefFree(virNodeDeviceD VIR_FREE(def->name); VIR_FREE(def->parent); + VIR_FREE(def->driver); caps = def->caps; while (caps) { @@ -94,6 +95,7 @@ void virNodeDeviceObjFree(virNodeDeviceO if (!dev) return; + VIR_FREE(dev->devicePath); virNodeDeviceDefFree(dev->def); if (dev->privateFree) (*dev->privateFree)(dev->privateData); @@ -191,6 +193,11 @@ char *virNodeDeviceDefFormat(virConnectP if (def->parent) virBufferEscapeString(&buf, " <parent>%s</parent>\n", def->parent); + if (def->driver) { + virBufferAddLit(&buf, " <driver>\n"); + virBufferEscapeString(&buf, " <name>%s</name>\n", def->driver); + virBufferAddLit(&buf, " </driver>\n"); + } for (caps = def->caps; caps; caps = caps->next) { char uuidstr[VIR_UUID_STRING_BUFLEN]; diff -r ec78a5d6c00c src/node_device_conf.h --- a/src/node_device_conf.h Thu May 28 14:42:24 2009 +0100 +++ b/src/node_device_conf.h Thu May 28 16:00:12 2009 +0100 @@ -136,6 +136,7 @@ typedef virNodeDeviceDef *virNodeDeviceD struct _virNodeDeviceDef { char *name; /* device name (unique on node) */ char *parent; /* optional parent device name */ + char *driver; /* optional driver name */ virNodeDevCapsDefPtr caps; /* optional device capabilities */ }; @@ -145,6 +146,7 @@ typedef virNodeDeviceObj *virNodeDeviceO struct _virNodeDeviceObj { virMutex lock; + char *devicePath; /* OS specific path to device metadat, eg sysfs */ virNodeDeviceDefPtr def; /* device definition */ void *privateData; /* driver-specific private data */ void (*privateFree)(void *data); /* destructor for private data */ diff -r ec78a5d6c00c src/node_device_hal.c --- a/src/node_device_hal.c Thu May 28 14:42:24 2009 +0100 +++ b/src/node_device_hal.c Thu May 28 16:00:12 2009 +0100 @@ -413,6 +413,7 @@ static void dev_create(const char *udi) const char *name = hal_name(udi); int rv; char *privData = strdup(udi); + char *devicePath = NULL; if (!privData) return; @@ -439,15 +440,22 @@ static void dev_create(const char *udi) if (def->caps == NULL) goto cleanup; + /* Some devices don't have a path in sysfs, so ignore failure */ + get_str_prop(ctx, udi, "linux.sysfs_path", &devicePath); + dev = virNodeDeviceAssignDef(NULL, &driverState->devs, def); - if (!dev) + if (!dev) { + VIR_FREE(devicePath); goto failure; + } dev->privateData = privData; dev->privateFree = free_udi; + dev->devicePath = devicePath; + virNodeDeviceObjUnlock(dev); nodeDeviceUnlock(driverState); -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Fri, May 29, 2009 at 02:39:09PM +0100, Daniel P. Berrange wrote:
This patch extends the node device XML from
$ virsh nodedev-dumpxml pci_8086_27d6 <device> <name>pci_8086_27d6</name> <parent>computer</parent> <capability type='pci'> <domain>0</domain> <bus>0</bus> <slot>28</slot> <function>3</function> <product id='0x27d6'>82801G (ICH7 Family) PCI Express Port 4</product> <vendor id='0x8086'>Intel Corporation</vendor> </capability> </device>
To, also include the operating system driver name.
$ virsh nodedev-dumpxml pci_8086_27d6 <device> <name>pci_8086_27d6</name> <parent>computer</parent> <driver> <name>pcieport-driver</name> </driver> <capability type='pci'> <domain>0</domain> <bus>0</bus> <slot>28</slot> <function>3</function> <product id='0x27d6'>82801G (ICH7 Family) PCI Express Port 4</product> <vendor id='0x8086'>Intel Corporation</vendor> </capability> </device>
We're not defining any particular semantics for the driver name, it is just a opaque string following rules of the OS in question.
Looks fine but let's wait after 0.6.4 release to commit, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

Hey, Looks fine to me, but if you're looking for comments ... :-) On Fri, 2009-05-29 at 14:39 +0100, Daniel P. Berrange wrote:
To, also include the operating system driver name.
$ virsh nodedev-dumpxml pci_8086_27d6 <device> <name>pci_8086_27d6</name> <parent>computer</parent> <driver> <name>pcieport-driver</name> </driver> <capability type='pci'> <domain>0</domain> <bus>0</bus> <slot>28</slot> <function>3</function> <product id='0x27d6'>82801G (ICH7 Family) PCI Express Port 4</product> <vendor id='0x8086'>Intel Corporation</vendor> </capability> </device>
We're not defining any particular semantics for the driver name, it is just a opaque string following rules of the OS in question.
The obvious question is "what's this for?" If this is just an opaque string, what should people use it for?
diff -r ec78a5d6c00c src/node_device.c --- a/src/node_device.c Thu May 28 14:42:24 2009 +0100 +++ b/src/node_device.c Thu May 28 16:00:12 2009 +0100 @@ -46,6 +46,60 @@ static int dev_has_cap(const virNodeDevi return 0; }
+#ifdef __linux__ +static int update_driver_name(virConnectPtr conn, + virNodeDeviceObjPtr dev) +{ + char *driver_link = NULL; + char devpath[PATH_MAX]; + char *p; + int ret = -1; + int n; + + VIR_FREE(dev->def->driver); + + if (virAsprintf(&driver_link, "%s/driver", dev->devicePath) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + /* Some devices don't have an explicit driver, so just return + without a name */ + if (access(driver_link, R_OK) < 0) { + ret = 0; + goto cleanup; + } + + if ((n = readlink(driver_link, devpath, sizeof devpath)) < 0) { + virReportSystemError(conn, errno, + _("cannot resolve driver link %s"), driver_link);
Do we really want dumpxml to fail for this?
+ goto cleanup; + } + devpath[n] = '\0'; + + p = strrchr(devpath, '/'); + if (p) { + dev->def->driver = strdup(p+1);
basename() ? (you already use basename() in storage_backend_disk.c)
diff -r ec78a5d6c00c src/node_device_hal.c --- a/src/node_device_hal.c Thu May 28 14:42:24 2009 +0100 +++ b/src/node_device_hal.c Thu May 28 16:00:12 2009 +0100
Probably should add a FIXME in node_device_devkit.c about adding support for this. Cheers, Mark.

On Wed, Jun 03, 2009 at 12:43:36PM +0100, Mark McLoughlin wrote:
Hey,
Looks fine to me, but if you're looking for comments ... :-)
On Fri, 2009-05-29 at 14:39 +0100, Daniel P. Berrange wrote:
To, also include the operating system driver name.
$ virsh nodedev-dumpxml pci_8086_27d6 <device> <name>pci_8086_27d6</name> <parent>computer</parent> <driver> <name>pcieport-driver</name> </driver> <capability type='pci'> <domain>0</domain> <bus>0</bus> <slot>28</slot> <function>3</function> <product id='0x27d6'>82801G (ICH7 Family) PCI Express Port 4</product> <vendor id='0x8086'>Intel Corporation</vendor> </capability> </device>
We're not defining any particular semantics for the driver name, it is just a opaque string following rules of the OS in question.
The obvious question is "what's this for?"
If this is just an opaque string, what should people use it for?
To determine what driver is associated with a device.
diff -r ec78a5d6c00c src/node_device.c --- a/src/node_device.c Thu May 28 14:42:24 2009 +0100 +++ b/src/node_device.c Thu May 28 16:00:12 2009 +0100 @@ -46,6 +46,60 @@ static int dev_has_cap(const virNodeDevi return 0; }
+#ifdef __linux__ +static int update_driver_name(virConnectPtr conn, + virNodeDeviceObjPtr dev) +{ + char *driver_link = NULL; + char devpath[PATH_MAX]; + char *p; + int ret = -1; + int n; + + VIR_FREE(dev->def->driver); + + if (virAsprintf(&driver_link, "%s/driver", dev->devicePath) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + /* Some devices don't have an explicit driver, so just return + without a name */ + if (access(driver_link, R_OK) < 0) { + ret = 0; + goto cleanup; + } + + if ((n = readlink(driver_link, devpath, sizeof devpath)) < 0) { + virReportSystemError(conn, errno, + _("cannot resolve driver link %s"), driver_link);
Do we really want dumpxml to fail for this?
This would only fail if the kernel had created a broken symlink, so I think its fine to return an error here. We already check for whether it actually exists just before.
+ goto cleanup; + } + devpath[n] = '\0'; + + p = strrchr(devpath, '/'); + if (p) { + dev->def->driver = strdup(p+1);
basename() ?
Basename isn't a very nice function becasue it potentially modifies the original string.
(you already use basename() in storage_backend_disk.c)
Didn't notice them - one of them is definitely risky due to the potential for modification of original string. Need to kill those IMHO
diff -r ec78a5d6c00c src/node_device_hal.c --- a/src/node_device_hal.c Thu May 28 14:42:24 2009 +0100 +++ b/src/node_device_hal.c Thu May 28 16:00:12 2009 +0100
Probably should add a FIXME in node_device_devkit.c about adding support for this.
Yeah, the devkit.c driver is just sooooo incomplete, mostly reflecting the inadequacies of device kit itself. Not really sure where togo with that. It is verging on being better to kill this junk and just talk to udev directly, because I'm told the info that's missing won't be added that they we need to fetch it from sysfs ourselves. Talking to devicekit for just a small part of the data is looking like a waste of time. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
participants (3)
-
Daniel P. Berrange
-
Daniel Veillard
-
Mark McLoughlin